我正在尝试在Unity项目中实现冷却,尽管这段代码似乎很有意义,但却无法正常工作。发布的代码是全方位的基本动作脚本。
我尝试用cooldown -=time.deltatime
做某事,但这似乎不起作用。我一直在尝试几种方法,但是似乎没有一种方法。
代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovementScript : MonoBehaviour
{
public float cooldown = 0;
public float actualcooldown = 3f;
public bool isCooldown = false;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.R))
{
GetComponent<Renderer>().material.color = Color.red;
}
if (Input.GetKey(KeyCode.G))
{
GetComponent<Renderer>().material.color = Color.green;
}
if (Input.GetKey(KeyCode.B))
{
GetComponent<Renderer>().material.color = Color.blue;
}
if (Input.GetKey(KeyCode.D))
{
transform.Translate(6f * Time.deltaTime, 0, 0);
}
if (Input.GetKey(KeyCode.A))
{
transform.Translate(-6f * Time.deltaTime, 0, 0);
}
if (Input.GetKeyDown(KeyCode.Space) && cooldown <= 0) {
transform.Translate(0f, 20f * Time.deltaTime, 0f);
isCooldown = true;
while (isCooldown == true)
{
coolDownhappening();
}
}
}
public void coolDownhappening()
{
cooldown = actualcooldown;
cooldown -= Time.deltaTime;
if (cooldown <= 0)
{
cooldown = 0;
}
}
}
答案 0 :(得分:1)
你做
while (isCooldown == true)
{
coolDownhappening();
}
但是您从不在任何地方更改isCoolddown
!
正如评论中已经提到的,您完全根本不希望在while
方法中使用Update
,至少在这种情况下不希望使用!这样会在给定的冷却时间内冻结整个主线程-或永久冻结!
您的代码中还有很多其他问题,让我们逐步进行:
Input.GetKey
的给定键时,它们是真实的每帧。但是,这是没有意义的,只要按钮保持按下状态,就只会造成不必要的开销,将材料颜色重复设置为相同的值。您只想将其应用一次。
→宁可使用Input.GetKeyDown
!
GetComponent
是一个非常昂贵的电话。您不应该不重复使用GetComponent<Renderer>()
,而应该存储参考一次,以后再使用
// most efficient is always to already reference this via the Inspector
[SerializeField] private Renderer _renderer;
// alternatively get it on runtime
private void Awake()
{
if(!_renderer) _rednerer = GetComponent<Renderer>();
}
然后再使用
private void Update()
{
if(Input.GetKeyDown(KeyCode.R))
{
_renderer.material.color = Color.red;
}
...
}
您的运动部件实际上很好。为了使其更具可读性,我实际上宁愿做类似的事情
if (Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.right * 6f * Time.deltaTime);
}
else if (Input.GetKey(KeyCode.D))
{
transform.Translate(Vector3.left * 6f * Time.deltaTime);
}
还要在此处注意else
。当然,这取决于您的需求,但通常情况下,您只希望使用相反的按钮。
最后是真正的交易:您实际上想在此处使用带有冷却时间的跳转方法。
首先在这里您进行了相反的操作:Input.GetKeyDown
仅被精确地调用一次,即一次,即在键被按下时的帧中。因此,您的对象“跳跃” 20 * 1/FPS
对于60 FPS始终约为0.33
。您可能想在多个框架上向上移动一定距离。达到一定高度后,启动冷却。
如评论中所述,可以在Update
中使用计时器来执行此操作,但是通常这会使代码有些混乱。而是使用协程:
private bool _canJump;
private void Update()
{
...
// _canJump is cheaper to check so check it first
if (_canJump && Input.GetKeyDown(KeyCode.Space))
{
StartCoroutine(JumpRoutine());
}
}
private IEnumerator JumpRoutine()
{
// avoid concurrent routines
if(!_canJump) yield break;
// disable jumping
_canJump = false;
// Now it really depends on what you actually want to do
// and how your object should move now
// you might e.g. want something like
var jumpedHeight = 0f;
while(jumpedHeight < 20f)
{
var jumpThisFrame = Vector3.up * 6f * Time.deltaTime;
transform.Translate(jumpThisFrame);
// important now! yield tells Unity to "pause" here,
// render this frame, and continue from here int he next frame
// without the yield statements this would again freeze your game until
// the exit condition is fulfilled!
yield return null;
}
// After reaching the target height this waits for 3 seconds but keeps on rendering meanwhile
yield return new WaitForSeconds(actualcooldown);
// after the cooldown allow next jump
_canJump = true;
}