Level instance workflow

thanks for the explanation. you were pretty clear actually.

as soon as you have actors that don’t behave genericly. generic structure are not ideal. that’s just a logical rule. so that’s the start of your issues. let me see what i can suggest.

imho i would use a manager to spawn those entities. specially if they are interactive.

these systems, i’m gonna mention, are very complex so quite possible they are overkill, but you might wanna look at pcg and mass system.

not ideal in my book.

unfortunately i can’t recall exactly. but i’m sure you’ll find it. it’s bound to have caveats too.

a quick search in ddg had this as a first result

which gives you a few alternatives. so it’s definitely easy to search. i do recommend to make a few searches.

push or pull refers to the direction of the intention, initiator, and data. if the manager tells the actors which data to use, it’s push. if the actor asks the manager, it’s pull. but since you have the issue detecting loads, a push is hard. so maybe pull is more natural. for things you can control, using push is preferable, for async things you end up using pull.

indeed. you should focus on that. which leads me to think that you might be approaching the problem in a not-ideal way.

i don’t think the levels solve much, but can be used as help.

yeah, it’s unfortunate that the actor label gets stripped on builds as it’s pretty useful. i was forced to implement my own label. i think that might be a good option for you. these objects of you have enough special behavior to make a base class a reasonable option.

in my game i have tons of interactives. and they use their labels to get the data they need. or to notify their events. but i also have other means.

the problem is that the label will be unique in the level, but not across the instances, so you might need to use LevelName + ActorLabel to get an unique id.

another option is to use something like custom primitive data, maybe you can store an id. but it’s going to be the same issue with uniqueness.

level streaming is one of those things that is poorly exposed to bps. in cpp you’ll get much more options.

like this.

LevelStreamingDynamic* const Stream = ULevelStreamingDynamic::LoadLevelInstanceBySoftObjectPtr(
    O, Level, Location, Rotator, LoadOk);
Stream->OnLevelHidden
Stream->OnLevelLoaded
Stream->OnLevelShown
Stream->OnLevelUnloaded
Stream->GetLoadedLevel()->Actors

beware that Stream→SetShouldBeVisible determines if the level is considered fully loaded and blocks beginplay on its actors or smth. so it has caveats.

you can also do

UGameplayStatics::LoadStreamLevel(O, Name, MakeVisible, Block, LatentAction);

that last param allows you to subscribe to an onload delegate

i recommend to take a bit of time to learn the diff between streaming levels and instanced levels because the naming is a bit confusing at first. they end up using similar code in the background though. so global delegates might work with both.

i really think there should be a better way but i haven’t thought of one. having that level of interaction in a level instance sounds not ideal to me.

i’m inclined to have a manager that spawns these groups you want. and try to compartmentalize these groups in bps somehow. maybe have the bps spawn the children they need. you can use childactors for that too.

then have a data table, structure, or helper actors (e.g. aInfo actors that work as markers which you then do a getallactorsofclass and spawn. or you can make the marker actor self transmute into a new instance of such bp (eg spawn and destroy self)).

you can either have the manager tell these markers what to spawn. or you can set the data on these lightway markers. you can use a data table and store a name. or use data assets and store a (soft) ref.

a manager and dynamic spawn will also make it easier to optimize and dynamically load (like the mass system does for example).

but it will have some impact in your workflow. so it’s worth trying, testing, and consider. both will. your approach right now will limit your design. so if your team really wants to do weird things, it’s going to be a constant argument with the team and everyone will be unhappy, it happens too often. on the other hand, it might be the simpler to implement and maintain, if the design doesn’t change.

good luck, keep it up!

1 Like