Hello all - first post here. Lets get down to it 
I have a list that contains all the current units in my game world. What I’m trying to achieve is to take the current GUI mouse position, create a REct based upon the distance dragged and use its Contains method to check against all my game units to see if we’ve selected any (I know, so many posts on the forum concerning this - but none seem to help me).
I am aware of the differences between GUI, Screen coord systems but still cant quite figure this out.
I am using Event.current.mousePosition to get my mousing in the OnGUI event and doing this when trying to check for selection:
private void TrySelectionBox(){
//this is for getting the width, height of RECT
float width = currentMouse.x - startMouse.x;
float height = currentMouse.y - startMouse.y;
//color of selection texture
GUI.color = new Color(1.0f, 1.0f, 1.0f, 0.70f);
//create rect here
Rect drawRect = new Rect(startMouse.x, startMouse.y, width, height);
//draw texture
GUI.DrawTexture(drawRect,healthBar, ScaleMode.StretchToFill);
foreach(Unit u in GameManager.GameUnits){
Vector3 worldToScreenPoint = Camera.main.WorldToScreenPoint(u.transform.position);
if(drawRect.Contains(worldToScreenPoint)){
print("Selection contains: " + u.Name);
}
}
}
I am getting selections, but like all the other posts out here, its just not quite right
I have to select below the unit to actually get it to select which tells me its that darn screen vs GUI coords discrepancy but I just cant get it!!! I hope someone can shed the light on my issue here
Thanks so much
3 Answers
3
I think what I’d do is create two raycasts from screen to world - one at the start location of the drag rect and one at the end location of the drag rect.
Then, take the intersections (with the ground) and use the locations to create a box collider with edges that match the cast. Following that, test collision on the box to get a list of everything that collides with the box.
Typical of RTS’s is that a box dragged downward selects only those units fully inside it while boxes dragged upward select units that are inside OR cross the boundary of it.
This solution I propose handles the last (crossing or within) - to get the first, you’ll need an additional step of looping through all the units and seeing if their leftmost, rightmost, topmost and bottommost coordinates are all within the coordinates. If so, you keep them. If not, they’re partially outside and you drop them.
This solution has an additional benefit in that you can make the collider visible (by adding a mesh at the same location) and see the selection in 3D.
And yes, you can make the box be aligned with the camera so that it seems more 2D than it is.
http://wiki.unity3d.com/index.php?title=CameraFacingBillboard
I think your underlying problem with your initial approach is that you are trying to use Event.current.mousePosition and believe that it is in screen coordinates. It is not. The GUI system does all sorts of weird layout stuff to do with positions and rectangles and you have to convert it’s coordinates into screen coordinates using GUIUtility.GUIToScreenPoint.
It seems reasonable to me to convert unit positions to screen positions and then check your selection that way.
What I did for the above was give the objects in question a specific tag (in this case “selectable”) I then created an array of all selectable objects in the scene and then checked if a raycast of it’s screen co-ordinates fell inside the box.
I’ve just cut out the specific bit in question but this is the code I implement:
void Update() {
if(Input.GetMouseButtonDown(0)) {
start_box = Input.mousePosition;
}
if(Input.GetMouseButtonUp(0)) {
end_box = Input.mousePosition;
makeBox();
GameObject[] csel = GameObject.FindGameObjectsWithTag("Selectable");
for (int i = 0; i < csel.Length; i++) {
Vector3 objectlocation = Camera.main.WorldToScreenPoint(new Vector3(csel<em>.transform.position.x,csel_.transform.position.y,csel*.transform.position.z));*_</em>
* //If the object falls inside the box set its state to selected so we can use it later*
* if(boundbox.Contains(objectlocation)) {*
_ csel*.SendMessage(“setisSelected”, true);
}
}
}
}
private void makeBox() {
//Ensures the bottom left and top right values are correct*
* //regardless of how the user boxes units*
* float xmin = Mathf.Min(start_box.x, end_box.x);
float ymin = Mathf.Min(start_box.y, end_box.y);
float width = Mathf.Max(start_box.x, end_box.x) - xmin;
float height = Mathf.Max(start_box.y, end_box.y) - ymin;*
* boundbox = new Rect(xmin, ymin, width, height);
}*_
Just draw everything for debugging purposes ... use Debug.DrawLine and the other Debug. commands (Look at the documentation page for Debug). (The "gizmo" commands can also be helpful.) 90% of the code I have ever typed out in Unity is "Debug.DrawLine ..." - exaggerating for humour but you get the point, it's totally central to doing things like that in Unity. It is one of those situations "If you teach a man to fish..." BTW you don't make clear WHAT the heck you're doing .. is this a 3D game, what "are" these units etc ? Cheers
– FattieFattie - thx for the reply. This is a 3D game.A "Unit" is a soldier in this case. I'm attempting the typical RTS. Want to create a multi-selection box with mouse coords - same old story. Everything I've seen out here uses raytracing for detection, but I thought it might be easier to do it this way? Is that enough? thanks agin
– DirgMcCuneFattie: I'm trying to do an isometric-style game so the cam is offset. I'm currently drawing the "selection rectangle" in the GUI then attempting to convert tose coords to world and determine if the soldier units are within the rect created by the mouse-drag. So how would you create rays for EVERY single place that would fall withing a given rect? there has to be a better way to go about it, right?
– DirgMcCuneoopos - just FYI - I noticed that I hadn't replaced "WorldToViewportPoint with WorldToScreenPoint. Either way, this still doesn't work.
– DirgMcCuneMan I'm really trying to help someone help me! Here's another screenshot of my craziness: ![alt text][1] [1]: http://dl.dropbox.com/u/16876550/Screen%20Shot%202013-04-10%20at%205.36.03%20PM.png So my coordinates are flipped - You can see my selection box up at the top and the very bottom of the console reads "Selection contains PLAY 0...". So the question is how the heck do I get them right!??? Thanks to all super heroes out there :)
– DirgMcCune