Hello, I wrote this simple editor script to basically mimic Unity’s built-in RequireComponent attribute, but for the root object instead of the same object.
Is it possible to have the inspector say a warning that another object requires this component without creating custom inspector scripts for each new script that uses this attribute? Also, how can I detect if a component is being removed in the editor, like how a pop-up box appears when you try to remove a component that’s held on by Unity’s RequireComponent attribute? And, are there any other ways I can improve this?
using System;
using UnityEngine;
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class RequireComponentOnRootAttribute : Attribute
{
/// <summary>
/// The type of component to be required on the root gameobject.
/// </summary>
public Type type;
/// <summary>
/// Whether or not only one instance of the required component is allowed in the entire transform hierarchy.
/// </summary>
public bool singleton = false;
public RequireComponentOnRootAttribute(Type type)
{
if (!(type.IsSubclassOf(typeof(Component)) || type == typeof(Component)))
{
throw new ArgumentException("type must derive from Component or MonoBehaviour.", "type");
}
this.type = type;
}
}
using System;
using UnityEditor;
using UnityEngine;
[InitializeOnLoad]
public class RequireComponentOnRootExecution
{
static RequireComponentOnRootExecution()
{
EditorApplication.delayCall += Update;
EditorApplication.hierarchyWindowChanged += Update;
EditorApplication.projectWindowChanged += Update;
}
static void Update()
{
foreach (var comp in UnityEngine.Object.FindObjectsOfType<Component>())
{
RequireComponentOnRootAttribute attribute = (RequireComponentOnRootAttribute) Attribute.GetCustomAttribute(comp.GetType(), typeof(RequireComponentOnRootAttribute));
if (attribute != null)
{
Transform root = comp.transform.root;
if (root.GetComponent(attribute.type) == null)
{
Debug.LogWarning(comp.GetType() + " requires the root gameobject to contain " + attribute.type + ". Adding to '" + root.name + "'...");
root.gameObject.AddComponent(attribute.type);
}
if (attribute.singleton)
{
var arr = root.GetComponentsInChildren(attribute.type);
for (int i = 1; i < arr.Length; i++)
{
Debug.LogWarning(comp.GetType() + " only allows one " + attribute.type + " in its transform hierarchy. Removing " + attribute.type + " from '" + arr[i].name + "'...");
UnityEngine.Object.DestroyImmediate(arr[i]);
}
}
}
}
}
}