Unity小行星生成出现NullReferenceException等错误,求原因分析
小行星游戏生成逻辑错误排查
我正在制作一款小行星游戏,尝试在屏幕四边的中心位置各生成1颗小行星。运行代码时出现两个错误:
- NullReferenceException: Object reference not set to an instance of an object (UnityEditor.PropertyHandler.isArrayReordable)
- Should not be capturing when there is a hotcontrol
我已尝试将实例化对象存入列表并从中获取组件,但仍出现相同错误,希望有人能指出错误原因。
SpawnerScript 代码
[SerializeField] GameObject prefabAsteroid; List<GameObject> asteroids = new List<GameObject>(); List<Vector3> screenSides = new List<Vector3>(); // Start is called before the first frame update void Start() { //get screen numbers float screenHeight = ScreenUtils.ScreenTop - ScreenUtils.ScreenBottom; float screenWidth = ScreenUtils.ScreenRight - ScreenUtils.ScreenLeft; //collect all screen sides screenSides.Add(new Vector2(ScreenUtils.ScreenLeft,screenHeight/2)); screenSides.Add(new Vector2(ScreenUtils.ScreenTop, screenWidth / 2)); screenSides.Add(new Vector2(ScreenUtils.ScreenRight, screenHeight / 2)); screenSides.Add(new Vector2(ScreenUtils.ScreenBottom, screenWidth / 2)); //loop through each direction(Up,Left,Down,Right) and //Instantiate asteroid on center of each side. int i = 0; foreach (Direction dir in System.Enum.GetValues(typeof(Direction))) { GameObject pa = Instantiate<GameObject>(prefabAsteroid); //add to list asteroids.Add(pa); pa.GetComponent<Asteroid>().Initialize(dir, screenSides[i]); i++; } }
Asteroid 脚本 Initialize 方法代码
public void Initialize(Direction direction, Vector2 location) { transform.position = location; float angle = Random.Range(0 * Mathf.Deg2Rad, 30 * Mathf.Deg2Rad); Vector2 forceMagnitude = new Vector2(Random.Range(minImpulse, maxImpulse), Random.Range(minImpulse, maxImpulse)); if(direction == Direction.Right) { angle +=-15*Mathf.Deg2Rad; } else if (direction == Direction.Left) { angle +=165 * Mathf.Deg2Rad; } else if (direction == Direction.Up) { angle += 75 * Mathf.Deg2Rad; } else if (direction == Direction.Down) { angle += 255 * Mathf.Deg2Rad; } Vector2 moveDirection = new Vector2(Mathf.Cos(angle), Mathf.Sin(angle)); rb.AddForce(forceMagnitude * moveDirection, ForceMode2D.Impulse); }
错误原因及解决方案
1. NullReferenceException 问题
- 预制体未赋值:检查 Inspector 面板中,SpawnerScript 组件的
prefabAsteroid是否拖拽了正确的小行星预制体,未赋值会导致Instantiate返回null,后续调用组件方法报错。 - Asteroid 组件缺失:确认小行星预制体上挂载了
Asteroid脚本,否则GetComponent<Asteroid>()会返回null,调用Initialize时触发空引用。 - Rigidbody2D 未初始化:在
Asteroid脚本中,rb变量需要提前获取组件,比如在Awake()中添加rb = GetComponent<Rigidbody2D>();,否则rb.AddForce()会报错。 - ScreenUtils 数值异常:如果
ScreenUtils是自定义类,检查ScreenTop、ScreenBottom等属性是否正确计算了屏幕边界,空值或错误值会导致坐标计算异常。 - 枚举与列表数量不匹配:确保
Direction枚举只有4个值(Up、Left、Down、Right),否则循环时i会超出screenSides的索引范围。
2. "Should not be capturing when there is a hotcontrol" 问题
这是Unity编辑器的UI交互冲突错误,解决方式:
- 运行游戏前点击编辑器空白区域,取消所有选中或拖拽操作。
- 暂时禁用第三方Editor扩展或自定义Editor脚本,排查是否有脚本干扰编辑器交互。
代码优化建议
- 修正屏幕边界坐标计算:原代码中四边中心坐标逻辑错误,正确的计算方式应为:
// 左边缘中心 screenSides.Add(new Vector2(ScreenUtils.ScreenLeft, (ScreenUtils.ScreenTop + ScreenUtils.ScreenBottom) / 2)); // 上边缘中心 screenSides.Add(new Vector2((ScreenUtils.ScreenRight + ScreenUtils.ScreenLeft) / 2, ScreenUtils.ScreenTop)); // 右边缘中心 screenSides.Add(new Vector2(ScreenUtils.ScreenRight, (ScreenUtils.ScreenTop + ScreenUtils.ScreenBottom) / 2)); // 下边缘中心 screenSides.Add(new Vector2((ScreenUtils.ScreenRight + ScreenUtils.ScreenLeft) / 2, ScreenUtils.ScreenBottom));
- 添加空值检查:在获取组件时增加空值判断,避免崩溃:
Asteroid asteroidComp = pa.GetComponent<Asteroid>(); if (asteroidComp != null) { asteroidComp.Initialize(dir, screenSides[i]); } else { Debug.LogError("预制体缺少Asteroid组件"); }
内容的提问来源于stack exchange,提问作者Zachary.S
相关产品推荐
相关产品推荐

