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

Unity 2D C#中如何在不同脚本间正确传递变量

错误原因

继承自MonoBehaviour的类禁止通过new关键字手动实例化,这是Unity开发和Java开发的核心差异点:所有MonoBehaviour子类的生命周期都由引擎管控,必须作为组件挂载在场景内的GameObject上,通过GetComponent、FindObjectOfType或者Inspector拖拽的方式获取真实运行的实例。你手动new出来的WispDisplay对象没有绑定场景中的UI引用,也不会触发Start/Update生命周期函数,完全不参与场景运行逻辑,自然无法正常工作。

修复方案
  • 先在编辑器内完成基础配置:把WispDisplay脚本挂载到持有Wisp计数UI文本的GameObject上,将对应的Text组件拖拽到脚本的WispText字段引用槽,初始Wisp数值可直接在Inspector面板设置。
  • 修改两个脚本的逻辑,移除错误的new实例化逻辑,优先通过Inspector拖拽赋值引用,减少运行时查找开销。

修正后的拾取脚本 WispCode

public class WispCode : MonoBehaviour
{
    // 直接在Inspector面板拖拽挂载了WispDisplay的对象赋值,无需new
    public WispDisplay wd;
    
    private void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Player"))
        {
            // 兜底逻辑:如果忘记在Inspector拖引用,运行时自动查找场景中的WispDisplay实例
            if (wd == null)
            {
                wd = FindObjectOfType<WispDisplay>();
            }
            wd.setWisp(wd.getWisp() + 1);
            Destroy(gameObject);
        }
    }
}

优化后的UI显示脚本 WispDisplay

原脚本每帧刷新文本的写法会产生不必要的性能开销,改为数值更新时主动刷新即可:

using UnityEngine.UI;
public class WispDisplay : MonoBehaviour
{
    public int Wisp = 5;
    public Text WispText;
    
    void Start()
    {
        RefreshWispText();
    }
    
    public int getWisp()
    {
        return Wisp;
    }
    
    public void setWisp(int newWisp)
    {
        Wisp = newWisp;
        RefreshWispText();
    }

    private void RefreshWispText()
    {
        WispText.text = "Wisp: " + Wisp.ToString();
    }
}
注意事项
  • 标签判断优先用CompareTag方法,直接用==对比tag字符串性能更低,且拼写错误时不会抛出提示,排查问题难度更高。
  • 非必要不要在运行时用FindObjectOfType查找对象,场景物体较多时该方法开销很高,Inspector拖拽赋值是最高效稳定的方案。
  • 只要类继承了MonoBehaviour,就永远不要手动写new 类名()来创建实例。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 06:09:29