【问题标题】:Replace SerializeField with a static Instance in Unity在 Unity 中用静态实例替换 SerializeField
【发布时间】:2018-06-06 02:33:59
【问题描述】:

通常我会以这种方式调用另一个 Monobehaviour 的方法

[SerializeField]
private OtherScript s;

private void Start()
{
    s.DoSomething();
}

我也想过这样的事情

public class OtherScript : MonoBehaviour
{
    public static OtherScript Instance { get { return this; } }

    public void DoSomething()
    {
        Debug.Log("Call");
    }
}

然后我可以通过这种方式从其他脚本中调用该方法

OtherScript.Instance.DoSomething();

但我不能将this 作为静态属性返回。解决方法是这样的

public class OtherScript : MonoBehaviour
{
    private static OtherScript instance;

    public static OtherScript Instance { get { return instance; } }

    private void Start()
    {
        instance = this;
    }

    public void DoSomething()
    {
        Debug.Log("Call");
    }
}

使用此代码时可能会出现一些问题,因为实例是在Start 方法中设置的。如果其他组件在执行自己的Start 方法时需要引用,这可能为时已晚。

所有像GameManagerGameObserverIngameMenu 等唯一的单一行为都应该有一个静态实例,因为它们在场景中只存在一次,我不必为此参考设置检查器字段多次。

有没有更好的使用静态实例的方法?

【问题讨论】:

    标签: c# unity3d


    【解决方案1】:

    使用此代码时可能会出现一些问题,因为实例是 在 Start 方法中设置。如果其他组件,这可能为时已晚 在执行自己的 Start 方法时需要引用

    没错,但这就是我们拥有Awake 函数的原因。将其初始化为Awake 函数,然后在Start 函数中读取它。在调用Start 之前,每个脚本都会调用Awake 函数。

    public class OtherScript : MonoBehaviour
    {
        private static OtherScript instance;
    
        public static OtherScript Instance { get { return instance; } }
    
        private void Awake()
        {
            instance = this;
        }
    
        public void DoSomething()
        {
            Debug.Log("Call");
        }
    }
    

    您的其余代码应保持不变。

    【讨论】:

    • 但是Awake 没有100% 保证在Start 之前被调用,对吗?
    • 100% 保证。滚动到页面底部查看执行流程图here,甚至有文档记录。
    • 非常感谢,我认为这比多次使用多个检查器字段更有用
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-10-04
    • 1970-01-01
    • 1970-01-01
    • 2012-11-12
    • 1970-01-01
    • 2018-02-18
    • 1970-01-01
    相关资源
    最近更新 更多