- Home /
Editor. Ignore selection some gameObjects
Hi everyone. I want to ignore selection some gameObjects. For example, I have two scripts :
ChooseObject.cs
Don'tChooseObject.cs
If in my selection area are some objects with first script - they have to be selected, but if there are some objects with second script - these objects have to be unselected
You probably only need one script called 'Selectable' which is attached to anything that you can actually select. It can have all the rules for selecting it, like will it be selected while dragging out a selection area, or which $$anonymous$$m/player it belongs to, etc.
Assu$$anonymous$$g that you have your selection rect working properly, and that it can discover game objects that exist within the area defined, the rest is easy.
Use GetComponent to find the Selectable Component on each GameObject in the selection area.
Query each discovered Selectable Component, via a method call that returns a bool, to see if it should be added to the selection.
If the result of step 1 is not null and the result of step 2 is true then add it to a list.
The list now represents your selection.
Answer by vexe · Jun 12, 2014 at 09:29 AM
So just like @iwaldrop said, this is basically it: First put this in any non-Editor folder:
using UnityEngine;
public class Unselectable : MonoBehaviour
{
}
And put this in an "Editor" folder:
using UnityEngine;
using UnityEditor;
using System.Linq;
using System;
using Object = UnityEngine.Object;
[InitializeOnLoad]
public static class CustomSelection
{
private const string MenuPath = "EditorTools/CustomSelection";
// Change these keys to your liking - just make sure they don't conflict with something
private const string MakeSelectableKey = "#&s";
private const string MakeUnselectableKey = "#&u";
private static bool enabled;
/// <summary>
/// Needed so that we could start automatically after an assembly reload
/// </summary>
static CustomSelection()
{
Start();
}
/// <summary>
/// Whether or not we can start (used to [en, dis]able the Starting mechanism)
/// </summary>
[MenuItem(MenuPath + "/Start", true)]
public static bool CanStart()
{
return !enabled; // we can only start if we're stopped
}
/// <summary>
/// Starts the selection check
/// </summary>
[MenuItem(MenuPath + "/Start")]
public static void Start()
{
if (!enabled) // Might be a redundant check, but just in case someone wants to start it from code
{
enabled = true;
EditorApplication.update += Update;
}
}
/// <summary>
/// Whether or not we can stop (used to [en, dis]able the Stopping mechanism)
/// </summary>
[MenuItem(MenuPath + "/Stop", true)]
public static bool CanStop()
{
return enabled; // we can only stop if we're started
}
/// <summary>
/// Stops selection check
/// </summary>
[MenuItem(MenuPath + "/Stop")]
public static void Stop()
{
if (enabled)
{
enabled = false;
EditorApplication.update -= Update;
}
}
/// <summary>
/// Makes the current gameObjects selection unselectable by adding the Unselectable component to each gameObject in the selection
/// </summary>
[MenuItem(MenuPath + "/Make Selection Unselectable " + MakeUnselectableKey)]
public static void MakeUnselectable()
{
foreach (var go in Selection.gameObjects)
{
// Add it only if it's not there
if (go.GetComponent<Unselectable>() == null)
go.AddComponent<Unselectable>();
}
}
/// <summary>
/// Whether or not we can make the selection selectable again
/// </summary>
[MenuItem(MenuPath + "/Make Selection Selectable " + MakeSelectableKey, true)]
public static bool CanMakeSelectable()
{
return !enabled;
}
/// <summary>
/// Makes the current gameObjects selection selectable again
/// Note: Must call Stop first in order to select a selection that has the Unselectable component on it
/// </summary>
[MenuItem(MenuPath + "/Make Selection Selectable " + MakeSelectableKey)]
public static void MakeSelectable()
{
Action<Component> destroy = Application.isPlaying ?
(Action<Component>)Object.Destroy : Object.DestroyImmediate;
foreach (var go in Selection.gameObjects)
{
destroy(go.GetComponent<Unselectable>());
}
}
private static void Update()
{
var gos = Selection.gameObjects;
if (gos != null && gos.Length > 0)
{
Selection.objects = gos.Where(g => g.GetComponent<Unselectable>() == null).ToArray();
}
}
}
This works perfectly well. However, you may notice that sometimes it may seem that you're selecting an unselectable gameObject (it highlights in blue) but you're actually not (no inspector shown for it) - not sure if this is a Unity quirk.
I missed the editor part. Yes, an 'unselectable' component is the way to go.
Just trying this out now (Unity 5.6), the code seems to work but I'm getting an issue with the functionality itself.
I have a very long mesh object which I'm trying to select the faces of using ProBuilder. when I try to select a face that's far from the center of origin and near another object, if that object has been made unselectable, my click returns no selection. If I hide the objects near my intended target I can select the faces fine.
So it seems that while the unselectable code is functioning, it's not actually removing the attempt to select, which can still present a higher priority selection that any other object resulting in no selection being made.
Looking at the code and making a few guesses it seems that selection isn't prevented, but denied so the process of selection still happens, which would end up producing the results I'm seeing. A full solution would ignore any attempt of selection as though the object isn't there, or upon detecting an unselectable object would cause a chain of actions until a valid object found or none at all, that might be expensive though to cycle through all possible objects under the cursor.
Just added some debug code to see what's being returned from the selection
foreach (GameObject i in gos) Debug.Log("name: " + i.name);
It only seemed to report a single gameobject, I never got an instance where it would return multiple objects either by drag selecting or single clicking, so not sure why it's an array of gameobjects. This code, of course, printed out the name of the unselectable object because the system is actually grabbing it before the above code removes it. Not sure what to suggest for fixing this issue in my case, I don't know enough about Unity Editor code to have an idea of the next step without some investigation.
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
ObjectField Get object type(Asset, Scene Object) 2 Answers
Box Selecting Top-Level Transforms Only 0 Answers