【问题标题】:access global game data in Unity (C#)在 Unity (C#) 中访问全局游戏数据
【发布时间】:2020-01-06 04:09:28
【问题描述】:

我对 Unity 和 C# 完全陌生。我尝试使用我的 OOP 知识来构建一些东西来保存我的游戏的数据和“业务逻辑”。

游戏大纲:一些方块掉下来,可以在下落时移动,最后落到窗格上。

立方体是预制对象,必须对其进行跟踪以计算分数、检测不受欢迎的行为等。

场景是:

  • 1 个空游戏对象 = CubeSpanPoint + CubeSpawn 脚本
  • 1 个空 GameObject = GameMain + GameMain 脚本(保存游戏设置和业务逻辑)
  • 1 个预制立方体 + MoveScript + FallingScript

GameMain.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class GameMain : MonoBehaviour
{
    private float CubeSpawnSpeed = 3.0f;  //seconds
    private int score = 0;

    // construtor
    public GameMain()
    {
    }

    // getter: is falling allowed for the cube
    public bool getFalling(){
        return true;
    }

    // getter cube spawn speed
    public float getCubeSpawnSpeed(){
        return this.CubeSpawnSpeed;
    }
}

FallingScript 必须从 MainGame(getter)、FallingSpeed 和下降权限中获取数据。

CubeFalling.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoxFalling : MonoBehaviour
{
    public GameMain gameMain;

    void Start(){
        // an attempt to get the instance this way, but fail
        // GameMain main = GameObject.Find("GameMain").GetComponent<GameMain>();
    }

    void Update()
    {
        // Is still falling allowed?
        if (gameMain.getFalling()){
            transform.Translate(Vector3.down);
        }
    }
}

但这会产生错误NullReferenceException: Object reference not set to an instance of an object BoxFalling.Update ()

也不能通过将 GameMain 游戏对象拉到 CubeFalling 脚本中的 gameMain 插槽到同名的公共变量来使用检查器。

我一直期待的是,我必须将 GameMain scipt 拉到 GameMain 游戏对象,这相当于使用 new GameMain 进行实例化。为了重用这个实例,我必须将 GameObject 拉到下降脚本中的 GameMain 变量中。但这不起作用。

【问题讨论】:

标签: c# oop unity3d


【解决方案1】:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class GameMain : MonoBehaviour
{   private static GameMain _gameMain;
    public static GameMain Instance {get {return _gameMain;}}
    void Awake()
    {
        _gameMain = this;
    }

    // getter: is falling allowed for the cube
    public bool getFalling(){
        return true;
    }
}

BoxFalling.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class BoxFalling : MonoBehaviour
{
    void Update()
    {
        // Is still falling allowed?
        // now you can got it
        if (GameMain.Instance.getFalling()){
            transform.Translate(Vector3.down);
        }
    }
}

【讨论】:

  • 太棒了。这对我帮助很大!有一点我不明白。为什么 GameMain 不需要实例化?发生这种情况是因为脚本位于 GameMain 游戏对象上吗?
  • @row 是的,Monobehaivor 依赖于“GameObject”生命周期,所以把它放在一个存在的 GameObject 上。并确保此 GameObject 已启用。 docs.unity3d.com/Manual/ExecutionOrder.html 或者没有 Monobehaivor ,只需要写一个“单例模式”类。
【解决方案2】:

您可以使用Singleton 访问GameMain。当您将来在运行时实例化更多多维数据集时,这将非常方便。

但您也应该能够使用

检索GameMain
gameMain = GameObject.Find("GameMain").getComponent<GameMain>();

也许你拼错了什么?将找不到停用的对象。

(编辑:这种方法搜索层次结构中的所有游戏对象。至少缓存结果。在Unity's documentation查看更多信息)

【讨论】:

  • GameObject.Find 搜索整个场景层次结构,因此使用单例/静态实例访问会更好
  • 你是对的,但它应该仍然有效。我认为知道出了什么问题会很有趣。
  • 我的猜测是他实际上并没有将带有 GameMain 的空游戏对象命名为“GameMain”,所以它没有在层次结构中找到任何东西
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
相关资源
最近更新 更多