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

C#不使用static跨类访问变量报CS0120错误解决方案

问题原因

你遇到的CS0120报错核心原因是:非静态的字段、方法属于类的具体实例(对象),不能直接通过类名调用。
你之前用static能跑是因为静态成员是类级别的,不需要实例就能直接访问,但全局滥用静态确实会导致代码耦合度高、生命周期不可控、场景切换数据残留等问题,不符合面向对象的编码规范。
你写的generalManager.getEggs()是直接用类名调用非静态方法,编译器无法定位你要访问的是哪个generalManager对象里的eggs数据,才会抛出这个错误。

正确实现方案(Unity环境下,无需static)

Unity中跨MonoBehaviour类访问成员的核心逻辑是:先拿到目标类挂载在场景物体上的实例引用,再通过引用调用getter/setter操作变量。

第一步:修正GeneralManager脚本

注意Unity要求C#脚本文件名必须和类名完全一致,所以脚本要命名为GeneralManager.cs:

using UnityEngine;

public class GeneralManager : MonoBehaviour
{
    // 私有字段加[SerializeField]可在Inspector面板编辑,比public字段更安全
    [SerializeField] private float _eggs;

    // C#标准属性实现get/set,替代手写getEggs/setEggs方法
    public float Eggs
    {
        get => _eggs;
        set => _eggs = value;
    }
}

第二步:在GameManager中获取实例并访问

两种最常用的获取引用方式,选一种即可:

方式1:Inspector拖拽赋值(推荐,耦合最低)

脚本写好后,在Inspector面板把挂载了GeneralManager脚本的场景物体,拖到GameManager组件的对应字段上完成赋值,运行时就可以直接访问:

using UnityEngine;

public class GameManager : MonoBehaviour
{
    // 拖拽赋值后,这个字段就持有了GeneralManager的实例引用
    [SerializeField] private GeneralManager _generalManager;

    private void Start()
    {
        // 取值
        float currentEggCount = _generalManager.Eggs;
        Debug.Log($"当前鸡蛋数量:{currentEggCount}");

        // 赋值
        _generalManager.Eggs = 15f;
    }
}

方式2:运行时动态获取

如果不想手动拖拽,可以在生命周期函数里动态查找获取实例:

using UnityEngine;

public class GameManager : MonoBehaviour
{
    private GeneralManager _generalManager;

    private void Awake()
    {
        // 如果GeneralManager和GameManager挂在同一个GameObject上,用这行
        _generalManager = GetComponent<GeneralManager>();

        // 如果GeneralManager挂在场景中名为"ManagerRoot"的独立GameObject上,用这行
        // _generalManager = GameObject.Find("ManagerRoot").GetComponent<GeneralManager>();
    }

    private void Start()
    {
        // 判空避免空引用报错
        if (_generalManager == null)
        {
            Debug.LogError("未找到GeneralManager实例,请检查脚本挂载配置");
            return;
        }

        // 取值
        float eggs = _generalManager.Eggs;
        // 赋值
        _generalManager.Eggs = 20f;
    }
}

注意事项

  • 不要图省事把所有Manager都做成全局单例,这种用法本质和滥用static区别不大,能通过传引用解决的场景优先用引用,代码可维护性更高。
  • 面向对象的核心规则是:类是创建对象的模板,非静态成员存储在具体实例中,必须拿到实例引用才能访问,直接通过类名只能访问静态成员。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:36:22