Unity静态方法创建GameObject后,Start()中类引用为何丢失?
问题分析与解决方案
你遇到的问题核心是实例化对象与赋值对象不匹配,导致场景中实际运行的Hero实例没有被正确赋值。我们来拆解一下问题所在:
问题根源
在你的Spawn静态方法里,存在一个关键逻辑错误:
- 你先通过
MovableStrategicObject.Spawn(prefabPath, tile)得到了对象o - 接着调用
Instantiate(o, ...)生成了一个新的游戏对象,但没有保存这个新实例的引用 - 之后把
heroName、conrtollingPlayer等字段赋值给了原来的o对象,而非刚实例化出来的新对象 - 场景中实际执行
Start()方法的是Instantiate生成的新实例,这个实例完全没被赋值,所以所有字段都是null
另外还有个小细节:你遍历组件找Hero的方式可以简化,直接用o.GetComponent<Hero>()就行,不用遍历所有MonoBehaviour。
修正后的代码
public class Hero : MovableStrategicObject { public string heroName; public Player controllingPlayer; // 修正拼写错误:conrtolling → controlling protected new void Start() { base.Start(); Debug.Log("2 - Hero name: " + heroName); Debug.Log("2 - Controlling player exists: " + (controllingPlayer != null)); Debug.Log("2 - Tile exists: " + (currentTile != null)); } public static GameObject Spawn(Tile tile, Player player, string name, string prefabPath = "Heroes/HeroPrefab") { // 假设MovableStrategicObject.Spawn是加载预制体(而非实例化),如果它已经实例化对象,需去掉后续Instantiate GameObject prefab = MovableStrategicObject.Spawn(prefabPath, tile); if (prefab == null) { Debug.LogError("Failed to load prefab from path: " + prefabPath); return null; } Hero heroPrefab = prefab.GetComponent<Hero>(); if (heroPrefab == null) { Debug.Log("Object (" + prefabPath + ") has no Hero script attached."); return null; } // 实例化新对象并保存引用 GameObject spawnedHero = Instantiate(prefab, (Vector2)tile.gameObject.transform.position, Quaternion.identity); Hero heroComponent = spawnedHero.GetComponent<Hero>(); // 给新实例的字段赋值 heroComponent.controllingPlayer = player; heroComponent.heroName = name; heroComponent.currentTile = tile; // 手动设置继承的属性(如果父类Spawn没处理) Debug.Log("1 - Hero name: " + heroComponent.heroName); Debug.Log("1 - Controlling player exists: " + (heroComponent.controllingPlayer != null)); Debug.Log("1 - Tile exists: " + (heroComponent.currentTile != null)); return spawnedHero; } }
额外注意点
- 修正了字段名拼写错误:
conrtollingPlayer→controllingPlayer(拼写错误可能导致后续其他逻辑异常) - 确认
MovableStrategicObject.Spawn的行为:如果这个方法已经完成了实例化操作,那你需要去掉后续的Instantiate,直接对Spawn返回的对象赋值即可,避免重复实例化 - 建议在赋值时直接保存组件引用,避免多次调用
GetComponent<Hero>(),提升代码性能
内容的提问来源于stack exchange,提问作者Keyshon
相关产品推荐
相关产品推荐

