Unity2D实例化随机对象仍报空引用异常问题求助
问题:Unity食物生成与伤害系统的空引用异常
我正在制作一款简易游戏,核心玩法是生成食物并对其造成伤害直至消失。需要实现从数组实例化随机对象、为实例化对象附加脚本,以及在另一脚本中对生成的食物造成伤害。目前两个脚本均触发Null Reference Exception(空引用异常),尝试在实例化对象时附加脚本后问题依旧存在。
Food脚本(Food.cs)
public class Food : MonoBehaviour { public GameObject[] food; public Vector3Int spawnPosition; public int health = 200; public int currentHealth; private GameObject clone; public void Start() { currentHealth = health; SpawnFood(); } //Spawning food public void SpawnFood() { int random = Random.Range(0, food.Length); //Null Reference Exception occur here clone = Instantiate(food[random], this.spawnPosition, Quaternion.identity) as GameObject; clone.AddComponent<Food>(); } public void TakeDamage(int damage) { currentHealth -= damage; //play hurt effect if(currentHealth < 0) { Vanish(); } } void Vanish() { Debug.Log("Vanished"); } }
Board脚本(Board.cs)
public class Board : MonoBehaviour { public Tilemap tilemap { get; private set; } public Piece activePiece { get; private set; } public TetrominoData[] tetrominoes; public Vector3Int spawnPosition; public Vector2Int boardSize = new Vector2Int(10, 20); public int damage; public Food clone; public TextMeshProUGUI hud_score; public static int currentScore = 0; public int scoreOneLine = 40; public int scoreTwoLine = 100; public int scoreThreeLine = 300; public int scoreFourLine = 1200; private int numberOfRowsThisTurn = 0; public RectInt Bounds { get { Vector2Int position = new Vector2Int(-this.boardSize.x / 2, -this.boardSize.y / 2); return new RectInt(position, this.boardSize); } } private void Awake() { this.tilemap = GetComponentInChildren<Tilemap>(); this.activePiece = GetComponentInChildren<Piece>(); //call Tetromino.Initialize() to spawn pieces for (int i = 0; i < this.tetrominoes.Length; i++) { this.tetrominoes[i].Initialize(); } } private void Start() { SpawnPiece(); } private void Update() { UpdateScore(); UpdateUI(); } public void UpdateUI() { hud_score.text = currentScore.ToString(); } public void UpdateScore() { if(numberOfRowsThisTurn > 0) { if(numberOfRowsThisTurn == 1) { ClearedOneLine(); } else if (numberOfRowsThisTurn == 2) { ClearedTwoLine(); } else if (numberOfRowsThisTurn == 3) { ClearedThreeLine(); } else if (numberOfRowsThisTurn == 4) { ClearedFourLine(); } numberOfRowsThisTurn = 0; } } public void ClearedOneLine() { currentScore += scoreOneLine; clone.GetComponent<Food>().TakeDamage(10); //Null Reference Exception occur here } public void ClearedTwoLine() { currentScore += scoreTwoLine; clone.GetComponent<Food>().TakeDamage(20); //Null Reference Exception occur here } public void ClearedThreeLine() { currentScore += scoreThreeLine; clone.GetComponent<Food>().TakeDamage(40); //Null Reference Exception occur here } public void ClearedFourLine() { currentScore += scoreFourLine; clone.GetComponent<Food>().TakeDamage(80); //Null Reference Exception occur here } }
检查器配置说明
检查器中已为food数组配置64个元素(数组已正确赋值)。
解决方案
1. 修复Food脚本的空引用异常
问题根源:同一个脚本既承担食物生成器职责,又承担食物实体职责,导致实例化的新食物对象上的food数组未赋值,触发空引用。
代码优化:拆分职责
- 新建
FoodSpawner脚本负责生成逻辑 - 修改
Food脚本仅处理食物的生命值与受伤逻辑
修改后的Food脚本:
public class Food : MonoBehaviour { public int health = 200; private int currentHealth; private void Start() { currentHealth = health; } public void TakeDamage(int damage) { currentHealth -= damage; //play hurt effect if(currentHealth <= 0) { Vanish(); } } void Vanish() { Debug.Log("Vanished"); Destroy(gameObject); // 销毁消失的食物对象 } }
新增FoodSpawner脚本:
public class FoodSpawner : MonoBehaviour { public GameObject[] foodPrefabs; // 存放带有Food脚本的预制体 public Vector3Int spawnPosition; private GameObject currentFood; private void Start() { SpawnFood(); } public void SpawnFood() { if(foodPrefabs == null || foodPrefabs.Length == 0) { Debug.LogError("食物预制体数组为空或未赋值!"); return; } int random = Random.Range(0, foodPrefabs.Length); currentFood = Instantiate(foodPrefabs[random], spawnPosition, Quaternion.identity); // 可选:如果预制体未挂载Food脚本,动态添加 // if(currentFood.GetComponent<Food>() == null) // { // currentFood.AddComponent<Food>(); // } } // 提供给Board获取当前食物的接口 public Food GetCurrentFood() { return currentFood?.GetComponent<Food>(); } }
2. 修复Board脚本的空引用异常
问题根源:Board中的clone变量未被赋值,导致调用GetComponent<Food>()时为空。
代码修改:通过Spawner获取食物实例
public class Board : MonoBehaviour { // 新增:引用FoodSpawner对象 public FoodSpawner foodSpawner; // 删除原有的public Food clone; // ... 其他代码保持不变 ... public void ClearedOneLine() { currentScore += scoreOneLine; Food currentFood = foodSpawner.GetCurrentFood(); if(currentFood != null) { currentFood.TakeDamage(10); } else { Debug.LogWarning("没有可攻击的食物对象!"); } } // 同理修改其余Cleared方法 public void ClearedTwoLine() { currentScore += scoreTwoLine; Food currentFood = foodSpawner.GetCurrentFood(); if(currentFood != null) currentFood.TakeDamage(20); } public void ClearedThreeLine() { currentScore += scoreThreeLine; Food currentFood = foodSpawner.GetCurrentFood(); if(currentFood != null) currentFood.TakeDamage(40); } public void ClearedFourLine() { currentScore += scoreFourLine; Food currentFood = foodSpawner.GetCurrentFood(); if(currentFood != null) currentFood.TakeDamage(80); } }
最终配置步骤
- 创建空GameObject命名为
FoodSpawner,挂载FoodSpawner脚本,并将食物预制体拖入foodPrefabs数组。 - 在Board脚本的检查器中,将
FoodSpawner对象拖入foodSpawner字段。 - 确保
Food脚本仅挂载在食物预制体上,或由FoodSpawner动态添加。
内容的提问来源于stack exchange,提问作者Anend
相关产品推荐
相关产品推荐

