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

Unity报错:MonoBehaviour构造函数调用Find,已在Start中调用仍报错

Unity 中 GameObject.Find 调用报错排查与解决

错误信息

UnityException: Find 不允许从 MonoBehaviour 构造函数(或实例字段初始化器)中调用,请改为在 Awake 或 Start 中调用。调用来自 MonoBehaviour 'CombatStateMachine'。
请查看 Unity 手册中的“Script Serialization”页面了解更多详情。
CombatStateMachine..ctor () (at Assets/Scripts/BattleStuff/CombatStateMachine.cs:25)

代码情况

你提供的代码显示Find调用确实在Start方法内:

//using Microsoft.Win32;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class CombatStateMachine : MonoBehaviour
{
    public phase currentPhase;
    bool playerCanAct;
    int currentRound;

    public GameObject playerPartyObj;
    public GameObject enemyPartyObj;

    private Queue<string> sentences;

    // Start is called before the first frame update
    void Start()
    {
        currentPhase = phase.start;
        playerCanAct = false;
        currentRound = 0;
        sentences = new Queue<string>();
        playerPartyObj = GameObject.Find("PlayerParty");
        enemyPartyObj = GameObject.Find("EnemyParty");
        StartCoroutine(SetupBattle());
    }

//More code that isn't really relevant AFAICT
}

你已尝试的方案

  • 注释Start中的Find并移至类体
  • 在Start中重新定义对象
  • 给GameObject声明添加[Serializable](提示类型不支持)

问题根源与解决方法

报错指向构造函数/字段初始化阶段调用了Find,但你贴出的代码无此问题,大概率是以下隐藏情况:

1. phase枚举存在违规逻辑

你声明了public phase currentPhase;,如果phase枚举的构造函数或其内部字段的初始化逻辑中间接调用了GameObject.Find,就会触发错误——因为类的字段初始化是在构造函数阶段执行的,currentPhase作为类级字段,初始化时的违规操作会被判定为构造函数内的调用。

  • 排查方法:暂时将public phase currentPhase;替换为public int currentPhase;测试,若报错消失,直接重构phase枚举的逻辑,移除其中涉及Find或其他Unity API的初始化代码。

2. Unity 编译缓存残留

即使你修改了代码,Unity的编译缓存可能保留了旧的违规逻辑(比如之前你曾在字段声明时直接写public GameObject playerPartyObj = GameObject.Find("xxx");)。

  • 解决方法:删除项目根目录下的Library文件夹,重启Unity并重新编译项目。

3. 脚本被重复挂载或存在同名脚本

场景中若有多个对象挂载了CombatStateMachine,或者存在同名的其他脚本,可能某个实例的字段初始化存在违规调用。

  • 排查方法:在Hierarchy面板中搜索CombatStateMachine,检查所有挂载该脚本的对象,确认它们的字段初始化逻辑无问题;同时检查项目中是否有同名脚本文件,避免命名冲突。

4. SetupBattle协程的隐藏问题

虽然你认为其他代码无关,但StartCoroutine(SetupBattle());调用的协程中,如果在第一个yield语句之前调用了GameObject.Find,也可能被判定为构造函数阶段的调用(协程启动时的同步执行部分)。

  • 排查方法:检查SetupBattle协程的开头逻辑,确保所有Find调用都在yield之后执行。

内容的提问来源于stack exchange,提问作者HalfTangible

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 21:23:22