Mouse Marquee Selection and Other Mouse Actions

Hey everyone. I’m new here. I did a search for this kind of topic, but haven’t been able to find anything.

I am on a team that is building a 2D game in Unity that needs functionality to select an individual or a group of creatures and direct them towards points on the screen.

My main question is…is the mouse marquee selection even possible in Unity? I’ve looked through pages and pages of mouse scripts, and can only find click up and down, mouse over, that kind of thing, on individual objects, not group selection.

My sub-question is…in order to make the entire screen click-able with the mouse, would a good way be to create a transparent background plane that would field all mouse clicks that don’t land on 2D platforms or objects?

And my final question is…I’ve downloaded a SpriteManager that I found here on the Unity Community site. Are there any more good 2D resources that would be helpful?

The answer to this ‘is it possible’ question is pretty much the same as the answer to almost every ‘is it possible’ question, and that is: of course it is, although if the functionality isn’t available ‘out of the box’, you’ll likely have to code it yourself.

Marquee selection is something you’d have to code yourself. For a 2-d top-down game, it’s pretty straightforward; for isometric or 3-d a little less so, but still not too difficult. (If you need some tips on how to implement this, feel free to ask.)

Yeah, that actually seems like it might be a pretty reasonable way of ‘catching’ click events that don’t fall directly on a ‘selectable’ object. (It’s not the only way to do it, but it seems like it might work).

Thanks for the reply. :slight_smile:

I would love some tips on a starting point for marquee selection.

I’m not used to scripting environments…my coding skills are all in XNA (C#) and C++, where interaction between classes, objects and update cycles seems much more intuitive to me.

I think a fairly common solution in Unity is to perform the selection in screen space.

There’s at least a couple of ways to respond to mouse events; one would be to check for these events in an Update() function using Input.GetMouseButtonDown(), GetMouseButtonUp(), and mousePosition.

When a mouse ‘button down’ event is detected, set a ‘marquee’ variable to ‘true’ to indicate that you’re now in marquee selection mode, and save the current mouse position. When a mouse ‘button up’ event is detected, leave marquee selection mode.

While in marquee selection mode, for each update, create a 2-d AABB from the saved mouse position and the current mouse position. Then, use Camera.WorldToScreenPoint() to find the screen-space positions of all objects of interest. Deselect all objects, and then select any for which the screen-space position is within the AABB.

There are various enhancements and possible optimizations you could introduce, but that’s the basic idea.

I and many others also came to Unity from a more traditional ‘low-level’ background, and although the Unity architecture does seem to throw some people, my own opinion is that there’s nothing particularly mysterious about it. Unity provides a fairly easy-to-understand framework under the hood that handles the game loop, update cycles, and so on (the kind of stuff you’d typically code by hand if you were, say, writing a game from scratch in C++), and then lets you hook into it using game object behaviors. Because the basic elements of the system (input, object transforms, etc.) are exposed, you can basically implement just about anything you can think of via script components (within the limits of the engine itself, of course, although that’s the case with any engine).

If you haven’t already seen it, here is a page from the Unity docs that summarizes some methods for accessing game objects and scripts attached to those objects (this seems to be one of the things that frequently throws people).

Great, thanks a lot. That gives me a really good idea for a starting point.

I’m also about to make a marquee selection code.

Just to point out, it was quite easy to find these:
http://forum.unity3d.com/threads/17634-C-amp-C-style-RTS-Community-Project-Generals
http://forum.unity3d.com/threads/29034-RTS-style-selecter
http://forum.unity3d.com/threads/69067-Rts-unit-selection-problem

Wouldn’t it be problematic if the box was axis-aligned; what if the player rotated the camera (assuming the game allows that)? If you meant to say a Rect that would work, though I don’t think a Rect is considered an AABB.

How should one find all objects of interest in the first place? Isn’t it a hassle to have to keep and manage a list of all objects of interest (you mean all units that are seen on the screen?)?

Well I was thinking, since there’s no such thing as Physics.BoxCast or Physics.RectCast, I make a gameobject that has a box collider, set it to be a trigger, align it to the camera, make sure its length is long enough considering the camera can zoom out, then every time a gameobject with the “Unit” tag is found (as an example of how to recognize if a gameobject is a unit) in OnTriggerEnter then set it as selected (or add it to your list of selected objects perhaps, whatever you need to do), if a unit gameobject is found in OnTriggerExit then set it as unselected. Then when the mouse button is released, disable the box collider. That’s the easiest thing I can think of.

Just to note though this would only work if your camera has no perspective projection.

A rectangle can be an AABB. The term ‘AABB’ is dimension-independent; an axis-aligned bounding box can exist in any dimension (although obviously they’re most commonly used in 2-d and 3-d).

That said, it would certainly be reasonable to use the term ‘rectangle’ in this context instead.

That depends on the application, I think. For example, if the total number of units were small enough, you could just brute-force it. You could also use the ‘visibility’ callbacks to keep track of which units were currently visible; or, you could attempt to leverage the physics system, as you described above.

I see. I thought you were referring to a 3d AABB.

That’s what I thought also, even though I plan to have only a few units, a brute force approach won’t be scalable. Well, turns out the box collider approach won’t work for me because of camera perspective (well I could just turn off perspective in the camera).

Even if you use visibility callbacks to manage the list, the problem is you’re going to have to loop through all visible units on the screen every frame, checking each if they are within the marquee selection rectangle, and if there are dozens of them, it will be slow (of course it depends on your hardware).

Also a minor problem with checking the screen-space position of a unit is the marquee won’t consider a unit selected until the screens-space rectangle encompasses the pivot point of that unit. It may or may not be a problem, though I imagine some players might get confused with that kind of behavior. Maybe you can make use of the Renderer’s Bounds instead.

Turns out its not so bad, I just had to give a proper value to the z coordinate for Camera.ScreenToWorldPoint, which would ideally be the distance between the camera and your ground. Though its not as accurate as if I checked the screen-space position of the units instead. To make this method accurate, I would have to use a trapezoidal pyramid instead (a tapered box), with the taper matching the field of view of the perspective camera. I probably could create one with a dynamically created mesh and use that as a mesh collider trigger instead.

Here’s my test (press space to toggle perspective on or off): http://dl.dropbox.com/u/25260770/TacticsEnsembleTest/index.html