首页 > 解决方案 > How to manage multiple timers to control various elements of Unity game?

问题描述

My end goal is to have a tile game with Home tile and surrounding tiles- character moves to highlighted square and back to home square at the speed in which the game is presented. I am trying to design a game with few speed modes. Two Instances being-

  1. HomeTile highlighted then Tile 3 (highlighted for x seconds) then HomeTile then Tile 8 (highlighted for x seconds) then HomeTile.... so on. The x seconds can be increased or decreased by a UI slider. Points are given as the charachter enters the correct highlighted tile.
  2. HomeTile highlighted then Tile 3 (highlighted for x seconds) & character needs to be on this tile for y seconds to get point then HomeTile highlighted then Tile 8 (highlighted for x seconds) and character stays for y seconds for point then HomeTile... and so on... Again speed is controlled by UI slider.

y= 80% of x seconds.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System.IO;
using System;
using System.Collections.Generic;

public class MultiDirection_short : MonoBehaviour
{
    public Slider speedSlider;
    public int scoreValue;
    public static bool onTargetFlag = false; // flag to indicate character on target
    public static bool failedTargetReachFlag = false; // flag to indicate character did not reach the target

    public int currentRowNumber;
    public int randomNumber;

    private Double elapsedTime;
    public static float timeLefts;
    public float timeBeforeChange;

    private static TimeSpan time1, time2, homeTime, dwellTime, requiredDwellTime;
    private DateTime time12, startTime, dwellTimeStart;
    private bool homeSquareLit = true; // To indicate if the home Tile is on.
    private bool targetTile = false; //to indicate if any of the target tiles are on.

    void Start()
    {
        startTime = DateTime.Now; // time declared at the start of the program. This is valid for first iteration. 
    }

    void Update()
    {
        timeBeforeChange = Scaler.speedPres;
        time2 = new TimeSpan(0, 0, (int)timeBeforeChange);
        Debug.Log("TimeBeforeChange: " + (int)timeBeforeChange);
        homeTime = new TimeSpan(0, 0, 1);
        Debug.Log("t2/2=" + time2.Seconds / 2);

        elapsedTime = (timeLefts % 60) - DateTime.Now.Second;
        time12 = DateTime.Now; // the current time

        TimeSpan time1 = time12 - startTime;
        Debug.Log("Time1: " + time1);

        if (gameManager.Instance.Play)
        {
            if (!gameManager.Instance.Paused)
            {
                Scaler.speedPres = speedSlider.value;  // to ensure the values dont change randomly before the play button is pressed. 
            }
        }

        if (gameManager.Instance.Paused)
        {
            Scaler.speedPres = speedSlider.value;  // to ensure the values dont change randomly before the play button is pressed. 
            randomNumber = 0;

            //highlight the home square and make everything else white
            HomeTile.GetComponent<Renderer>().material.color = Color.grey;
            FrontLeftTile.GetComponent<Renderer>().material.color = Color.white;
            FrontRightTile.GetComponent<Renderer>().material.color = Color.white;
        }

        if ((time1 > homeTime) && (homeSquareLit)) // TARGET SQUARE lit
        {
            randomNumber = UnityEngine.Random.Range(1, 10);

            //Defining the conditions in which the squares light up- EACH CASE per square
            switch ((randomNumber))
            {
                case 1:
                    FrontLeftTile.GetComponent<Renderer>().material.color = Color.blue;//1 
                    HomeTile.GetComponent<Renderer>().material.color = Color.white;//0
                    FrontRightTile.GetComponent<Renderer>().material.color = Color.white;//4

                    break;
                case 2:
                    FrontRightTile.GetComponent<Renderer>().material.color = Color.red;//2
                    HomeTile.GetComponent<Renderer>().material.color = Color.white;//0 
                    FrontLeftTile.GetComponent<Renderer>().material.color = Color.white;//3

                    break;

                default:
                    targetTile = false;
                    homeSquareLit = false;
                    break;
            }
            startTime = time12;
            Debug.Log("startTime: " + startTime);

        }

        if ((time1 > time2) && (!homeSquareLit)) // HOME SQUARE BLOCK
        {
            Debug.Log("inside home square block, randNum_ now:  " + randomNumber);

            switch ((randomNumber))
            {
                case 1:

                    HomeTile.GetComponent<Renderer>().material.color = Color.blue;
                    FrontLeftTile.GetComponent<Renderer>().material.color = Color.white;//3
                    FrontRightTile.GetComponent<Renderer>().material.color = Color.white;//4
                    break;

                case 2:

                    HomeTile.GetComponent<Renderer>().material.color = Color.red;
                    FrontLeftTile.GetComponent<Renderer>().material.color = Color.white;//3
                    FrontRightTile.GetComponent<Renderer>().material.color = Color.white;//4
                default:
                    break;
            }
            startTime = time12;
        }
    }

void OnTriggerEnter(Collider other)
{
    dwellTimeStart = DateTime.Now;
    requiredDwellTime = new TimeSpan(0, 0, 1);
    DateTime requiredDwellTime = 1.5f;
    if ((dwellTimeStart.Second > requiredDwellTime.Seconds)) // TARGET SQUARE lit
    {//trigger or change color of tile as above.
}

So for the First Scenario- This code works fine as is.. However when I reduce the time on the slider below 2 seconds then the the half equals 0 as int. Then the game stops working with the if statements... Or if statements are removed then it works so fast that it looks like its flickering between the targets.

Am I supposed to use a different timer? AM i mistakenly taking update time?

标签: c#unity3dtimer

解决方案


public static float timeLefts;
public float timeBeforeChange;
private static TimeSpan time1, time2, homeTime, dwellTime, requiredDwellTime;
private DateTime time12, startTime, dwellTimeStart;

天哪。您有 10 个计时器值要在单个 class中跟踪。这不是要走的路。

你有两个选择:

  1. 您可以实例化并保存其时间值并根据需要执行任何任务的自定义对象,您将这些对象存储在您每帧更新的列表中。
  2. Coroutines,您说“将此函数作为协程执行”,在该函数内部,您可以执行诸如yield return new WaitForSeconds(5)使该函数的执行暂停 5 秒(或多长时间)之类的事情。

推荐阅读