繁体   English   中英

检查器值无法从Unity3d中的另一个类访问

[英]Inspector value cannot access from another class in Unity3d

我有两节课。 一个叫GameManager ,另一个叫敌人 我在GameManager中有两个变量,它们已从检查器currentLevel=1totalEnemy=10.更改totalEnemy=10.

// GameManager.cs
    private static GameManager instance = new GameManager();
    public static GameManager get(){ return instance; }

    public int currentLevel;
    public int curLevel { get; set; }
    public int totalEnemy;
    public int totLevel { get; set; }


    void Start () {
        curLevel = currentLevel;
        totLevel = totalEnemy;
    }

我试图像这样从Eneimes类访问这两个变量; 但是每次它都会给我curLevel = 0 ,但是我希望得到curLevel = 1 我做错了什么?

// Enemies.cs

    void Start () {
        Debug.Log (GameManager.get().curLevel); // always output = 0
    }

该行的private static GameManager instance = new GameManager(); 是问题。

当脚本被附接到GameObject ,该脚本的类型的实例被引用作为this脚本内部。 换句话说,如果将相同的脚本附加到多个GameObject ,则可以存在多个相同类型的实例。

因此,您在Inspector中设置的具有curLevel = 1 的特定实例是附加到特定 GameObject的类型的实例 这意味着在脚本中应将其称为this

如果您在代码中声明了GameManager的新实例,则基本上将忽略Inspector中的所有值,因为static GameManager instance所指向的实例与您在Inspector中为其设置值的实例不同。

为了使用您使用检查器声明的特定实例,您应该执行以下操作。

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

public class GameManager : MonoBehaviour
{
    private static GameManager instance;
    public static GameManager get() { return instance; }

    public int currentLevel;
    public int curLevel { get; set; }
    public int totalEnemy;
    public int totLevel { get; set; }

    void Awake()
    {
       if (instance == null) 
       {
          instance = this;
       }
       else 
       {
          Debug.LogError(string.Format("GameManager.Awake(): More than one instances of this type {0} is being initialised but it's meant to be Singleton and should not be initialised twice. It is currently being initialised under the GameObject {1}.", this.GetType(), this.gameObject.name));
          Destroy(gameObject);
       }

        curLevel = currentLevel;
        totLevel = totalEnemy;
    }
}

请注意,我将Start()更改为Awake() 这是因为您是从其他脚本中引用此方法中初始化的值,并且不能保证在运行时中的不同MonoBehaviours之间首先调用哪个Start() 但是,Unity保证总是在Start()之前调用Awake() Start() 此外,Unity的最佳实践是在Awake()初始化可自我初始化的变量,并由于该执行顺序而在Start()初始化依赖于其他脚本的变量。

最后,就会出现问题,当有多个GameObject是具有GameManager作为其在场景中的组成部分。 考虑一下您有两个这样的对象的情况。 加载场景时,每个脚本都将调用Awake() ,并且两个脚本都将设置private static GameManager instance; 每两个this 结果将是一个被另一个覆盖。

您可能会说,使用该脚本时要小心,并确保只有一个GameObject将此脚本作为其组件。 但是,您应该始终编写代码,就像不了解您的代码的人可以不经考虑就使用它,并且可以很容易地发现其他人对项目的愚蠢错误。

编辑:

为了回应OP的评论,我添加了代码以在项目中多次初始化此类型时进行处理。 除了@Kardux的建议之外,我还添加了Debug.LogError()因为我不希望该项目静默地解决问题。 如果发生问题,我想得到通知。

如果您在项目中经常使用Singleton ,则可能需要一个父abstract class Singleton来处理所有子Singleton的实例检查过程,并使GameManager继承自Singleton

但是,请谨慎使用Singleton ,因为如果滥用它,这将被视为不良的设计模式。 (而且我不知道如何正确使用它,所以我避免使用它。)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM