Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何检查游戏是否在主菜单后启动?_C#_Unity3d - Fatal编程技术网

C# 如何检查游戏是否在主菜单后启动?

C# 如何检查游戏是否在主菜单后启动?,c#,unity3d,C#,Unity3d,在默认情况下运行游戏时,主菜单场景首先在索引0处加载。 因此,当加载游戏或制作新游戏时,任何加载的场景索引都不是0,表示游戏已启动或加载 我想将此脚本用作管理器脚本,以检测新游戏何时开始或游戏是否加载了主菜单以外的任何内容,以便我可以激活其他脚本中的内容或开始其他脚本中的内容 第一个问题是游戏对象脚本附加到的空游戏对象是否应该在DontDestroyOnLoad上 我如何从其他脚本中使用它 using System.Collections; using System.Collections.Ge

在默认情况下运行游戏时,主菜单场景首先在索引0处加载。 因此,当加载游戏或制作新游戏时,任何加载的场景索引都不是0,表示游戏已启动或加载

我想将此脚本用作管理器脚本,以检测新游戏何时开始或游戏是否加载了主菜单以外的任何内容,以便我可以激活其他脚本中的内容或开始其他脚本中的内容

第一个问题是游戏对象脚本附加到的空游戏对象是否应该在DontDestroyOnLoad上

我如何从其他脚本中使用它

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

public class NewGame : MonoBehaviour
{
    public static bool GameStarted = false; 

    private Scene currentScene;

    // Start is called before the first frame update
    void Start()
    {
        currentScene = SceneManager.GetActiveScene();
    }

    // Update is called once per frame
    void Update()
    {
        if(currentScene.buildIndex != 0 && GameStarted == false)
        {
            GameStarted = true;
        }
    }
}
我想使用的脚本示例如下:

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

public class ScaleRotate : MonoBehaviour
{
    public GameObject objectToScale;
    public Vector3 minScale;
    public Vector3 maxScale;
    public float duration;
    public float rotationAngle = 180.0f;
    public DimLights dimLights;

    private bool scaling = true;
    private bool isInProcess = false;

    private void Start()
    {
        StartCoroutine(dimLights.DimLightsOverTime(2, duration));
        StartCoroutine(ScaleOverSeconds(maxScale, new Vector3(0,rotationAngle,0), duration));
    }

    public IEnumerator ScaleOverSeconds(Vector3 scaleTo, Vector3 rotateTo, float seconds)
    {
        isInProcess = true;
        float elapsedTime = 0;
        Vector3 startingScale = objectToScale.transform.localScale;
        Vector3 startingRotation = objectToScale.transform.localEulerAngles;
        //If you want, you can change axis of rotation or angle or everything you want. But what I do - I rotate by Y-axis for 180 degrees

        while (elapsedTime < seconds)
        {
            objectToScale.transform.localScale = Vector3.Lerp(startingScale, scaleTo, (elapsedTime / seconds));
            objectToScale.transform.localEulerAngles = Vector3.Lerp(startingRotation, rotateTo, (elapsedTime / seconds));

            elapsedTime += Time.deltaTime;
            //You can use yield return null instead of yield return new WaitForEndOfFrame() - this will do the same, but it's easier to write
            yield return null;
        }
        objectToScale.transform.localScale = scaleTo;
        objectToScale.transform.localEulerAngles = rotateTo;
        isInProcess = false;
    }

    private void Update()
    {
        if(NewGame.GameStarted == true)
        {

        }

        if (Input.GetKeyDown(KeyCode.S))
        {
            //Check if object is not changing it's scale right now
            if (!isInProcess)
            {
                //Use if(scaling) instead of if(scaling == true) - this means the same, but it's more readable
                if (scaling)
                {
                    Vector3 rotateTo = objectToScale.transform.localEulerAngles + new Vector3(0, rotationAngle, 0);
                    StartCoroutine(dimLights.DimLightsOverTime(0, duration));
                    StartCoroutine(ScaleOverSeconds(minScale, rotateTo, duration));
                    //Remove scaling = false (we will paste it later)
                }
                //Add there else operator
                else
                {
                    //If you want to change rotation to counterclockwise, change '+' to '-'
                    Vector3 rotateTo = objectToScale.transform.localEulerAngles + new Vector3(0, rotationAngle, 0);
                    StartCoroutine(dimLights.DimLightsOverTime(2, duration));
                    StartCoroutine(ScaleOverSeconds(maxScale, rotateTo, duration));
                }
                //Change scaling value. If you want, you can move this line into ScaleOverSeconds coroutine
                scaling = !scaling;
            }
        }
    }
}

但我仍然不确定如何使用新游戏,以及这是否是检查新游戏开始的逻辑方法?

使用
DontDestroyOnLoad

  • 当场景发生更改时,您将获得另一个实例->您必须确保只存在一个实例

  • 对于已启动的实例,不再调用
    Start

  • 1的解决方案称为Singleton模式,您可以这样做

    public class NewGame : MonoBehaviour
    {
        // Here you store the actual instance
        private static NewGame _instance;
    
        // Public read-only access property
        public static NewGame Instance 
        {
            get
            {
                // if already set simply return directly
                if(_instance) return _instance;
    
                // Otherwise try to find it in the scene
                _instance = FindObjectOfType<NewGame>();
                if(_instance) return _instance;
    
                // Otherwise create it now
                _instance = new GameObject(nameof(NewGame)).AddComponent<NewGame>();
    
                return _instance;
            }
        }
    
        private void Awake()
        {
            if(_instance && _instance != this)
            {
                // There already exist another instance 
                Destroy (this.gameObject);
                return;
            }
    
            // Otherwise this is the active instance and should not be destroyed
            _instance = this;
            DontDestroyOnLoad(this.gameObject);
    
            // Todo solution for 2
        }
    
        ...
    }
    
    因此,您可以在任何其他脚本中简单地访问

    if(NewGame.GameStarted)
    {
        // => buildIndex != 0
    }
    

    我尝试了第二种解决方案,但在get=>行中出现错误,需要无效的表达式项{and;,需要get或set访问器
    public class NewGame : MonoBehaviour
    {
        // Here you store the actual instance
        private static NewGame _instance;
    
        // Public read-only access property
        public static NewGame Instance 
        {
            get
            {
                // if already set simply return directly
                if(_instance) return _instance;
    
                // Otherwise try to find it in the scene
                _instance = FindObjectOfType<NewGame>();
                if(_instance) return _instance;
    
                // Otherwise create it now
                _instance = new GameObject(nameof(NewGame)).AddComponent<NewGame>();
    
                return _instance;
            }
        }
    
        private bool _gameStarted;
        public static bool GameStarted => Instance._gameStarted;
    
        private void Awake()
        {
            if(_instance && _instance != this)
            {
                // There already exist another instance 
                Destroy (this.gameObject);
                return;
            }
    
            // Otherwise this is the active instance and should not be destroyed
            _instance = this;
            DontDestroyOnLoad(this.gameObject);
    
            SceneManager.sceneLoaded += OnSceneLoaded;
    
            // update it once now 
            _gameStarted = SceneManager.GetActiveScene().buildIndex != 0;
        }
    
        void OnSceneLoaded(Scene scene, LoadSceneMode mode)
        {
            _gameStarted = scene.buildIndex != 0;
        }
    }
    
    if(NewGame.GameStarted)
    {
        // => buildIndex != 0
    }