如何将场景的所有MonoBehaviours添加到List中?

How to add all MonoBehaviours of Scene into the List?

我读过一篇文章 10000 UPDATE() CALLS。 作者使用 UpdateManager。它有 Update 方法,该方法在对象的所有其他 MonoBehaviours 中调用 Update 方法。它比分别从每个 MonoBehaviour 调用 Update 方法更快。

这位经理看起来像:

private ManagedUpdateBehavior[] list;

private void Start() {
    list = GetComponents<ManagedUpdateBehavior>();
}

private void Update() {
    var count = list.Length;
    for (var i = 0; i < count; i++) {
        // UpdateMe
        list[i].UpdateMe();
    }
}

现在每个对象都包含带有代码的组件:

public class ManagedUpdateBehavior : MonoBehaviour {
    // some variables

    public void UpdateMe() {
        // some logic
    }
}

如果 5-6-7-8- 对象有那个组件也没关系。

但是如果我有 100 个对象呢? 1000? 10000?

如何从场景的所有对象中查找并添加所有ManagedUpdateBehaviors?我应该在 On Start 上使用一些递归方法吗?因为每个对象都可能包含脚本的其他对象,它们可能包含其他对象等...无限嵌套

还有一些对象可以动态实例化...如何将它们的单声道添加到管理器?什么是正确的方法?

您可以使用 Object.FindObjectsOfType 方法查找并添加所有 ManagedUpdateBehaviours。

您可以使用静态方法添加动态实例化对象,该静态方法可从创建的游戏对象中调用以将其添加到列表中。

我的建议是创建一个 SceneUpdateManager,像这样:

using UnityEngine;
using System.Collections.Generic;
using System.Linq;

public class SceneUpdateManager : MonoBehaviour {

    private static List<ManagedUpdateBehavior> list;

    private void Start () 
    {
        list = Object.FindObjectsOfType<ManagedUpdateBehavior> ().ToList ();
    }

    public static void AddBehavior(ManagedUpdateBehavior behaviour)
    {
        list.Add (behaviour);
    }

    private void Update () {
        var count = list.Count;

        for (var i = 0; i < count; i++)
        {
            list [i].UpdateMe();
        }
    }
}

Object.FindObjectsOfType does not return inactive objects.

Also some objects can be instantiating dynamically

让每个 ManagedUpdateBehavior 通过将其实例添加到 ManagedUpdateBehavior 实例来订阅 ManagedUpdateBehavior 列表。他们还应该在通过从 ManagedUpdateBehavior 实例中删除自身来销毁时取消订阅 ManagedUpdateBehavior

您的新 ManagedUpdateBehavior 脚本:

public class ManagedUpdateBehavior : MonoBehaviour
{
    UpdateSubscriber updateSUBSCR;

    //Add it self to the List
    void Start()
    {
        updateSUBSCR = GameObject.Find("UpdateSUBSCR").GetComponent<UpdateSubscriber>();
        updateSUBSCR.addManagedUpdateBehavior(this);
    }

    //Remove it self from the List
    void OnDestroy()
    {
        updateSUBSCR.removeManagedUpdateBehavior(this);
    }

    public void UpdateMe()
    {
        // some logic
        Debug.Log("Update from: " + gameObject.name);
    }
}

创建一个名为 UpdateSUBSCR 的游戏对象并将下面的脚本附加到它:

public class UpdateSubscriber : MonoBehaviour
{
    private List<ManagedUpdateBehavior> managedUpdateBehavior = new List<ManagedUpdateBehavior>();


    public void addManagedUpdateBehavior(ManagedUpdateBehavior managedUB)
    {
        managedUpdateBehavior.Add(managedUB);
    }

    public void removeManagedUpdateBehavior(ManagedUpdateBehavior managedUB)
    {
        for (int i = 0; i < managedUpdateBehavior.Count; i++)
        {
            if (managedUpdateBehavior[i] == managedUB)
            {
                managedUpdateBehavior.RemoveAt(i);
                break;
            }
        }
    }

    /*
    public List<ManagedUpdateBehavior> getManagedUpdateBehaviorinstance
    {
        get
        {
            return managedUpdateBehavior;
        }
    }*/

    public void updateAll()
    {
        for (int i = 0; i < managedUpdateBehavior.Count; i++)
        {
            managedUpdateBehavior[i].UpdateMe();
        }
    }
}

然后你可以调用它:

public class Test : MonoBehaviour
{
    UpdateSubscriber updateSUBSCR;

    void Start()
    {
        updateSUBSCR = GameObject.Find("UpdateSUBSCR").GetComponent<UpdateSubscriber>();
    }

    void Update()
    {
        updateSUBSCR.callUpdateFuncs();
    }
}

请注意数组比 List 快,但这比在每个脚本中使用 Update() 函数要好。