- Home /
Select un-selectable Objects with mouse.
(Problem)
I have came across a pretty annoying issue, I need to select a game object that does not have a single selectable component. Which is infuriating because I have alot of those kinds of objects, I need a handle, gizmo, or a dummy object that only has a presence in editor, that I can click on in the editor. I want to see if the community has a solution first before I try to make one.
(Context)
I made a pathfinding system involving a lot of waypoints for a complex 2D platformer. All the waypoints sit on a single parent named Waypoints, There is at least 100 or more waypoints. My current way to select a object is to scan through the objects to find the one I want to edit. Do to the nature of the garbage collector, it has to dispose of memory often because what I'm assuming is the inspectors fault, Leaving a small delay before I can continue scanning through the objects, Annoying and a little bearable but definatly adding to the currently fubar situation.
(What I hope exists)
An example script to help select those un-selectable objects(With a mouse).
A handle function(that I haven't found by name) so I can make a editor script for the waypoint comp to make it selectable.
Something that exists in the doc that pertains to this situation.
A feature request link, so I can upvote it.
Answer by ricardo_arango · Jul 10, 2014 at 09:03 PM
You can draw handles using the Handle class:
http://docs.unity3d.com/ScriptReference/Handles.PositionHandle.html
You can use Gizmos to draw the Spheres in the scene:
http://docs.unity3d.com/ScriptReference/Gizmos.DrawSphere.html
And you can detect the intersection of a ray and a sphere using this code:
public static bool IntersectRaySphere(Ray ray, Vector3 sphereOrigin, float sphereRadius, ref float t, ref Vector3 q)
{
Vector3 m = ray.origin - sphereOrigin;
float b = Vector3.Dot(m, ray.direction);
float c = Vector3.Dot(m, m) - (sphereRadius * sphereRadius);
// Exit if rís origin outside s (c > 0)and r pointing away from s (b > 0)
if ((c > 0.0f) && (b > 0.0f)) return false;
float discr = (b * b) - c;
// A negative discriminant corresponds to ray missing sphere
if (discr < 0.0f) return false;
// Ray now found to intersect sphere, compute smallest t value of intersection
t = -b - Mathf.Sqrt(discr);
// If t is negative, ray started inside sphere so clamp t to zero
if (t < 0.0f) t = 0.0f;
q = ray.origin + t * ray.direction;
return true;
}
t is the distance to the sphere, q is the point of collision.
ray is the Ray to the scene from the camera, which you can calculate using
var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
sphereOrigin is the position of each waypoint.
sphereRadius is the radius of each waypoint.
What you need to do is that when your Waypoints GameObject is selected, you will display all the waypoints using Gizmos.DrawSphere.
When the user clicks in the scene:
var mouseUpEvent = Event.current.type == EventType.MouseUp;
you will then use the IntersectRaySphere function above to detect if a sphere/waypoint was clicked and store the reference to it (you will have to iterate all the waypoints).
With a reference to a waypoint (and it's data) you can draw a position Handle with Handles.PositionHandle, which will allow you to edit the position of the waypoint.
Now that I can click the object and get a tangible reference to it, I'm assu$$anonymous$$g that I just assign the reference to Selection.activeGameObject...? Really wish they made a function or class attribute that basically did all this. Thanks Ricardo!
Do you need a GameObject for each waypoint? If it's just a point you can simply have an array of Vector3 in a single "Wayponts" class. And use the Gizmos and Handles to do all the editing in the scene.
The handles don't care about object selection, they are simply gizmos that are drawn at a point in space. So all you need is a position to represent the waypoint/handle. If you really need to have a GameObject per waypoint object, then yes, you can change the selection with Selection.activeGameObject.
It would have been a great idea to have each waypoint to not have there own game object, And I certainly could do what you said. However the waypoints are going to be added onto prefabs and I realise that the complexity could grow even larger than ever if I made them all on one object(Also I'm using the transforms attached to all of them). I could make each prefab have a container for those waypoints but I think there is really no positive performance impact or any other practical reason to do so, Beside it being neat a pretty. Sounds like I should experiment into it however, maybe punch them all into a scriptable object so I could edit them as the game is playing. I would have to do it later in dev, Its not worth throwing more time into if it works fine right now.
I eventually was able to make my waypoints operate sorta like the light probe system in the editor, When you select a GameObject with a Waypoint component, you will have the ability to click other GameObjects with the same component. However when you click something else that doesn't, You lose that ability.
Here is a code snip for anyone interested. You are going to have to format it a bit.
[DrawGizmo (GizmoType.NotSelected | GizmoType.Pickable)]
static void OnDrawGizmo (Waypoint aTarget, GizmoType aGizmoType){
if (Selection.activeGameObject != null && Selection.activeGameObject.GetComponent<Waypoint> () != null) {
Gizmos.color = Color.cyan;
Gizmos.DrawSphere (aTarget.transform.position,SphereRadius);}}
void OnSceneGUI(){
foreach (Waypoint point in Waypoint.Waypoints) {
if (point != null) {
if (point != selected) {
if (Event.current.type == EventType.$$anonymous$$ouseUp) { float t = 0f;
Vector3 q = Vector3.zero;
if (IntersectRaySphere (HandleUtility.GUIPointToWorldRay(Event.current.mousePosition), point.transform.position, SphereRadius, ref t, ref q)) { Selection.activeGameObject = point.gameObject;}}}}}
Your answer
![](https://koobas.hobune.stream/wayback/20220613153742im_/https://answers.unity.com/themes/thub/images/avi.jpg)