c# - 统一冷却实施
问题描述
我正在尝试在我的 Unity 项目中实现冷却,虽然这段代码似乎有意义,但它不起作用。发布的代码是一个全方位的基本运动脚本。
我尝试用 a 做一些事情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;
}
}
}
解决方案
你做
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; }
推荐阅读
- android - Android Studio 不会自动导入 androidx.lifecycle.observe
- gnuplot - csv 文件数据的移动平均值显示 gnuplot 中的初始错误
- reactjs - 背景图像数据未正确通过 graphql Gatsby 查询
- macos - 在苹果汇编程序中加载 x64 上的立即地址
- javascript - 是否可以创建相同 html 元素的无限循环,从顶部滚动到底部并具有类似门户的效果?
- c++ - 如何以内存泄露的形式创建信息泄漏?(源代码)
- pip - simpletraj(setup.py)的构建轮...错误
- javascript - 选中的复选框在第一时间不起作用
- android - OnClickListener 仅适用于第一个 ViewHolder
- python - 具有均匀间隔颜色的颜色条的不均匀(不规则)间隔数据