How to procedurally spawn an actor on a level, permanently?

Hi,

I’ve pieced together multiple posts to try and spawn or create actors from static meshes, generated from a list in a txt file. It seemed to be be working (100’s of instance are created in the outliner although it I don’t see the meshes yet), however as soon as I hit ESC, all the actors disappear from the outliner. I’ve tried with NewObject, LoadObject, ConstructObject, and spawnactor. They more/less have the same effect. They disappear when the PIE is stopped. How can I make them permanent? I don’t want them to disappear!! I want to save their locations in the .umap…

I’m trying to procedurally generate a level with the hope of saving a .umap to be used with another UE4 project afterwards; I’ve used the basic code template in C++, and my objects are StaticMeshes imported from Blender in FB
X format.

Structure is as follows:
1- Gamemode reads the txt file and grabs the positions (location, rotation,scale) [OK]
2- Gamemode loops through the object names (they exist in the content browser) and triggers a spawnactor on the actor class [OK, I can see beginplay messages] 3- The spawned actor appears in the editor (although invisible for now, for some reason) 4- When I hit ESC, the spawned elements just disappear.

Ideas?

Code

FActorSpawnParameters SpawnInfo;
SpawnInfo.Owner = GetOwner();

AMyActorSpawn* spawnActor = GetWorld()->SpawnActor<AMyActorSpawn>(AMyActorSpawn::StaticClass(),
obLoc,
obRot,
SpawnInfo
);

This kind of procedural creation occurs during runtime as part of the game execution, so when the game stops running it returns to its constructed state. This does not permanently change your level. The ULevel itself (and the .umap file) aren’t ever modified, it’s just executing code to spawn actors within the running level (as you would spawn enemies, projectiles, etc. during gameplay - it would be weird if gameplay permanently added objects to the level by default).

Alternatively, you could create an actor that exists within your level that reads the spawning data and constructs the desired objects, or you could build the spawning method(s) directly into your level; but again, these created objects will only exist during runtime.

You could spawn the objects during level construction rather than after BeginPlay, they would then show up in the editor; but they still don’t exist as part of your level, they’re being spawned within the level as part of the execution of your game.

If you need to store the data in the .umap itself you’ll need to do some work on the editor itself, creating a utility (probably a plugin) that actually modifies the ULevel object, perhaps even creating a custom ULevel class.

You might be able to save a .umap file during runtime, but you’ll still have to see how the editor does that and be sure you generate the paths and data structure the same way UE4 does, otherwise you’ll have untold problems. It’s probably easier to write it as a plugin than as a runtime gameplay element.

Regardless, you’ll need the content assets to have the same file structure within the new game project as in the existing one in order for the levels to load properly.

See:

https://docs.unrealengine.com/latest/INT/Videos/PLZlv_N0_O1ga0aV9jVqJgog0VWz1cLL5f/zg_VstBxDi8/

“it would be weird if gameplay permanently added objects to the level by default”

I totally agree, however, this is the behavior I’m looking for, and I believe (after reading many posts) more people have been looking to do this as well, for procedural functionality/testing. Would be nice to have some sort of flag to keep actors in the scene after exiting the PIE.

I noticed a new option in the FBX importer to recreate objects in the scene, it kinda works, but it creates totally new objects with random names in the Editor, and I ultimately would want to instantiate from components (in this case StaticMesh) that would already be in the content browser, mainly so they’d have a custom name and a bunch of tags, to refer to them later (in another project). And preferably without or with very minimal BP involvement. The goal being the artists could see their objects in the level with the exact name they had in the other 3D design software (in this case, Blender).

As far as the .umap goes, as a workaround, I would not mind saving it myself as a .umap manually after procedural generation is complete.

Thanks for the links and detailed explanation though, I understand a bit more how it works.

“As far as the .umap goes, as a workaround, I would not mind saving it myself as a .umap manually after procedural generation is complete.”

I still think the plugin is the way to go here. You can use the exact same functionality to read in your text file and procedurally create everything, and tie the execution of your procedural generator to a button in your plugin interface. That way you can create multiple instances and offer more options (filename, version numbers etc.) without having to execute the full game code.
The only real difference is that you’d be storing the location and spawn information within the game level, rather than performing the spawn. You’re going to have to write the .umap files the same way as a plugin or as a runtime utility, I just suspect you may run into file read/write collisions or other unexpected behavior if you do it in runtime. It’s also probably easier to distribute to artists if it’s a plugin (if you need them to have it). The extra work will be creating the plugin panel and interface itself, but shouldn’t be too bad. A button, maybe a text input for filenames is all you probably need. And once it’s done you’ll have a platform to expand functionality as needed.

One of the nice things about Unreal is that you can actually look to see how the engine developers did what you want to do and pull their code directly and modify for your needs. If you do go ahead with the plugin, it might be something worth posting on the content marketplace.

Also, check the FBX importer code for the way it reads keywords from the hierarchy (usockets, collision volumes, etc.), you can probably modify it to create the objects using artist-generated names with a similar method.

…cont’d…

…cont’d…

I will add this though, if you don’t need artists to be able to modify the spawned objects in the level, but only need them to be able to see them, it’s going to be easiest and fastest to have the level spawn the objects during level construction, either from the level itself, from a dedicated spawning UObject/AActor. You have all that functionality already, you just need to change when it happens. That will require the least work to get going if that’s all you need.

I hope I’ve been helpful.

Good luck.

Very insightful alternatives, thank you for your detailed reply!

I found also:

So I guess there is no simple way to go about it at the moment…

It’s not so much that the process isn’t simple, it’s just not something you would build into the game code. In both your case and the forum post, you should be modifying the editor to do what you want, or building standalone tools.

What you, and what the forum post you linked to, are trying to build are game design tools. This is the software you are using to build your game; not the game itself; but you’ve been trying to build that functionality into game runtime framework. You’re using runtime spawning methods to create prebuilt game data; they’re not designed for that. The editor is designed to build static game data, so if you model your methods after its structure you’ll have much more (and much easier) success.

Fortunately, Epic has not only given us access to the game engine source, but to the game editor source-code as well; so what you are trying to do is entirely possible; and it sounds like it would be a popular plugin.

Hm, question is old, but maybe someone find it useful. If I get it right, you want to spawn actor in simulation mode (for example) and keep it after you stop the simulation. If it is, then you should add actors to editor level instead of runtime level.

    #if WITH_EDITOR
    	if (GEditor) {
    		FTransform transform; // Set any transform that you want
    		AStaticMeshActor* actor = Cast<AStaticMeshActor>(GEditor->AddActor(GEditor->EditorWorld->GetCurrentLevel(), AStaticMeshActor::StaticClass(), transform));
    		if (actor != nullptr) {
    			actor->SetActorLabel(FString("TestObj"));
    			actor->SetMobility(EComponentMobility::Movable);
    
    			UStaticMesh* Asset = Cast<UStaticMesh>(StaticLoadObject(UStaticMesh::StaticClass(), NULL, TEXT("StaticMesh'/Game/StarterContent/Props/SM_Chair.SM_Chair'")));
    
    			actor->GetStaticMeshComponent()->SetStaticMesh(Asset);
    		}
    	}
    #endif

You can add this to BeginPlay, but you will see this object only after simulation stop. So, to work this right, you need to spawn actor in usual way and on EndPlay create new object in editor level and copy all parameters to this.
P.S. Sorry for my english:)