我有两节课。一个叫GameManager,另一个叫敌人。
我在GameManager中有两个变量,它们已从检查器currentLevel=1
和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
,则可以存在多个相同类型的实例。
因此,在检查器中设置的具有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()
。这是因为您是从其他脚本中引用此方法中初始化的值,并且不能保证在运行时中,在不同的Start()
之间首先调用哪个MonoBehaviours
。但是,Unity保证总是在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
,因为如果使用不当,它会被认为是不好的设计模式。 (而且我不知道如何正确使用它,所以我避免使用它。)关于c# - 检查器值无法从Unity3d中的另一个类访问,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44623070/