Hot reload and UWorld asset

Hello,

I made a special asset type that inherit from UWorld and is loaded during the game to get some datas (use actors in it as template to load other actors). It works well, but when I use the hot reload system, the asset class is re-instanced and, during the construction of the CDO (I believe) and the UWorld being not initialized, it cannot pass the check(PersistantLevel);

PostDuplicate is called and the PersistantLevel being null, it crashes :

void UWorld::PostDuplicate(bool bDuplicateForPIE)
{
	Super::PostDuplicate(bDuplicateForPIE);

	TArray<UObject*> ObjectsToFixReferences;
	TMap<UObject*, UObject*> ReplacementMap;

	// If we are not duplicating for PIE, fix up objects that travel with the world.
	// Note that these objects should really be inners of the world, so if they become inners later, most of this code should not be necessary
	if ( !bDuplicateForPIE )
	{
		**check(PersistentLevel);**

		// Update the persistent level's owning world. This is needed for some initialization
		if ( !PersistentLevel->OwningWorld )
		{
			PersistentLevel->OwningWorld = this;
		}

I cannot find a workaround about this. Should I make some flag somewhere ? Should I use something else than a UWorld to stock actor datas (transform + individual properties) ? It will implies lot of work to do again, but it still is a solution.

Thanks for any help you could bring !

Well obviously PersistentLevel is lost somewhere. What functions of UWorld did you override?

I didn’t override any function, I just add more variables in it.

I tried to override PostDuplicate to cancel its call when PersistentLevel is null, but it just crash in another place and I think it will may cause some stability issues.

So the only difference I see with UWorld is that my class is loaded as an object during the game (not as a map). Maybe the problem from here but I don’t know what to do to solve it…

You extending UWorld just to add some varbales, what those varables are for?

Just to keep references on main actors I want to use as template (so it is just an array of AActor*), but I could do without it. I mainly used a UWorld to keep trace of the actors and theirs datas.
If I remember correctly, I got a error due to a like “Graph is linked to private object(s) in an external package” when I inherit from UObject instead of UWorld. It seems that UWorld are managed differently and allows the saving of actors.

No it’s not managed diffrently, all object are treaded equily, not to mention all objects are inheret of UObject

Did you place “public:” before varbale declerations?

Alternaticly you could use AGameMode, i never heard anyone extending UWorld to keep some central varables

I set my variable in public.
I forgot to say that I made a custom editor window (with a viewport) for this special asset, in which you can place actors and set them up individually (it is to create wave patterns for a shoot’em up game). The game will only load the asset and spawn the wave thanks to its data. It works well, but I have this issue and it will be very disappointing to not be able to use hot reload anymore.
Do you think I can use AGameMode to save/load actors and theirs datas ?

ahhh then store the data in asset class it self, make it UPROPERTY() and it will be saved when saved

That was the first thing I tried, but if I create an UWorld in editor, make some spawns/change then make some pointers from my TArray< Actor* > setup on my spawned actors will be a problem, as the UWorld is temporary.
Is it possible to do something like :

MyActorDatas = NewObject<Actor>();
StaticDuplicateObject(SpawnedActor, MyActorDatas, ...)

to save all the datas ?
I don’t have UE4 on my current computer, I will give a try tomorrow.

The final objective being to have an actor I can use as a template during the call to UWorld::SpawnActor() in game.

Ok so this wave data and you got viewport to operate info about it? and you want to edit state of those actors?

Btw this crash happens in your instance of UWorld for that preview window right?

No, it crashes when the type of my wave is loaded. So, it occurs only when I play the game, then hot reload.
During the hot reload, it seems to have some duplicate from the old classes to the new ones or the CDO, I’m not really sure. Then, when UE tries to reload my wave class, the crash happens.
But all is ok with the preview window and all.
Btw, thanks to help me. It’s the kind of hard issue to solve ^^

When you save, close editor open again it crashes too?

I will give a try tomorrow but I think it will

Maybe you should store actor data diffrently, in some kind of struct and try to reconstruct that

Yes, maybe I should create a FArchive and start a (de/)serialization of the actor from that.
I remember that at the very beginning I tried to serialize the actor (Ar << Actors), exactly like UWorld (that is how I went to UWorld later), but I still got this error of “Graph is linked to private object(s) in an external package”. I didn’t understand why UWorld could do it but not my class, so I though that the UWorld was serialized differently (since maps are something very special). Then I made it inherit from UWorld and it worked.
But this time, I may try to stock the transform, then all important properties of the actor and finally make copies of the components. It doesn’t seems to be a clean way but if it is the only one, I will take it.

I made a new project I can distribute to you if you want to make some tries on your side without to prepare all the project. Make a new object “Test Asset > My Asset Factory”, and then, a double click will create a world internally (as I have for my custom editor), make some spawn and tries to save actor in UMyAsset, that just contain an AActor*. There is a simple map with a AMyAssetDumper that require a UMyAsset and tries to spawn the actor. The code to test is in “MyAssetTypeAction.cpp”
I tried multiple solutions but I always have an issue. It can be due to links between the uworld and my asset, between the actor and the world, between the actor and the asset, good at the first save but not the second, make a NewObject instead of SpawnActor, etc.
I cannot find a good combo :frowning:
I will make some research again and if I don’t find any solution, I will stock the actor as we said (transform + component properties)

link text

Hello,

I gave up the idea of saving in UWorld so I made a system to serialize actor script properties and then components properties, using FMemoryWriter and FMemoryReader to fill a TArray< uint8 >. But they don’t support the serialization of UObject*, so if I want to change a mesh in a StaticMeshComponent for example, it won’t work.
So I looked up at the available tools with class inheriting from FArchiveUObject, however I am not sure which class I should use to serialize object references.
Any idea ?

So i assume you trying to make asset which have wave data with unit posiion. why dont you just make struct which will contain UClass* and FVector (maybe FVector2D if it’s 2D) varables, then in asset class you make array with that structures, you mark it with UPROPERTY() and then once you save the asset engine gonna serialize it for you. Once you know how to do your own asset, storeing data is very easy, i don’t get why you have issues with that and why you wanted to store data in some preview UWorld, make preview window read data from asset

I want a perfect clone of an actor customized in a preview scene, that the game designer can fully custom (change the mesh/material or any other property of the actor in the preview scene), save that and reload during the game.
Actually, it works for most of the datas (so the game designer can change its position 2D, as you said) but changing something like the mesh (as it is an UObject*) won’t work.


About the UWorld, imagine you have some code like that :

// In an editor class
FPreviewScene previewScene;
AActor* previewSceneActor = previewScene.()->SpawnActor(...);
MyAsset->Actor = previewSceneActor; // With UMyAsset::Actor having UPROPERTY()
...
// Make some modifications on the previewSceneActor
...

If you save your asset like this. It just won’t work, since you have a link with a private external object. The editor will say to you “Graph is linked to private object(s) in an external package”, and you won’t be able to save. So, at this time, I made my UMyAsset inherit from UWorld, and make some SpawnActor using the preview scene actors as templates to the spawn function. And in this situation, the editor is able to save it without any custom serialization system.


Also, in editor, if you do :

    MyAsset->Actor = NewObject<AActor>(MyAsset/MyAsset->GetOutermost()/CreatePackage(NULL, NULL)/GetTransientPackage()/NULL (I tried a lot of stuff));
// Copy properties from the previewSceneActor to MyAsset->Actor

It will make some internal issues in the engine. In particular in the UEditorEngine::Tick that will try to update your actor (I don’t know why, but it seems that FActorIterator success to find a way to my actor) in will crash in a check done by TActorIteratorBase(l:250-253). I didn’t have enough debug information to see accurately what was the problem but well, I didn’t find any workaround too.

If you want to create actor you need to create class of it with modified defaults, you need to do something that blueprint do, or extra editor (you can add action i think) for pawn blueprints