I’ve been trying to set up a way of polling a non-Unreal remote server for data at a rate specified by the user. With Rama’s help, I used William Gaul’s Sagittarius plugin (https://rocket.unrealengine.com/questions/7592/best-way-to-perform-a-http-request.html) and modified it to suit my needs so far as creating a http request, receiving a result, and parsing it for a value to update an in-game object.
However, when it comes to setting up polling, I seem to be running into an error after some time of my game running in Rocket. It usually happens after 60 seconds (often with ~0.5s variance, on rare occasions ~30s longer), and is independent of polling rate. The error occurs in one of a few ways:
This appears in console, either followed by a hang or no further updates (which I designed in):
LogActorComponent: UnregisterComponent: (/Engine/Transient.ProjectileMovementComponent_0) Not registered. Aborting.
LogActorComponent: UnregisterComponent: (/Engine/Transient.CharacterMovementComponent_0) Not registered. Aborting.
I get an error on attempting to call Http->CreateRequest(), even if ensuring the Http module is available. My URL passed in for the request gets set to null.
The URL becomes unparseable after or during (not sure which) constructing the Http request in lines following CreateRequest() mentioned above. I set the URL once during a call to an Initialise(FString URL) method, and never change it in any code thereafter…
I’ve got a feeing my custom class (derived from AActor) is being destroyed during its Tick function (and, in an alternative I tried earlier, a callback passed to SetTimer()… I tried implementing my own timer via the Tick() function for thread safety, assuming it was the issue) after about 60 seconds, but I can’t see anything that’d be causing that. Any thoughts for troubleshooting this would be welcome!
These errors appear to only be happening when polling continuously with Http.
UObjects (and any derived from them like
AActors), will always be tied to garbage collection as that is how their memory allocation is designed to work. If you create any
UObject and there isn’t a path from “root” to your object by following
UObject pointers/references then your object will most certainly be garbage collected at a time slice specified in the ini file (usually 30 seconds, but maybe Rocket has changed that). There are other ways to control the lifetime of a
UObject, but most are probably beyond the scope of what you are trying to do.
Rama is correct that adding UPROPERTY will work. UPROPERTY would in fact be required in most cases unless you were handling the lifetime yourself (again not usually necessary). UPROPERTY does much more than aid in GC. It provides reflection metadata to the engine about your class (or variable or function via UFUNCTION). This reflection data is also required for replication (non UFUNCTIONs can’t be RPCs, non UPROPERTYs won’t replicate for example).
RF_RootSet is part of a function
AddToRoot, which is one of the more advanced ways to control GC, but not recommended.
Detecting garbage collection in the future can be done by overloading
BeginDestroy() on your
AActor derived class. It should be called when GC has determined it’s about to be killed. At that time
IsPendingKill() should start to report true. During your ticks you may want to guard with that because the object is about to get destroyed and any work it’s doing is probably no long required, assuming its lifetime is working correctly.
Hope this insight helps.
Thank you for the detailed explanation Josh!
I’ve copied what you wrote into my growing UE4 notes database
If your code is in any way based on the code I offered you earlier, originally created by Willlam Gaul,
The problem is that the original UObjects that are instanced during runtime are getting destroyed by Garbage Collection
anywhere you are using new / creating an object, make a reference to that created object and make that reference a UPROPERTY() in your .h file
VictorySagMod = NewObject(this);
Make everything about your code that is a reference to a UObject, and maybe also actors if you are really suspicious of Garbage collection occurring, into a UPROPERTY()
and your issues should be resolved
Thanks again Rama, I’ll give that a crack. I presume it’ll work since you’ve done plenty with your own stuff derived from Sagittarius
Seeing your old question with a similar GC-related issue for UObject-derived classes spawned with NewObject(), I searched up the docs for the NewObject() function. The page I found describes controlling GC by setting object flags while using NewNamedObject() and ConstructObject() to spawn it. I’ll also give that a crack out of curiosity, since I suspect the UPROPERTY() macro sets those same object flags to register the object as, say, RF_RootSet or RF_Standalone, while potentially having other ramifications (eg exposing the member in the editor and blueprints). Making this AActor-derived class as lightweight as possible is a priority since I’m aiming to eventually have up to several tens of thousand instances / derivatives of it instantiated simultaneously, with http requests pooled for certain - likely arbitrarily defined - groups of those instances, the purpose being enabling the player to selectively update them in player-defined / pre-defined groups. Getting past this GC issue is a big step towards that Thanks!
All that said, I’m still curious about why exactly my code-spawned UObject is registered with GC as unreferenced when I can’t see any code to destruct it / release its reference…
has many advantages
in addition to preventing garbage collection
it is also essential for replicating properties that are inside of a USTRUCT()
Let us know if using UPROPERTY() resolves your issue!
Just confirming this did the trick for me. Thanks, Rama!
Could you please mark the check by my answer so people know this issue is resolved?