Creating Game Object Properties Via Python

Is there a way to create an object timer property in python? Like own[‘delay’].timerProperty?

I don’t believe you can, as it doesn’t belong to the default python types.
You could easily create a class instance with a property that updates when called. Using the get() method, every time you call


time = myclass.timer_prop_1 

it would update the value. Bare in mind you’d need both the container class as well as the timer property class.

Otherwise, you could write a class with methods like get_time, or a property decorated function that returns the time.

Here is an example of a descriptor version (hacky)


from time import time,  sleep


def unbind(function):
    try:
        return function.__func__
    except AttributeError:
        raise Exception("Function is not bound")


def is_bound(function):
    return hasattr(function, "__self__")


class SpecialProperty(object):
    "Emulate PyProperty_Type() in Objects/descrobject.c"


    def __init__(self, fget=None, fset=None, fdel=None, doc=None):
        self.fget = fget
        self.fset = fset
        self.fdel = fdel
        
        if is_bound(self.fget):
            self.fget = unbind(self.fget)
            
        if is_bound(self.fset):
            self.fset = unbind(self.fset)
            
        if is_bound(self.fdel):
            self.fdel = unbind(self.fdel)
        
        self.__doc__ = doc


    def __get__(self, obj, objtype=None):
        if obj is None:
            return self
        if self.fget is None:
            raise AttributeError("unreadable attribute")
        return self.fget(obj)


    def __set__(self, obj, value):
        if self.fset is None:
            raise AttributeError("can't set attribute")
        self.fset(obj, value)


    def __delete__(self, obj):
        if self.fdel is None:
            raise AttributeError("can't delete attribute")
        self.fdel(obj)
    
    def setter(self, func):
        if is_bound(func):
            func = unbind(func)
        self.fset = func
        return self
    
class InstanceDescriptor:
    def __getattribute__(self, name):
        value = object.__getattribute__(self, name)
        if hasattr(value, "__get__"):
            return value.__get__(self, self.__class__)
        return value
    
    def __setattr__(self, name, value):
        try:
            obj = object.__getattribute__(self, name)
        except AttributeError:
            pass
        
        else:
            if hasattr(obj, '__set__'):
                return obj.__set__(self, value)
        
        return object.__setattr__(self, name, value)    


class Timer:
    def __init__(self):
        self.time = time()
        
    def __get__(self, inst, typ):
        if inst is None: return self
        return time() - self.time
    
    def __set__(self, inst, value):
        if inst is None: return 
        self.time = time() - value       
    
        
class ExampleClass(InstanceDescriptor):
    def __init__(self):
        self.timer = Timer()


a = ExampleClass()


print(a.timer)
sleep(1)
print(a.timer)


a.timer = 0.0
time.sleep(1)
print(a.timer)

Here is a simple property version, but less hidden


from time import time


class ExampleClass:
    def __init__(self):
        self._time = time()
        
    @property
    def timer(self):
        return time() - self._time
    
    @timer.setter
    def timer(self, value):
        self._time = time() - value
     

That’s a to bad you cant use properties in that way. It would be very useful.

you mean a object that keep the time for all objects of the scene ?

if so, you can make a obj that keep the time, call it Time or something .
with a script that run every frame(and calculate the time)

then , from other obj , you call this obj from the scene , and read the time .

objTime = scene.objects[“Time”]

time = objTime[“time”]

I would have liked each object to work independently on its own properties, but it will work.
Thanks =D

Since you took the time to create these I decided to try them out and, it works great! Thanks! I like to look over the code and try to figure out how it works so at first it looked a little intimidating. Still does kinda. I’m still learning how classes work.
Thank you for your help! Thank you for creating these!

That’s kind of you to try them, although I really wanted to see how easy it was. Fundamentally you can never trick C++ into thinking a PyObject isn’t a PyObject unless you explicitly try to do so, so that would always be an issue with debug properties and logic bricks. I wouldn’t try and understand the classes too badly; they’re non-conventional hacking. I took the concept of descriptors, then allowed them to work with instances (using the InstancedDescriptor base class) and then I overwrote the property access mechanism on the game object to call any descriptors if they existed before reading the property.

It is pretty simple. I added the script to my addons folder so all I have to do is import “from timer_lib import Timer, ObjectPatch”
set own = ObjectPatch(own) and your good to go!


import bge
from timer_lib import Timer, ObjectPatch

def main(cont):
    own = cont.owner
    own = ObjectPatch(own)

    if not "timer" in own:
        own['timer'] = Timer()
    print(own['timer'])

Do you need to use this?


if not isinstance(own, ObjectPatch):
    own = ObjectPatch(own)

Yes. That is the only part you “need”. It only needs to (and should only) be run once to setup the object.