You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity小行星生成出现NullReferenceException等错误,求原因分析

小行星游戏生成逻辑错误排查

我正在制作一款小行星游戏,尝试在屏幕四边的中心位置各生成1颗小行星。运行代码时出现两个错误:

  1. NullReferenceException: Object reference not set to an instance of an object (UnityEditor.PropertyHandler.isArrayReordable)
  2. 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 16:35:22