I’m trying to design the shell of an RTS and I’m working on the selection box. Basically, when I click and drag I’m using Open GL to draw a box from where the click began to where the mouse was released. This works fine, except for one case. When hovering the mouse around the sides of the screen, say the left side, the camera scrolls left. However, since the box-drawing is based on screen position and not on world locations, the box stays the same size throughout the scroll. What I would like is for when the screen scrolls left for the rightmost boundary of the box to move right, to compensate for the scrolling screen. I tried implementing a counterbalance into the scroll script that changed the position of the start-point (say, moves it right when the screen scrolls left) but ran into a problem. I’m moving the camera by unity units and would have to move the start-point by pixels. How would I make this conversion?
Basically, the orthographic camera uses the size of 1/2 of its total VERTICAL size in units:
in other words, let’s say my camera has an orthographic size of 100 and the Screen.height is 1000. for every 1 unit I move my camera along the y-axis, that is equivalent to 5 pixels (because size is HALF, remember).
In other words
desiredPixelDistanceVertical = (Screen.height / (camera.orthographicSize * 2)) * unityUnitsMoved_y;
At least I think that sounds right…
for the VERTICAL.
(note the horizontal distance would depend on the aspect ratio, so you would need to use that as well for horizontal)
I guess that would be like
desiredPixelDistanceHorizontal = (Screen.height * aspectRatio / (camera.orthographicSize * 2)) * unitsMoved_x;
The way I would approach this is to store the initial and current mouse positions in world space (this is the intersection of the ScreenPointToRay ray and either the terrain or the Y=0 plane), then project those points back into screen space for drawing (using WorldToScreenPoint). This would account for a perspective camera and any rotations as well. Just be careful to account for the case when points move behind the camera, if that can indeed happen.
I had trouble implementing fast unit selection (slows for > 100 units), especially considering both units and the selection box are moving/animating. I had success dynamically creating a cube triangle mesh in “clip space” (divide mouse pos by screen size, scale by 2 and subtract 1 to give a -1 to 1 range) given by the selection area, projecting that into camera space (multiply vertices by camera.projectionMatrix.inverse) and creating a collider with it, parented to the camera. Using OnTriggerStay on the mesh object was slow but least buggy. Using physics layer masks is a must - if your characters have complex colliders you could create selection colliders in a separate layer.
Each frame units entering/exiting the selection can be found from the difference of the current selection set and a stored previous selection set.
Here’s a screenshot of the selection mesh from a different camera angle: