Given using the Get All Actors Of Class node is an expensive operation, would it be better to perhaps have a variable keep track of the number of crystals collected? Decrementing then checking the an integer might be cheaper.
I wonder what Epic means by “slow”. Does it depends on the total number of actors in the level, or the number of actors matching the request? And how slow are talking about, a “avoid-calling-it-all”, or “avoid-calling-at-every-tick”, or “avoid-calling-it-multiple-times-at-every-tick”?
I doubt that it’s a problem in a game such as CrystalCavern though, unless you add hundred of crystal and/or you map is more an openworld level than a puzzle level.
Decrementing is an option. But if your game allows creating crystals (e.g. when opening a chest), or if they are other ways of removing crystals (e.g. shooting them), you need to remember to update the counter in all those places. If you count the crystals instead, you don’t need to worry as much about it.
An in-between option is to keep a list of weak pointers to crystal objects (if the engine allows that kind of structure), and checking if there are any weak pointer still valid. That way you don’t need to query the world each time, and still be able to destroy/remove the crystals without worrying about updating the counter.
And in UE 5.1, there will be the option of using Mass Entity, which specializes in querying/tracking objects with specific properties, and thus make counting the crystals very cheap.
I think it’s fair to say that it depends on the use case. On something that’s of the scale that Crystal Cavern is, it’s probably appropriate to use it. But for a much larger game, you’d have to make a judgement call.
Certainly using a counter variable may be cheaper, but could wind up being far less elegant and prone to error should the game become more complex. I suppose creating a game design document might be helpful in making those kind of decisions before implementing them. Provided you don’t deviate too far from the original plan.
My approach is usually:
- keep things simple/readable/expressive first. Choose something that you think is more performant only if it is as simple/readable/expressive as the less performant one.
- profile your app/game to find the bottlenecks and see if your choice is a problem. Often enough, bottlenecks are not where one expects them. Only then replace the simple code with something more complex.
There are exceptions to (1) of course, based on experience in what is usually a bottleneck, e.g. use a hashmap/dictionary instead of an array when a collection of item often needs to be searched often. But even such broad optimizations need to be tinted with a context, e.g. for small collections, it can still be faster to do a binary search in an array rather than using a hashmap.
In this particular case, I’m way too much of an Unreal newb to know how slow
GetAllActorsOfClass truly is. As an experienced programmer though, I suspect it isn’t an issue in a game such as CrystalCavern, otherwise I would think
GetAllActorsOfClass would be pretty much useless/unusable at any time.
Another way to think of (1) is that often developers think “is this way expensive compared to that way”, when really they should be thinking “is this way expensive compared to the overall cost of the app”. Thus, knowing that
GetAllActorsOfClass means one should keep an eye on it, not necessarily avoid altogether.
And to reply to myself:
Actually the documentation does mention it:
This is a slow operation, use with caution e.g. do not use every frame.
This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.