Okay, so very frequently in my game, I need to perform a check on an arbitrary number of actors to determine something about one of them in relation to the player.
As an example in my current situation, I’m trying to take an Array of actors which have been hit with an attack, determine the Look at rotation between the player and each actor, find which of these possible Look at rotations is the closest to the actor’s current rotation, and set it to a rotator Var.
My instinct so far in situations like this has been to use a second array. What I do is run a ForEach loop on the first array to perform some math which can reduce each index to a simple float between 0 and 9999999 (i.e. Find look at rotation, delta rot between that and the current rotation, break to yaw, abs yaw), then set it on a SECOND array at the same index number, and use the Min (or Max) of Float Array node to find the appropriate index value.
But this seems inelegant and also like it creates a lot of unnecessary arrays… I feel like I’m missing some obvious solution for this? Is there a better way to, for instance, compare all rotators in an array to determine which one is closest to a given rotation? Or vectors? Etc.
You should be able to use a foreach loop through the array and do a branch afterwards. The condition will be if the array element >= (or <=, or ==, etc) a rotator you set. If true, do X function, if false, do y function or do nothing.
That doesn’t exactly help… the problem is, I’m trying to compare each array value to ALL OTHERS in the array.
What you describe would work well for determining IF each element of an array was, say, close to a given value. But it doesn’t let me determine WHICH is closest to that value, at least not that I can determine.
I suppose I could multi-set the new variable in question… like, for each value, set the new rotator var to itself IF it’s closer to the actor rotation than the current value? But I sort of wonder if that’s actually more efficient than what I was currently doing.
your situation, a C++ implementation with space partitions would get you best performance( use whatever cost cheap to update), otherwise it’s a O(n^2) compare to get closest lookat rotation for each actor. using a partition even without fast update can be cost effective after you have large amount of actors.
OR, if it’s not important for accuracy, develop some hacky way to solve it, what game design is about, is getting good enough result but fast. like only doing a few sweep trace, only compare with in meaningful distance, etc etc.
Honestly I’m not SUPER concerned about performance. This function doesn’t tick, it only fires once per attack (at the very end), and we’re talking about AT MAX like 5 possible values to compare, and in most cases only 2 or 3.
I’m not so much concerned with slightly unoptimized solutions as I am with the elegance of the whole thing; creating a second Array of floats seems like it invites problems with residual values sometimes, setting the rotator Var frequently while searching for the correct value might result in odd behavior if it’s set multiple times in a row at the wrong moment, etc.
I’ve learned the hard way with this project that inelegant solutions lead to phantom bugs that are difficult to track down. I can use these approaches if I need to but I’m really surprised there isn’t a better way to compare values in an array apart from the min/max for float and int arrays…
If you’re just comparing “entities to player” then it’s not O(n^2) but “only” O(n), because entities don’t need to compare to each other.
A spatial partition will not help with this problem, assuming you still need to actually check each entity. Spatial partition in general turns O(n^2) problems into O(n lg n), but this is not a O(n^2) problem.
I would keep a variable for “best found entity” and “best score” and iterate over all the entities and calculate their scores. Inside the loop, if the score is better than the previous score, update the score, and set the “best found entity” variable to that entity. When the loop is done, the “best found entity” variable will be the entity with the highest score.
If your criteria is “looks in the same direction as the player” or “looks towards the player” then a simple dot product between two unit vectors would be a good score – closer to 1 means higher score.
Note that min/max for float and int arrays are still O(n) problems, just like the above solution.
Jwatte: thanks for the explanation. That is, effectively, what I was originally going to do with the secondary array. I suppose that’s just about the best approach available for this, then.