Unity 冷却实现 [英] Unity cooldown implementation

查看:27
本文介绍了Unity 冷却实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在我的 Unity 项目中实现冷却时间,虽然这段代码似乎有意义,但它不起作用.贴出来的代码是一个全能的基本运动脚本.

I'm trying to implement cooldowns in my project in Unity, while this code seems to make sense, it doesn't work. The code that's posted is an all-around basic movement script.

我尝试使用 cooldown -=time.deltatime 做一些事情,但这似乎不起作用.我一直在尝试几种方法,但似乎都不起作用.

I tried doing something with a cooldown -=time.deltatime, but that didn't seem to work. I've been trying several methods, but none seem to work.

代码:

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();
 }

但你永远在任何地方改变isColddown

正如评论中已经提到的,您不想想在 Update 方法中使用 while,至少不是在这个用例!这将在给定的冷却时间内冻结整个主线程 - 或者在您的情况下永远冻结!

Also as was already mentioned in the comments you do not want to use while in the Update method at all, at least not in this usecase! This will freeze the entire mainthread for the given cooldown time - or in your case forever!

您的代码中还有很多其他问题,让我们一步一步来:

There are a lot of other issues in your code so let's go step by step:

  • Input.GetKey 在他们按下给定键时每一帧为真.但是,只要按住按钮,将材料颜色重复设置为相同的值,这没有任何意义,只会导致不必要的开销.您更愿意做的是应用一次.

  • Input.GetKey is true every frame while they given key is pressed. However, it makes no sense and only causes unecessary overhead to repeatedly set the materials color to the same value as long as a button stays pressed. What you rather want to do is apply it once.

→而是使用 Input.GetKeyDown 来实现这些!

→ rather use Input.GetKeyDown for these!

GetComponent 是一个相当昂贵的调用.您应该不要重复使用GetComponent(),而是应该存储引用一次并在以后重新使用

GetComponent is a quite expensive call. You should not repeadedly use GetComponent<Renderer>() but rather store the reference once and re-use it later

// 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;
    }

    ...
}

  • 您的活动部件实际上很好.然而,为了让它更易读,我实际上宁愿做一些像

  • Your moving part is actually fine. To make it slightly more readable I would however actually rather do something like

    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.当然取决于您的需求,但通常您希望相反的按钮独占.

    also note the else here. Depends on your needs of course but usually you want contrary buttons exclusive.

    最后是真正的交易:你真的想要一个有冷却时间的跳跃方法.

    Finally to the real deal: You actually want to have a jump method with a cooldown here.

    首先,您以相反的方式执行此操作:Input.GetKeyDown 仅被调用一次,即在按键按下时的帧中.因此,您的对象跳跃"20 * 1/FPS,对于 60 FPS,始终约为 0.33.您可能更希望在多个帧上向上移动一定距离.达到一定高度后,激活冷却时间.

    First here you did it the other way round: Input.GetKeyDown is called only exactly once namely in the frame when the key went down. So your object "jumps" 20 * 1/FPS which for 60 FPS is always about 0.33. You probably rather wanted to move a certain distance upwards over multiple frames. After a certain height is reached, activate a cooldown.

    正如评论中提到的,可以Update 中使用计时器来做到这一点,但这通常会使代码有点混乱.而是使用协程:

    As mentioned in the comments one can do this in Update using a timer but usually this makes the code a bit messy. Rather use a Coroutine:

    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;
    }    
    

  • 这篇关于Unity 冷却实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆