I have created a sort of prototype ‘light switch’ that toggles between on/off on custom defined functionality of a specific actor. (Example: Turn a light source on/off)
Currently I am using a complete actor iteration through all actors that exist in the world to find one that has the tag(using UE4s tag system) defined in a blueprint of the custom C++ class and the relevant actor.
I am curious if this is really the best way to do this as it’ll always have to iterate through ALL actors in the world, is there a smarter/better/faster way to get a specific actor or is this just as good of an approach? Any feedback is welcome!
Actor Iterators are very slow. IMO you should only ever use them for prototyping an idea. Storing references to all the lights in the appropriate class is a much better idea (store them as Weak Pointers just to be safe).
If it’s a light-switch, then just create a TArray of ‘ALight’ actors (or whatever the classname is) and mark it as ‘EditAnywhere’. You will then have direct access to the lights in the switch.
But how do you get the reference to the actor that stores the lights in the first place? One would assume you would have an ObjectManagerActor of some kind that you place in your map, then in your GameMode, you would search for that one actor that has all references right? Is there a better way?
The easiest way is to create a pointer / reference in your class which points to the object you’re going to interact with. During level design, when you place the object into the level, you select the object it interacts with. So, if you place a light switch in the level, it has a reference to a light bulb. You place the light bulb into the level and a light switch, and then you tell the light switch about the light bulb by giving it a reference to the specific light bulb you want to toggle on and off when the switch is used.
If you realize that switches can toggle many things, not just light bulbs, then you could create a more abstract implementation using interfaces and just pass in a reference to an actor. If the referred to actor implements the interface, it will do its thing via an interface call. So, a switch attached to a light bulb toggles the bulb on and off, a switch wired to a blender will make the blender blend. It’s up to the individual objects themselves to decide how they want to react when they are switched on and off (ie, how they want to implement their interface call).
Using actor iterator is fine here. Just do it on BeginPlay() and store refs. No performance hits and no need to manually link in editor. For a non-trivial amount of lights it is the only reasonable way to do it.
Example where the player controller needs a reference to an “AreaLightingController”, exactly one of which is in each level. This is also a case where it is not possible to manually link things in the editor - player controllers don’t exist until the game starts.
for (TActorIterator<AAreaLightingController> ActorItr(GetWorld()); ActorItr; ++ActorItr)
_areaLightingController = Cast<AAreaLightingController>(*ActorItr);
LOG("APrimaryPlayerController: GetAreaLightingController(): controller found!");