Unity中跨类引用公共属性始终为Null,求正确实现方法
Unity中正确引用其他脚本属性的方法
问题根源
你当前代码的错误在于CameraManager的Awake方法中使用了gameObject.AddComponent<GameManager>(),这会给相机对象添加一个全新的GameManager组件,而非引用场景中已存在的、挂载在GameManager空对象上的那个组件。这个新创建的组件的lastTile属性自然未被赋值,所以始终为null。
正确的引用方式
1. Inspector面板手动赋值(最推荐)
这种方法直观且性能最优,适合固定存在的场景对象:
- 修改
CameraManager的代码,将gameManager字段设为public:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class CameraManager : MonoBehaviour { private Vector3 currPos; private Vector3 newPos; public float CamMoveSpeed = 5f; // 改为public,允许在Inspector中赋值 public GameManager gameManager; private void Start() { } private void Update() { if (gameManager?.lastTile != null) { currPos = transform.position; Vector3 tilePos = gameManager.lastTile.transform.position; newPos = new Vector3(currPos.x + tilePos.x, currPos.y + tilePos.y, currPos.z + tilePos.z); transform.position = Vector3.Lerp(currPos, newPos, CamMoveSpeed * Time.deltaTime); Debug.Log("Moving Camera..."); } else { Debug.LogWarning("gameManager.lastTile is NULL"); } } }
- 在Unity编辑器中,选中挂载
CameraManager的相机对象,在Inspector面板找到CameraManager组件,将场景中的GameManager空对象拖到Game Manager字段上即可。
2. 通过FindObjectOfType自动查找
适合场景中只有一个GameManager实例的情况,在初始化时查找:
private void Awake() { // 查找场景中第一个GameManager组件实例 gameManager = FindObjectOfType<GameManager>(); }
注意:FindObjectOfType会遍历场景中所有对象,性能开销较大,仅在初始化(如Awake/Start)时调用,不要放在Update中。
3. 通过GameObject.Find按对象名称查找
如果你明确知道场景中GameManager对象的名称,也可以通过名称定位后获取组件:
private void Awake() { // 先找到名为GameManager的对象,再获取其GameManager组件 GameObject gmObj = GameObject.Find("GameManager"); if (gmObj != null) { gameManager = gmObj.GetComponent<GameManager>(); } }
注意:如果场景中有多个同名对象,GameObject.Find只会返回第一个找到的对象,需确保对象名称唯一。
4. 单例模式(适合全局管理类)
如果GameManager是全局唯一的管理类,可以将其设为单例,方便任何脚本随时引用:
- 修改
GameManager代码:
public class GameManager : MonoBehaviour { public GameObject tilePrefab; public GameObject startTile; public GameObject lastTile; // 单例实例 public static GameManager Instance; private void Awake() { // 确保全局唯一 if (Instance == null) { Instance = this; DontDestroyOnLoad(gameObject); // 可选,跨场景保留 } else { Destroy(gameObject); } } }
- 在
CameraManager中直接引用:
private void Update() { if (GameManager.Instance?.lastTile != null) { // 使用GameManager.Instance.lastTile进行操作 currPos = transform.position; Vector3 tilePos = GameManager.Instance.lastTile.transform.position; newPos = new Vector3(currPos.x + tilePos.x, currPos.y + tilePos.y, currPos.z + tilePos.z); transform.position = Vector3.Lerp(currPos, newPos, CamMoveSpeed * Time.deltaTime); Debug.Log("Moving Camera..."); } else { Debug.LogWarning("gameManager.lastTile is NULL"); } }
内容的提问来源于stack exchange,提问作者user736893
相关产品推荐
相关产品推荐

