我对C#很新,我试图为敌人AI编写脚本。我想要的是如果" S"关键是按下敌人消失(淡出然后淡化回使用协程)。如果在一段时间内未按任何键,游戏将重置。相反,敌人的Debug.Log重置在开始时出现(这是有意义的,因为它在我的启动函数中。但是,如果我把它置于更新它更新每一帧。我应该使用FixedUpdate吗?我需要一个明确的例子如何这应该去。
public GameObject gameOverPanel;
public float TimeLimit = 10f;
private bool pressS;
private void Update() {
if (Input.GetKeyDown("S")) {
pressS = true;
//Kills Owl
}
//Test
if (!Input.GetKeyDown("S")) { //If key is not pressed within certian time
pressS = false;
//Reset screen Appears
StopCoroutine(Reset());
StartCoroutine(Reset());
}
}
private IEnumerator Reset() {
Debug.Log("Reset Taking place")
yield return new WaitForSeconds(TimeLimit);
//GameOverScreen Appears
gameOverPanel.SetActive(true);
}
答案 0 :(得分:1)
您要求的是使用Coroutines的基于状态的引擎。对于这种特殊情况,有四种状态:
以下代码是您发布的代码的修订版。我重构了Start()
和Update()
Monobehaviours,专注于启动状态引擎并分别监控玩家的输入。
Start()
只需要为状态引擎中的未来操作准备敌人,所以我使用该位置来执行EnemyFadeIn()
协程。
在Update()
之前不会重置输入标志,因此建议所有输入调用都在更新循环中发生。这也是从Start()
Monobehaviour中删除输入处理的原因。您可以在Unity Article for Input中找到有关此内容的更多信息。但是,代码中显示的所有剩余函数都可以在协同程序中顺利运行。
using System.Collections;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour {
public float waitTime = 10.0f;
public float fadeTime = 3.0f;
public float betweenFadesTime = 2.0f;
// Flag to determine whether or not the player may respond.
public bool canRespond = false;
// Flag to determine if the player has responded within the wait time.
public bool hasResponded = false;
public GameObject enemy;
void Start()
{ StartCoroutine(EnemyFadeIn(fadeTime, betweenFadesTime, waitTime)); }
void Update() {
if ((Input.GetKeyDown(KeyCode.S)) && (canRespond))
{ hasResponded = true; }
}
IEnumerator EnemyFadeIn(float timeToFade, float timeBetweenFades, float timeToWait) {
Debug.Log("An Enemy Is Fading In");
// Simulating Fade In Time.
yield return new WaitForSeconds(timeToFade);
// Fade in
// iTween.FadeTo(enemy, 1, 1);
// Invoke("SetMaterialOpaque", 1f);
Debug.Log("An Enemy Has Appeared");
yield return ListenForInput(timeToFade, timeBetweenFades, timeToWait);
}
IEnumerator EnemyFadeOut(float timeToFade, float timeBetweenFades, float timeToWait) {
Debug.Log("An Enemy Is Fading Away");
// Simulating Fade Out Time.
yield return new WaitForSeconds(timeToFade);
// Fade out
// SetMaterialTransparent();
// iTween.FadeTo(enemy, 0, 1);
Debug.Log("An Enemy Has Departed");
// Simulating Time Between Fades.
yield return new WaitForSeconds(timeBetweenFades);
yield return EnemyFadeIn(timeToFade, timeBetweenFades, timeToWait);
}
// Responsible for reacting to the 'S' key input.
IEnumerator ListenForInput(float timeToFade, float timeBetweenFades, float timeToWait) {
canRespond = true;
Debug.Log("Press the 'S' Key to Destroy the Enemy!");
float startTime = Time.time;
// Check every 0.25 seconds to see if the S key was pressed.
while (Time.time < (startTime + timeToWait)) {
if (hasResponded) {
Debug.Log("The 'S' Key was Pressed!");
hasResponded = false;
canRespond = false;
yield return EnemyFadeOut(timeToFade, timeBetweenFades, timeToWait);
}
yield return new WaitForSeconds(0.25f);
}
Debug.Log("The 'S' Key was not Pressed!");
canRespond = false;
yield return ResetGame();
}
IEnumerator ResetGame() {
Debug.Log("Game is Performing a Reset");
//Simulating Game Reset Time.
yield return new WaitForSeconds(10);
Debug.Log("Game has Restarted. End of Coroutine!");
}
}
我创建了EnemyFadeOut()
和ListenForInput()
方法以配合EnemyFadeIn()
和ResetGame()
方法。这是你的四个州。行为流程如下:
首先,Start()
Monobehaviour启动EnemyFadeIn()
协程。
接下来,EnemyFadeIn()
协程会在敌人完全进入游戏世界后将控制权传递给ListenForInput()
。
接下来,如果在给定的waitTime中按下'S'键,ListenForInput()
协程会将控制权传递给EnemyFadeOut()
,如果没有'S'键,则ResetGame()
及时按下。
如果控制权传递给EnemyFadeOut()
,敌人将逐步退出世界,然后控制权将转移到EnemyFadeIn()
并且循环将继续直到玩家未能按下'S'键
如果控制传递给ResetGame()
,则玩家未能及时按下'S'键,游戏将执行所有必要的功能以重启。
控制台Debug.Log()
和yield return new WaitForSeconds()
用于模拟目的。由于iTween不是我的本机库,因此必须注释掉一些淡入/淡出代码。
答案 1 :(得分:0)
目前,您正在Start()函数中启动Couroutine EnemyFadeIn(),这意味着只要脚本附加的对象被实例化,就会调用它。你的ResetEnemy()方法也会被调用,除非你设法在对象被实例化的那一刻按下S键,这是不太可能的。所以EnemyFadeIn()方法只被调用一次。如果你想在一段时间内没有按任何键时调用ResetEnemy(),你需要在每次按下一个键时设置一个时间戳:
float lastTimePressedButton;
void Start() {
lastTimePressedButton = Time.time;
}
void Update() {
if(Input.GetKeyCode(KeyCode.S)) {
lastTimePressedButton = Time.time;
}
if(Time.time >= lastTimePressedButton + 5f) {
ResetEnemyOrWhatever();
lastTimePressedButton = Time.time;
}
}
FixedUpdate只应该用于处理Rigidbodys只是一个不同的循环然后更新。
另外,GetKeyDown,GetKeyUp和GetKeyUp被认为是不好的做法,你应该使用GetButtonDown,GetButtonUp和GetButton。
仅供参考,在Stackoverflow上询问时,您应该编写您实际调用的函数。 Itween不是.Net Framework或Unity的一部分,我怀疑很多人都知道这个库(我想它是一个库)是做什么的。