它们具有完全相同的代码行,但第二行不起作用。第一次倒计时应该在游戏首次开始时运行,而第二次倒计时则在正在进行战斗时运行。
这是第一个按预期工作的:
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;
}
}
这个应该在每次发生战斗时运行,但它根本不起作用。无法弄清楚为什么。
你在开始时将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
一样,所以你可以在倒计时结束时简单地执行任何回调方法。
然后在Inspector中添加一个回调,或者你可以从脚本中设置它
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);
}
}