- Home /
Selecting objects in arbitrary 2d space using only arrow keys
Say I have a set of objects shown in the diagram. I start out somehow by auto selecting the lowest left object, A.
Then, if I were to press the up button, B would become selected. Since it is the nearest object in the upward direction. Likewise, if I were to press right while at A, then C would become selected.
I don't know how to code this.
Answer by macsimilian · Feb 27 at 03:34 AM
Answer from reddit post: https://old.reddit.com/r/Unity2D/comments/swpuar/how_to_select_objects_in_arbitrary_2d_space_using/
This is probably a bit suboptimal, but you could try this:
Suppose you press the right key. Now you get a list of all the objects to the right of the one that is currently selected. Exclude those that are outside the 90° angle centered on the right-pointing vector (the math here is rather simple I think, you just have to compare the x and y deltas) and then just pick the leftmost one.
This has the downside of being unable to choose an object if it's the only one to the right but it's outside the 90 degree angle, so you would have to press a different key to get it. You could fix that, if you want, by removing the 90 degree rule if there is only one object in the initial list of candidates, just automatically choosing it instead.
So, algorithm:
get all objects to the right
if there are none - do nothing, done
else, cycle though the objects in the list and compile a new list of ones that are inside the right-pointing sector (by comparing x and y deltas; remember to use >= to avoid losing perfect diagonals)
if 3 is empty, just select the leftmost one
else, select the leftmost of those you have picked in 3, done
4 is required if you want to be able to select something new even if the candidates are way out of the way, like 1 pixel to the right and then all the way down. If you're comfortable not selecting those - end the function on that step instead of selecting anything.
Edit: you can also play with the angle to expand the selectable area, if 90 degrees proves too restrictive.
This seems like it will work, thank you! I was actually thinking of something like this, except with doing some sort of 90 degree triangular raycast, and then choosing whichever it hits first. But there isn't a triangular raycast. However, a raycast isn't necessary. I like your idea of just making a list of all the objects inside a triangular area, and then choosing the closest one from those. Doing at least 90 degrees is important, since this divides the space into 4 quadrants, with no point excluded.
I would revise "leftmost" in step 5 though. Instead, I would look for the overall nearest point. This turns that theoretical triangle cast to have a rounded edge. See diagram.
Pressing right at A should go to C. Only looking at the x axis distance would cause a conflict between B,C,D.
Also I really appreciate the edge case covered in 4. I think I can code this now, thank you!
raycast
I'm only familiar with unity raycasts in theory, but I think this isn't the case for them. Simple math is more than enough here :)
Doing at least 90 degrees is important, since this divides the space into 4 quadrants, with no point excluded
Yep. I suggested you look into using wider angles to maybe make the user experience a little better. This will make the objects located in the angle overlap selectable by 2 keys, not just 1.
I would revise "leftmost" in steps 3-4 though. Instead, I would look for the overall nearest point. This turns that theoretical triangle cast to have a rounded edge. See diagram.
Good call! My morning brain didn't catch this. Also, you should take special care of the case when 2 or more objects are equally distant - it's not obvious which one you should pick, since their location can still affect your decision making.
Happy coding!
Answer by arrowmaster1252 · Feb 19 at 02:31 AM
If its like a button in ui an easy solution would be to change navigation to explicit in the script for it that allows it to be selected (like the button script).
If its an object not in UI make a script (or edit existing select script) and make a variable for what is selected with each arrow key.
If they are randomly placed you will have to change those variables via code, so get an array of them all and check which one is closest within certain peramaters (like above the object or whatever). You will likely have to use a foreach loop for each object.
If you would like more help you could discord me at ArrowMaster#7071
Sorry if the example was confusing, there are many more than 4 objects to select. And the selected object depends on what was previously selected. So what I am asking for is essentially a script that can find "nearest left" or "nearest up" etc. Sorry if this wasn't clear before, but your answer seems to be assuming I'm simply binding 4 objects to 4 keys, which I'm not.