新组件时是否有一些回调、消息或事件发送
附加到游戏对象?
没有。
有办法吗?
是的,但有点复杂。
如果您想阻止添加自定义脚本,这很容易,this question 应该可以解决这个问题。
这很复杂,因为您想防止将另一个人(内置)编写的组件添加到 GameObject,这意味着您首先需要一种方法来检测该组件何时已添加到 @987654323 @ 然后销毁它。 这必须在每一帧都完成(在编辑器中和运行时)。
您可以将不想添加的组件调用到GameObject黑名单组件。
步骤如下:
1.将列入黑名单的组件存储在一个数组中。
private static Type[] blacklistedComponents =
{
typeof(Rigidbody),
typeof(Rigidbody2D)
//...
};
2.获取场景中的根GameObjects并将它们存储在List中。
private static List<GameObject> rootGameObjects = new List<GameObject>();
Scene.GetRootGameObjects(rootGameObjects);
3.循环遍历每个根GameObject 并使用GetComponentsInChildren 获取附加到该根GameObject 下每个GameObject 的所有组件。
private static List<Component> allComponents = new List<Component>();
currentLoopRoot.GetComponentsInChildren<Component>(true, allComponents);
4.在#3的循环中,遍历检索到的组件并检查它是否有任何列入黑名单的组件。如果是,则销毁该列入黑名单的组件。
for (int i = 0; i < allComponents.Count; i++)
{
//Loop through each blacklisted Component and see if it is present
for (int j = 0; j < blacklistedComponents.Length; j++)
{
if (allComponents[i].GetType() == blacklistedComponents[j])
{
Debug.Log("Found Blacklisted Component: " + targetComponents[i].GetType().Name);
Debug.Log("Removing Blacklisted Component");
//Destroy Component
DestroyImmediate(allComponents[i]);
Debug.LogWarning("This component is now destroyed");
}
}
}
就是这样。您或其他人可能对此答案有一些疑问。
Q 1。想知道为什么不使用FindObjectsOfType 和FindObjectsOfTypeAll?
A 1。这些函数通常用于简化获取场景中的所有内容,但问题是它们返回数组。每帧调用这些函数会降低游戏性能,因为它会分配内存并导致垃圾收集器更频繁地运行。
这就是使用Scene.GetRootGameObjects 的原因,您可以在其中传递List,它会为您填写列表。它不返回数组。
Q 2。为什么你将 List 传递给 GetComponentsInChildren 却没有返回结果?
A 2。技术上与我上面解释的原因相同。我使用了不分配内存的GetComponentsInChildren 函数版本。只需将List 传递给它,它就会用它找到的每个组件填充它。这可以防止它返回一个昂贵的数组。
我在下面为此编写了一个完整的工作代码,但您需要改进它。这就是为什么我解释了每个过程,以便您可以自己改进或重写。它目前阻止从编辑器或编辑器中的代码或构建中添加Rigidbody 和Rigidbody2D。您可以将更多要阻止的组件添加到blacklistedComponents 变量。它也在运行时在编辑器中运行。 UNITY_EDITOR 用于删除编辑器代码并确保它可以针对平台进行编译。
1。创建一个名为ComponentDetector 的脚本并将下面的所有代码复制到其中。
2.保存并返回编辑器。而已。您不必将其附加到任何对象。 您永远不能将Rigidbody 和Rigidbody2D 添加到任何游戏对象中。
using System.Collections.Generic;
using UnityEngine;
using System;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
#endif
public class ComponentDetector : MonoBehaviour
{
//Add the blacklisted Components here
private static Type[] blacklistedComponents =
{
typeof(Rigidbody),
typeof(Rigidbody2D)
//...
};
private static List<Component> allComponents = new List<Component>();
private static List<GameObject> rootGameObjects = new List<GameObject>();
private static void GetAllRootObject()
{
Scene activeScene = SceneManager.GetActiveScene();
activeScene.GetRootGameObjects(rootGameObjects);
}
private static void GetAllComponentsAndCheckIfBlacklisted()
{
for (int i = 0; i < rootGameObjects.Count; ++i)
{
GameObject obj = rootGameObjects[i];
//Debug.Log(obj.name);
//Get all child components attached to this GameObject
obj.GetComponentsInChildren<Component>(true, allComponents);
//Remove component if present in the blacklist array
RemoveComponentIfBlacklisted(allComponents, blacklistedComponents);
}
}
private static void RemoveComponentIfBlacklisted(List<Component> targetComponents, Type[] blacklistedList)
{
//Loop through each target Component
for (int i = 0; i < targetComponents.Count; i++)
{
//Debug.Log(targetComponents[i].GetType());
//Loop through each blacklisted Component and see if it is present
for (int j = 0; j < blacklistedList.Length; j++)
{
if (targetComponents[i].GetType() == blacklistedList[j])
{
Debug.Log("Found Blacklisted Component: " + targetComponents[i].GetType().Name);
Debug.LogError("You are not allowed to add the " + targetComponents[i].GetType().Name + " component to a GameObject");
Debug.Log("Removing Blacklisted Component");
//Destroy Component
DestroyImmediate(targetComponents[i]);
Debug.LogWarning("This component is now destroyed");
}
}
}
}
public static void SearchAndRemoveblacklistedComponents()
{
//Get all root GameObjects
GetAllRootObject();
//Get all child components attached to each GameObject and remove them
GetAllComponentsAndCheckIfBlacklisted();
}
void Awake()
{
DontDestroyOnLoad(this.gameObject);
}
// Update is called once per frame
void Update()
{
//Debug.Log("Update: Run-time");
SearchAndRemoveblacklistedComponents();
}
}
#if UNITY_EDITOR
[InitializeOnLoad]
class ComponentDetectorEditor
{
static ComponentDetectorEditor()
{
createComponentDetector();
EditorApplication.update += Update;
}
static void Update()
{
//Debug.Log("Update: Editor");
ComponentDetector.SearchAndRemoveblacklistedComponents();
}
static void createComponentDetector()
{
GameObject obj = GameObject.Find("___CDetector___");
if (obj == null)
{
obj = new GameObject("___CDetector___");
}
//Hide from the Editor
obj.hideFlags = HideFlags.HideInHierarchy;
obj.hideFlags = HideFlags.HideInInspector;
ComponentDetector cd = obj.GetComponent<ComponentDetector>();
if (cd == null)
{
cd = obj.AddComponent<ComponentDetector>();
}
}
}
#endif