Inspector值无法从Unity3d中的另一个类访问

时间:2017-06-19 05:49:25

标签: c# unity3d

我有两节课。一个叫做 GameManager ,另一个叫 Enemies 。 我在 GameManager 中有两个变量,我从检查员ID Match ID New ID Zrecruit_376840000000415007 Zrecruit_376840000000367020 = 5782 Zrecruit_376840000000215296 Zrecruit_376840000000375036 = 5783 Zrecruit_376840000000217195 Zrecruit_376840000000389001 = 5784 Zrecruit_376840000000218111 Zrecruit_376840000000369168 = 5785 Zrecruit_376840000000219665 Zrecruit_376840000000392001 = 5786 Zrecruit_376840000000222030 Zrecruit_376840000000410013 = 5787 Zrecruit_376840000000226008 Zrecruit_376840000000432013 = 5788 Zrecruit_376840000000227079 Zrecruit_376840000000415007 = 5789 currentLevel=1更改了

totalEnemy=10.

我试图像这样从 Eneimes 类中访问这两个变量;但每次它都给我// 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; } ,但我希望得到curLevel = 0。我做错了什么?

curLevel = 1

1 个答案:

答案 0 :(得分:4)

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

当脚本附加到GameObject时,脚本类型的实例在脚本中被引用为this。换句话说,如果将相同的脚本附加到多个GameObject,则可能存在多个相同类型的实例。

因此,在检查器中设置的 具有curLevel = 1的特定实例 是附加类型的实例 具体的 GameObject。这意味着该脚本应该在脚本中被称为this

如果您在代码中声明GameManager的新实例,则基本上忽略了检查器中的所有值,因为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()。这是因为您指的是此方法中从其他脚本启动的值,并且您无法保证在运行时的不同Start()之间首先调用哪个MonoBehaviours。但是,Unity保证Awake()始终比Start()更早被调用。此外,在Awake()中初始化自我初始化变量是Unity的最佳实践,并且由于此执行顺序而初始化依赖于Start()中其他脚本的变量。

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

您可以说您将小心使用此脚本,并确保只有一个GameObject将此脚本作为其组件。但是,您应该始终编写代码,就像不了解您的代码的人可以不假思索地使用它一样,而对于项目新手的其他人的愚蠢错误可以 轻松检测到

编辑:

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

如果您在项目中频繁使用Singleton,则可能希望父abstract class Singleton处理所有子Singleton的此实例检查过程,并GameManager Singleton 1}}继承自Singleton

但是,请谨慎使用endif,因为如果误用,它会被视为糟糕的设计模式。 (而且我不知道如何正确使用它,所以我避免使用它。)