Unity开发疑问:销毁Enemy GameObject后为何无法实例化Scrap?
让我们一步步排查你遇到的问题,找出为什么Scrap对象无法正常生成:
1. 最关键的问题:销毁敌人与生成Scrap的顺序颠倒了
在EnemyDestroyed.cs的OnTriggerEnter方法里,你先执行了Destroy(gameObject)销毁敌人,再调用SS.SpawnScraps()。这会导致当生成逻辑执行时,敌人对象已经被销毁,ScrapScript里缓存的Es引用对应的transform已经无效,即使之前Es不为null,实例化操作也会因为目标位置/旋转失效而失败(甚至静默不生成)。
修复代码:调整执行顺序,先生成Scrap再销毁敌人:
if(collider.tag == "PlayerBullet" && theBulletType == BulletScript.BulletType.PlayerBullet) { print ("ship destroyed"); Destroy(collider.gameObject); // 先执行生成逻辑,再销毁敌人 SS.SpawnScraps (); Destroy(gameObject); }
2. 检查ScrapSprite数组是否在Inspector中赋值
你的ScrapScript里定义了public GameObject[] ScrapSprite,但如果没有在Unity编辑器中将Scrap预制体拖入这个数组,ScrapSprite[0]会是null。此时Instantiate不会抛出空引用(因为你判断了Es != null),但也不会生成任何对象。
验证&修复:
- 找到挂载了
ScrapScript的游戏对象,在Inspector面板中确认ScrapSprite数组已经添加了至少一个预制体元素。 - 你在
Start方法里写了打印逻辑,可以查看Console面板,如果输出的是null,就说明数组未赋值,赶紧把预制体拖进去。
3. 优化EnemyScript的引用方式(针对动态生成的敌人)
ScrapScript的Start方法中只获取一次EnemyScript引用:Es = GameObject.FindObjectOfType<EnemyScript>();。如果你的敌人是游戏运行后动态生成的,那么ScrapScript的Start可能在敌人创建前就执行了,导致Es始终为null,后续也不会自动更新。
更优的修复方案:直接在调用生成方法时传递敌人的transform,不需要依赖缓存的引用:
修改ScrapScript.cs的SpawnScraps方法:
public void SpawnScraps(Transform spawnTransform) { // 同时检查生成位置和预制体是否有效 if(spawnTransform != null && ScrapSprite[0] != null) { Instantiate (ScrapSprite[0], spawnTransform.position, spawnTransform.rotation); } }
然后修改EnemyDestroyed.cs的调用逻辑:
SS.SpawnScraps (transform); // 直接传递当前敌人的transform
这样不管敌人是静态还是动态生成的,都能准确获取到销毁时的位置,避免引用失效问题。
按以上步骤调整后,应该就能正常生成Scrap拾取物了。
内容的提问来源于stack exchange,提问作者Vapora Light

