How do I properly implement tickable UObject?

Hi,

currently implementing character attributes using UObjects, attributes are presumed to be changed a lot during the game, like stamina, which decreases while character runs. So i need attributes to tick. I’ve inherited attribute class from FTickableGameObject, not really sure if that’s the right way to do this, but i had something working.

Attributes were placed in TMap and tick was handled, though it was ticking in editor all the time as well as i found out just few minutes ago. Also had some really weird bug when attribute values was set to something like -193752392, just put random values after -19. Log still was outputting values as their max value(i clamped value in tick), but on HUD it was displayed like above. So i though it might happen because i didn’t use UPROPERTY() on TMap. But TMap is not supported with UPROPERTY() as i see, so i used TArray instead.

[2014.05.07-17.27.53:712][782]LogAlone: Attribute Health value - 100.000000. Owner - /Script/Alone.Default__AlonePlayerCharacter
[2014.05.07-17.27.53:712][782]LogAlone: Attribute Stamina value - 100.000000. Owner - /Script/Alone.Default__AlonePlayerCharacter
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Health value - 100.000000. Owner - /Game/Characters/Player/BP_Player.Default__BP_Player_C
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Stamina value - 100.000000. Owner - /Game/Characters/Player/BP_Player.Default__BP_Player_C
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Health value - 100.000000. Owner - /Game/Characters/Player/BP_Player.Default__SKEL_BP_Player_C
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Stamina value - 100.000000. Owner - /Game/Characters/Player/BP_Player.Default__SKEL_BP_Player_C
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Health value - 100.000000. Owner - /Game/Maps/UEDPIE_0_Default.Default:PersistentLevel.BP_Player_C_0
[2014.05.07-17.27.53:713][782]LogAlone: Attribute Stamina value - 100.000000. Owner - /Game/Maps/UEDPIE_0_Default.Default:PersistentLevel.BP_Player_C_0

After some play time attributes stop to tick in PIE and tick only in owner - /Script/Alone.Default__AlonePlayerCharacter

According to the above log, objects tick in CDO and PIE objects. How to restrict FTickableGameObject from ticking in CDO, or, it would be better to implement ticks via FTickFunction?

Thanks in advance!

P.S. I saw question about FTickableGameObject but there is no useful information, it was about properly overriding methods :slight_smile: Also question name might be little bit misleading.

1 Like

FTickableGameObject is probably the right way to go about this. The fact that the CDO is ticking isn’t ideal, but there probably is no reasonable way for us to you to put default behaviors in that will filter them out (that I can think of off the top of my head), but you can override the IsTickable function yourself to filter out the CDO using IsTemplate().

1 Like

Thank you, that helped. But objects still suddenly stop to tick after some play time… not sure what it might be, getting GC collected automatically?

Currently it’s declared this way:
TMap<FString, UCharacterAttribute*> Attributes;

Also tried declaring with UPROPERTY as TArray, as i stated before, but it didn’t change anything. There is no information being print to log once it happens, properties are marked with UPROPERTY, except the map, so i really have no idea…

Thank you for the reply :slight_smile:

GC seems like the most likely candidate. You can force GC to occur with the console command “obj gc” and if they stop ticking exactly then that is your problem.

If your UCharacterAttributes are not referenced by anything other than the map then you will definitely need to get them referenced. Obviously UPROPERTY on the TMap doesn’t work (something I would desperately love us to resolve some day), but you can override the AddReferencedObjects function in your class and iterate the map collecting the references. A good example of this is in FAudioDevice::AddReferencedObjects where we collect up the USoundMix references.

However, since you mentioned that converting to using a TArray with the UPROPERTY didn’t work, that somewhat implies that the containing object is itself not referenced, so making sure that whatever contains the TMap is collecting references too would be important.

Thought about GC at the first place, but also thought UPROPERTY would solve GC related issues.

Attributes do stop ticking after obj gc. It’s quite tricky to find origin of AddReferencedObjects function, even Visual Assist finds it hard :slight_smile: So, trying to override it i’m getting some weird errors.

Error	2	error C2664: 'UClass::UClass(const UClass &)' : cannot convert argument 8 from 'void (__cdecl AAlonePlayerCharacter::* )(FReferenceCollector &)' to 'void (__cdecl *)(UObject *,FReferenceCollector &)'	D:\UnrealEngine4\Engine\Source\Runtime\CoreUObject\Public\UObject\Class.h	2084


Error	1	error C2664: 'bool UClass::HotReloadPrivateStaticClass(uint32,uint32,EClassCastFlags,const TCHAR *,void (__cdecl *)(const FPostConstructInitializeProperties &),void (__cdecl *)(UObject *,FReferenceCollector &),UClass *,UClass *)' : cannot convert argument 6 from 'void (__cdecl AAlonePlayerCharacter::* )(FReferenceCollector &)' to 'void (__cdecl *)(UObject *,FReferenceCollector &)'	D:\UnrealEngine4\Engine\Source\Runtime\CoreUObject\Public\UObject\Class.h	2057

Looks like it exepcct to see UObject class but gets my character class.

Using FAudioDevice as a suggested override may have been a mistake, try looking at AInstanceFoliageActor instead.

AddReferencedObjects is a bit of a tricky implementation technique as it is a static function.

If following the AInstancedFoliageActor pattern for AddReferencedObjects doesn’t get you any further, can you post me the definition of that function?

That was actually what VA X suggested me to override, but it didn’t match FAudioDevice function.

Thank you, everything works fine now. And thank you for fixing ChildActor issue :slight_smile: