Создал дубликат текста на том же холсте, но второй не работает - PullRequest
0 голосов
/ 21 февраля 2019

У них тоже одинаковые строки кода, но вторая не работает.Первый обратный отсчет должен запускаться при первом запуске игры, а второй - всякий раз, когда идет битва.

Вот первый, который работает как задумано:

public class Countdown : MonoBehaviour
{
    float currentTime=0f;
    float startingTime=5f;
    public string outcome; //This will be the outcome of the random roll that will decide who attacks first

    [SerializeField] Text countdownText;

    void Awake()
    {

        currentTime = startingTime; //setting current time to 5
        System.Random rand = new System.Random(); //choses a random number between 0 and 1
        if (rand.Next(0, 2) == 0) 
        {
            outcome = "Player 1 Attacks First";
        }

        else
        {
            outcome = "Player 2 Attacks First";
        }
    }
    void Update()
    {

        if (currentTime > 3.5)
        {
            Timer();
            countdownText.text = outcome; // Displays the player that starts attacking firtst

        }
        if (currentTime > 0.5&& currentTime<3.5) //Starts the timer from 3
        {
            Timer();
            countdownText.text = currentTime.ToString("0");
        }


            if (currentTime < 0.5)
            {
            Timer();
            countdownText.text = "GO";
            }

            if (currentTime < -0.5)
            {
            countdownText.text = "";
            this.enabled = false;
            }


    }
    void Timer()
    {
        currentTime -= 1 * Time.deltaTime;
    }

}

А вот второй,он просто отображает «0»:

public class CountdownInBattle : MonoBehaviour
{
    float currentTime = 0f;
    float startingTime = 5f;
    [SerializeField] Text countdownText2;

    // Start is called before the first frame update
    void Awake()
    {
        currentTime = startingTime;
        //if (GameObject.Find("Canvas").GetComponent<Countdown>().enabled == true)
        //{
        //    this.enabled = false;
        //}
        Debug.Log("Starting Countdown");
    }

    // Update is called once per frame
    void Update()
    {
        if (currentTime > 0.5 && currentTime < 3.5) //Starts the timer from 3
        {
            Timer();
            countdownText2.text = currentTime.ToString("0");
        }


        if (currentTime < 0.5)
        {
            Timer();
            countdownText2.text = "GO";
        }

        if (currentTime < -0.5)
        {
            countdownText2.text = "";
            this.enabled = false;
        }
    }

    void Timer()
    {
        currentTime -= 1 * Time.deltaTime;
    }
}

Этот должен запускаться каждый раз, когда происходит битва, но он не работает вообще.Не могу понять, почему.

1 Ответ

0 голосов
/ 21 февраля 2019

Вы устанавливаете currentTime на 5f при запуске.

Так что ни одно из ваших условий в Update

if (currentTime > 0.5 && currentTime < 3.5) //Starts the timer from 3
{
    Timer();
    countdownText2.text = currentTime.ToString("0");
}


if (currentTime < 0.5)
{
    Timer();
    countdownText2.text = "GO";
}

if (currentTime < -0.5)
{
    countdownText2.text = "";
    this.enabled = false;
}

никогда не будет соответствовать -> ничего не происходит.

В первом сценарии у вас было дополнительное условие для

if (currentTime > 3.5)
{
    Timer();
    countdownText.text = outcome; // Displays the player that starts attacking firtst
}

, поэтому быстрое решение состояло в том, чтобы либо увеличить это первое условие до

if (currentTime > 0.5 && currentTime <= 5) //Starts the timer from 5

, либо переместить вызов Timer(); вне условий, поскольку он должен называться каждый безусловный кадр


Я настоятельно рекомендую использовать для этого Coroutine , чтобы вы могли просто использоватьодин и тот же компонент для обеих вещей:

public class Countdown : MonoBehaviour
{
    [SerializeField] private Text _countdownText2;

    public UnityEvent OnCountdownFinished;

    public void StartCountdown(int forSeconds)
    {
        Debug.Log("Starting Countdown");
        StartCoroutine(DoCountdown(forSeconds));
    }

    private IEnumerator DoCountdown(int forSeconds)
    {
        int seconds = forSeconds;
        while (seconds > 0)
        {
            // yield means return to the main thread, render the frame
            // and continue this method from this point
            // in the next frame

            // waitForSeconds does as it says ... repeat this return until X seconds have past
            yield return new WaitForSeconds(1);

            // reduce seconds by one
            seconds--;

            // update the text
            _countdownText2.text = seconds.ToString();
        }

        // when done call the callbacks you added
        OnCountdownFinished.Invoke();
    }
}

OnCountdownFinished является UnityEvent и работает так же, как кнопки onClick, так что вы можете просто выполнить любой метод обратного вызова, когдаобратный отсчет завершен.

, а затем добавьте обратный вызов либо в Инспекторе, либо вы можете настроить все это из сценария, например

public class FightController : MonoBehaviour
{
    [SerialiteField] private int _secondsDisplayName;
    [SerializeField] private int _secondsBeforeFight;
    [SerializeField] private int _secondsInFight;

    [SerializeField] private Countdown _beforeCountdown;
    [SerializeField] private Countdown _inFightcountdown;    

    public string outcome;

    private void Awake()
    {
        System.Random rand = new System.Random(); //choses a random number between 0 and 1
        if (rand.Next(0, 2) == 0) 
        {
            outcome = "Player 1 Attacks First";
        }
        else
        {
            outcome = "Player 2 Attacks First";
        }

        // and display the random outcome
        // there is no need to update this every frame
        countdownText.text = outcome;
    }

    private void Start()
    {
        // add a callback what should happen after the first countdown -> start the second
        _beforeCountdown.OnCountdownFinished.AddListener(StartInFightCountdown);

       // maybe also already add the callback what should happen after the second one

       // Now since you want to display the random name for
       // the first two seconds simply use a routine again:
       StartCoroutine(Prepare());
    }

    private IEnumerator Prepare()
    {
        // wait the two seonds, than begin the before countdown at 3
        yield return new WaitForSeconds(_secondsDisplayName);

        // than start the first countdown
        _beforeCountdown.StartCountdown(_secondsBeforeFight);
    }

    private void StartInFightCountdown()
    {
        _inFightcountdown.StartCountdown(_secondsInFight);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...