在Update中仅从另一个脚本调用一次函数

时间:2017-07-15 18:46:35

标签: c# unity3d timer

我在使用倒数计时器功能时出现问题。在我的GameManager脚本中,我检查场景名称并检查空闲使用情况(没有鼠标移动/没有点击),并在我的CountdownTimer脚本中启动一个函数,该函数使用函数StartPreCountTimer()倒计时空闲时间量。一旦该计时器达到零,它就会实例化一个倒计时对话框并启动IEnumerator RunTimer(),用户可以取消继续播放或让它达到零,此时游戏重置并返回到介绍屏幕。

我遇到的问题是在preount步骤。 GameManager脚本每帧保持调用StartPreCountTimer(),这显然可以防止倒计时完成,因为它会重新启动每一帧。我该如何解决?如何从Update中调用该函数一次?

GameManager脚本

using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour 
{
    public static GameManager gameManagerInstance = null; // Create Singleton

    public GameObject loader;
    public GameObject countdownTimer;

    public Color defaultBackgroundColor;                 
    public Object startingScene;
    public GameObject timeOutWarningDialog;
    public float countdownLength;
    public float countdownDelay;

    private Vector3 prevMousePosition;
    private CountdownTimer countdownInstance;
    private Scene currentScene;
    private GameObject gameManager;
    private GameObject canvas;

    public static string animalDataFilePathJSON;
    public static string animalDataFilePathTex;

    void Awake()
    {
        if (gameManagerInstance == null)
            gameManagerInstance = this;
        else if (gameManagerInstance != null)
            Destroy(gameObject);
        DontDestroyOnLoad(gameObject);
        gameManager = GameObject.FindGameObjectWithTag("GameManager");

        // get and store JSON and Tex filepaths defined in Loader script
        animalDataFilePathJSON = GameObject.FindGameObjectWithTag("Loader").GetComponent<Loader>().animalDataFilePathJSON;
        animalDataFilePathTex = GameObject.FindGameObjectWithTag("Loader").GetComponent<Loader>().animalDataFilePathTex;
    }

    void Start()
    {
        prevMousePosition = Input.mousePosition;
        currentScene = SceneManager.GetActiveScene();

        countdownInstance = countdownTimer.GetComponent<CountdownTimer>(); // Create an instance of CountdownTimer
    }

    void Update()
    {
        currentScene = SceneManager.GetActiveScene();

        if (currentScene.name != startingScene.name)
        {
            countdownInstance.StartPreCountTimer(); // Start Pre-count Timer

            if (Input.GetMouseButtonDown(0) || Input.mousePosition != prevMousePosition)
            {
                countdownInstance.StartPreCountTimer(); // Start Pre-count Timer

                if (timeOutWarningDialog != null)
                    timeOutWarningDialog.SetActive(false);
            }
            prevMousePosition = Input.mousePosition;
        }
    }
}

CountdownTimer脚本

using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;

public class CountdownTimer : MonoBehaviour {

    public GameObject timeOutWarningDialog;
    public float countdownLength;
    public float countdownDelay;
    public Object startingScene;

    private float countdownInterval = 1;
    private GameObject countdownTimer;
    private IEnumerator counter;
    private Button stopCountButton;
    private Text timerTextField;
    private GameObject timerInstance;
    private GameObject canvas;

    // GAME TIMER

    public void StartPreCountTimer()
    {
        CancelInvoke();
        if (GameObject.FindGameObjectWithTag("Timer") == null)
            Invoke("ShowRestartWarning", countdownDelay);
    }

    void ShowRestartWarning()
    {
        canvas = GameObject.FindGameObjectWithTag("Canvas");

        timerInstance = Instantiate(timeOutWarningDialog); // instantiate timeout warning dialog
        timerInstance.transform.SetParent(canvas.transform, false);
        timerInstance.SetActive(true);

        Text[] textFields = timerInstance.GetComponentsInChildren<Text>(true); // get reference to timer textfields
        timerTextField = textFields[2]; // access and assign countdown textfield

        stopCountButton = timerInstance.GetComponentInChildren<Button>(); // get reference to keep playing button
        stopCountButton.onClick.AddListener(StopTimer); // add button listener

        if (timerInstance.activeSelf == true)
        {
            counter = RunTimer(countdownLength); // create new reference to counter, resets countdown to countdownLength
            StartCoroutine(counter);
        }
    }

    IEnumerator RunTimer(float seconds)
    {
        float s = seconds;
        while (s > -1)
        {
            if (timerTextField != null)
                timerTextField.text = s.ToString();
            yield return new WaitForSeconds(countdownInterval);
            s -= countdownInterval;
        }

        if (s == -1)
        {
            RestartGame();
        }
    }

    void StopTimer()
    {
        StopCoroutine(counter);
        Destroy(timerInstance);
    }

    void RestartGame()
    {
        SceneManager.LoadScene(startingScene.name);
    }
}

0 个答案:

没有答案