【问题标题】:Where to initialize a static variable in Unity?Unity中的静态变量在哪里初始化?
【发布时间】:2019-11-18 09:47:49
【问题描述】:

我在一个类中使用一个静态变量,但问题是它需要另一个类的另一个值作为它的初始值(参见代码 sn-p)。我想在 Start 函数中初始化它。但是(如果我错了,请纠正我)这意味着它将为对象的每个实例重新初始化,这是多余的,因为我希望在创建具有 UnitManager 的第一个 Unit 时只初始化一次该变量。

所以我的问题是在什么地方初始化这个变量被认为是一个好习惯?

谢谢!

代码:

public class UnitManager : MonoBehaviour
{
    // Distance in terms of Unity Unity from the target position to stop for units
    static float distanceToStop;
    private void Start()
    {
        if (WorldCoordController.OneUnityMeterToRealWorld < 10)
        {
            distanceToStop = 1 / WorldCoordController.OneUnityMeterToRealWorld;
        }

        else
        {
            distanceToStop = 0.1f;
        }
    }
}

【问题讨论】:

  • Initialize WorldCoordController.OneUnityMeterToRealWorld in Awake(), awake 在启动前被调用,如果这不符合您的需要您可以设置脚本执行顺序:docs.unity3d.com/Manual/class-MonoManager.html
  • 感谢您的回复!但我也想只初始化一次 distanceToStop 值。
  • 然后把它放在一个静态构造函数中,你仍然可以覆盖之后的值,所以你应该把它标记为只读
  • 这个类是从 MonoBehaviour 派生的,如果我没记错的话,不建议在 MonoBehaviour 派生类中包含构造函数。
  • 确实不推荐,但有一些情况下还不错,但是为什么脚本执行顺序一开始就不满足你呢?

标签: c# unity3d variables static


【解决方案1】:
public class UnitManager : MonoBehaviour
{
    // Distance in terms of Unity Unity from the target position to stop for units
    static float distanceToStop;
    static bool distanceSet = false;
    private void Start()
    {
        // If the distance is not set
        if(!this.distanceSet)
        {
            if (WorldCoordController.OneUnityMeterToRealWorld < 10)
            {
                distanceToStop = 1 / WorldCoordController.OneUnityMeterToRealWorld;
            } else {
                distanceToStop = 0.1f;
            }

            this.distanceSet = true;
        }
    }

“distanceSet”布尔值将在实例之间共享,因此您只需在第一个实例上设置距离:D

【讨论】:

  • 感谢您的回复!我也使用了相同的方式,但我正在寻找一种更优雅的方式。 :D 不过还是谢谢!
【解决方案2】:

也许考虑使用 Init() 调用 UnitManager;使用它需要的 WorldCoordController 值。

【讨论】:

  • WorldCoordController 不知道 UnitManager 类的初始化时间和方式。
  • 这对我的回答并没有太大影响。您仍然应该尽可能避免使用 Unity 的基本启动和唤醒功能。要获取世界控制器,您可以创建它的静态实例,您可以随时获取它,如下面的@S.Fragkos 所述。
【解决方案3】:

您可以创建一个自定义类,该类将对其自身具有静态引用,并且只初始化一次(第一次被调用时)。 示例:

public class ExampleClass
{
    //Static Functionality
    private static ExampleClass _inst;
    public static ExampleClass Instance
    {
        get
        {
            if (_inst is null)
            {
                _inst = new ExampleClass();
                _inst.Init();
            }
            return _inst;
        }

    }


    //Class Values
    public static int MyValue;

    public int Value1;

    //private Constructor 
    private ExampleClass()
    {

    }


    //initialize values here
    private void Init()
    {

    }

}

然后你可以像这样访问这些值:

//This will return the Value1 int
ExampleClass.Instance.Value1

//This will return the static MyValue int
ExampleClass.MyValue

根据您的要求,您只能使用上述示例中的 Value1 并在 init 中仅将其初始化一次。如果您希望该值仅可用于读取,则可以使用“私有集”运算符将其设置为属性。

这样做的好处是您不需要 Start 或 Monobehaviour,因此它可以在任何地方工作,而无需在游戏对象中使用。

希望这对您有所帮助,祝您编码愉快!

【讨论】:

  • 我无法安静地理解您的解决方案。这个 UnitManager 类存在于许多不同的对象上。 (我意识到它的命名不正确)而且我需要从 MonoBehaviour 派生,因为它使用了许多 Unity 功能。
  • @AliİhsanElmas 我所描述的是单例设计模式(您可以在互联网上找到大量有关它的信息)。关于你的 MonoBehaviour 继承,如果你需要 Start、Awake、Update 等......那么我认为你不能使用它,但你可以使用 UnityEngine 参考以及它附带的东西(参考、函数、一切)。
猜你喜欢
  • 2011-02-06
  • 2015-07-11
  • 1970-01-01
  • 2017-05-13
  • 2011-08-22
  • 2010-12-22
  • 1970-01-01
  • 2023-01-20
相关资源
最近更新 更多