I tried using the AddToRoot() method to prevent UObjects created with NewObject from getting garbage collected,
and in multiplayer this caused a crash saying that the world could not be cleared.
The crash occurs before the world is reloaded as a listen server, as apparently the world cannot be cleared first due to the AddToRoot() calls.
When you use AddtoRoot(), how do you make sure this error does not occur?
Specifically I encountered this error when using the equivalent of the shootergame code to Host a new game using the Host button from the main menu, after the single player world had already been created, UObjects instanced, and AddToRoot called.
So you could say, about 10 seconds after regular world was loaded and AddToRoot() was called, I tried to host as listen server using the shootergame code.
So you could test this on your end via shootergame and using just AddToRoot on a custom class UObject while in the menu screen, before hosting a game
UPROPERTY() pointer references worked great though!
So that’s currently the only method I can get to work with my game setup where the world will be loaded in single player first, then loaded again when new multiplayer game is hosted
As Alexander alluded to, the problem you are running into is most likely a reference problem preventing garbage collection from cleaning up your world object when it needs to reload your level (like when you restart as a listen server).
Using AddToRoot() is a good, quick solution for preventing your object from getting garbage collected, but deciding when to destroy that object gets complicated when you reference it in other places, like as UProperties of other classes, and the end result is quite possibly a circular reference in which two objects should be deleted, but they both reference each other and thus will not be garbage collected.
If the object in question is also referenced by UProperties in other classes, is it really necessary to call AddToRoot() on it? As long as there is always at least one reference to it from another object that exists, it won’t be garbage collected.
Another option is, if this is some kind of global object that many classes share, instead of calling AddToRoot() on it, you could create an instance of it and store a UProperty reference in a globally accessible place like GameMode or GameState. Then you can get that reference in the functions of the other classes that need to access this object by calling a function in GameMode or GameState that returns a reference (really just an application of the singleton pattern).
Hopefully one of these alternatives will fix your problem.
"If the object in question is also referenced by UProperties in other classes, is it really necessary to call AddToRoot() on it? "
Thanks Joe, no it’s not really necessary, I was just testing options, and so this is not really a bug report, I was just wondering how to use AddToRoot() correctly, but using UPROPERTY() seems a lot more versatile and also stable
“Another option is, if this is some kind of global object that many classes share, instead of calling AddToRoot() on it, you could create an instance of it and store a UProperty reference in a globally accessible place like GameMode”
The error about the world not being cleared is caused by your custom UObject that you added to root is probably referencing an object that is in the UWorld.
Is it just one custom UObject class that you are calling AddToRoot() on or multiple? Could you provide us your .h and .cpp files so we can further investigate the issue?
// Copyright 1998-2013 Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Example.generated.h"
UCLASS()
class AExample : public AActor
{
GENERATED_UCLASS_BODY()
};
.cpp
AExample::AExample(const class FPostConstructInitializeProperties& PCIP)
: Super(PCIP)
{
//Set up Tick for Example
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;
}
void AExample::PostInitializeComponents()
{
Super::PostInitializeComponents();
AddToRoot();
}
The error message upon trying to restart as a listen server after world has already been loaded and post init has run
The object in question is ALSO referenced by UPROPERTY() references in other classes