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

Unity静态方法创建GameObject后,Start()中类引用为何丢失?

问题分析与解决方案

你遇到的问题核心是实例化对象与赋值对象不匹配,导致场景中实际运行的Hero实例没有被正确赋值。我们来拆解一下问题所在:

问题根源

在你的Spawn静态方法里,存在一个关键逻辑错误:

  1. 你先通过MovableStrategicObject.Spawn(prefabPath, tile)得到了对象o
  2. 接着调用Instantiate(o, ...)生成了一个新的游戏对象,但没有保存这个新实例的引用
  3. 之后把heroName、conrtollingPlayer等字段赋值给了原来的o对象,而非刚实例化出来的新对象
  4. 场景中实际执行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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:10:11