Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Unity3D防止添加某些内置组件_C#_Unity3d_Components - Fatal编程技术网

C# Unity3D防止添加某些内置组件

C# Unity3D防止添加某些内置组件,c#,unity3d,components,C#,Unity3d,Components,我制作了我自己的组件,它与一些Unity内置组件冲突(比如刚体与刚体2d冲突)。所以我需要确保这些组件不会同时存在于同一个游戏对象中。有办法吗?当我自己的组件被添加(by)时,似乎很容易检查,但如果添加了Unity的内置组件,该怎么办?当新组件连接到游戏对象时,是否会发送一些回调、消息或事件 精度 我不需要在编辑器中隐藏组件,也不需要阻止添加我自己的组件。我问的是如何防止在连接组件时添加某些Unity内置组件。从编辑器GUI(通过“”按钮)和Unity API(通过)。如果您试图确定该组件在运行

我制作了我自己的组件,它与一些Unity内置组件冲突(比如刚体与刚体2d冲突)。所以我需要确保这些组件不会同时存在于同一个游戏对象中。有办法吗?当我自己的组件被添加(by)时,似乎很容易检查,但如果添加了Unity的内置组件,该怎么办?当新组件连接到游戏对象时,是否会发送一些回调、消息或事件

精度


我不需要在编辑器中隐藏组件,也不需要阻止添加我自己的组件。我问的是如何防止在连接组件时添加某些Unity内置组件。从编辑器GUI(通过“”按钮)和Unity API(通过)。

如果您试图确定该组件在运行前是否存在(我假设您已经知道),则可以使用
Start()
方法。但是,正如我所说的,我假设您已经知道了这一点,所以在运行时检查类似内容的唯一其他方法是在
Update()
方法中,每一帧持续检查它。尽管如此,我不确定为什么在运行时会将Unity组件添加到游戏对象中。如果这是一个问题,也许有问题的组件可以被添加到子游戏对象或父游戏对象

如果您真的想做一些更改,这可能需要对您的项目进行大量重构,您始终可以创建一个
ComponentManager
类,该类处理向游戏对象添加和删除组件的操作,并创建您自己的回调。

有一个属性可以防止向同一游戏对象添加两个相同类型的组件。这也适用于子类型(这就是刚体和刚体2d的处理方式)

我不确定这是否适用于您,因为您没有说过您的组件彼此相关,但这是我可以找到的

新建组件时是否发送了回调、消息或事件 附加到游戏对象

没有

有办法吗

是的,但有点复杂

若你们想阻止你们的自定义脚本被添加,那个将是很容易的,问题应该解决这个问题

这很复杂,因为您希望防止将另一个人编写的组件(内置)添加到
游戏对象
,这意味着您首先需要一种方法来检测该组件何时已添加到
游戏对象
,然后销毁它这必须在每一帧(在编辑器中和运行时)进行

您可以调用不希望添加到
GameObject
黑名单组件中的组件

以下是步骤:

1。将列入黑名单的组件存储在一个数组中

private static Type[] blacklistedComponents =
{
    typeof(Rigidbody),
    typeof(Rigidbody2D)
    //...
};
2。在场景中获取根
游戏对象
,并将它们存储在列表中

private static List<GameObject> rootGameObjects = new List<GameObject>();
Scene.GetRootGameObjects(rootGameObjects);
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");
        }
    }
}

您需要在运行时进行此检查吗?@Ambo100在运行时和编辑器中都有此项检查。@replicate解释了如何进行此项检查。@Programmer我不需要在编辑器中隐藏它。我需要一个解决方案,防止在连接组件时添加某些Unity内置组件。从编辑器GUI(通过“添加组件”按钮)和Unity API(通过GameObject.AddComponent)。隐藏组件是另一个问题的一部分,但不是主要问题。主要问题(见标题)是关于防止向游戏对象添加组件。请阅读我答案的第二部分。是的,这是一个很好的属性,但它不会有帮助,我的组件不是从内置派生的(而且不能,它们大部分是密封的)。并且该属性不用于解决刚体和刚体2d之间的冲突,因为它仅适用于类及其派生(它们都是从组件派生的,并且对象可以有多个组件,例如,变换是从组件派生的)。如果您注意到,当您尝试添加刚体时,消息是不同的,因为已经添加了刚体2d。Unity明确指出这是一个冲突,这就是我需要复制的内容。@VictorF唉,这是我能找到的唯一一个更接近的信息。“我想问的是,在连接组件时,如何防止添加某些Unity的内置组件。”我把重点放在这个问题的标题上,这样这个问题就可以对其他用户重复使用,但是你可以用这个答案轻松地做到这一点。我把那部分留给你去做,如果你读了这个答案,这很容易。当在
if(targetComponents[i].GetType()==blacklistedList[j])
代码行中找到黑名单组件时,您可以使用
GetComponent
检查当前
targetComponents
是否有您的
Rigidbody
CustomRigidbody
并销毁它。只需添加
if(targetComponents[i].GetComponent()&&targetComponents[i].GetComponent(){//Destroy Component Destroy immediate(targetComponents[i]);}
内部
if(targetComponents[i].GetType()==blacklistedList[j])
。另外,将所有旧代码和调试语句移动到新的
if
语句中。就这样。您可以添加尽可能多的
else if
语句,以涵盖所有
if
组件。您的第二条注释无效,只是一句废话。1.答案中的代码不会一次返回所有游戏对象或所有组件。它返回根GameObjects,根GameObjects只是存储GameObject,而GameObject是一个对象,不是图像或大量数据。2.它循环遍历每个根游戏对象,并获取每个循环中的所有子组件。它不会一次获取场景中的所有组件。资源不应成为问题。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");
        }
    }
}
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