jqu*_*404 2 c# unity-game-engine
我有两节课。一个叫做GameManager,另一个叫做Enemies。我在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;
}
Run Code Online (Sandbox Code Playgroud)
我试图从这样的Enimes类中访问这两个变量;但每次它给我curLevel = 0,但我期待得到curLevel = 1。我做错了什么?
// Enemies.cs
void Start () {
Debug.Log (GameManager.get().curLevel); // always output = 0
}
Run Code Online (Sandbox Code Playgroud)
线private static GameManager instance = new GameManager();是问题。
当脚本附加到 a 时GameObject,脚本类型的实例被引用为this脚本内部。换句话说,如果同一个脚本附加到多个GameObjects 上,则可以有多个相同类型的实例。
因此,具体的实例有curLevel = 1,你在检查器中设置为一个实例连接到类型的具体 GameObject。这意味着应该将其称为this在脚本内部。
如果您GameManager在代码中声明了一个新的as实例,您基本上会忽略 Inspector 中的所有值,因为 thestatic GameManager instance指向的实例与您在 Inspector 中为其设置值的实例不同。
为了使用您使用 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;
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,我更改Start()为Awake(). 这是因为您是从其他脚本中引用此方法中初始化的值,并且您不能保证在运行时中的Start()不同之间首先调用哪个MonoBehaviours。但是,Unity 保证Awake()始终早于Start(). 此外,Unity 的最佳实践是在 中初始化自初始化变量Awake(),并在 中初始化依赖于其他脚本的变量Start()根据此执行顺序。
最后,就会出现问题,当有多个GameObject具有GameManager作为其在场景中的组成部分。考虑一种情况,您有两个这样的对象。当场景加载时,每个脚本都会调用Awake(),并且它们都将设置private static GameManager instance;为两个中的每一个this。结果将是一个被另一个覆盖。
你可以说你会小心使用这个脚本并确保只有一个GameObject脚本作为它的组件。但是,您应该始终编写您的代码,就好像不了解您的代码的人可以不假思索地使用它一样,并且可以很容易地检测到其他新项目的人的愚蠢错误。
编辑:
为了回应 OP 的评论,我添加了代码来处理在项目中多次初始化此类型的情况。除了@Kardux的建议,我补充Debug.LogError()是因为我不想让项目默默解决事情。如果出现问题,我希望得到通知。
如果您Singleton在项目中经常使用s,您可能希望有一个父级abstract class Singleton来处理所有子级Singleton的实例检查过程,并GameManager继承自Singleton.
但是,请Singleton谨慎使用,因为如果误用它会被认为是一种糟糕的设计模式。(而且我不知道如何正确使用它,所以我避免使用它。)
| 归档时间: |
|
| 查看次数: |
212 次 |
| 最近记录: |