在 OnTriggerStay() 中的特定操作之前延迟

Delay before a specific action in OnTriggerStay()

我正在 Unity 中制作 3d 射击游戏。我想让玩家钉上 windows 和门,这样他就有了掩护。 windows 等墙上的洞和门上已经有不活动的木板。我想让玩家在 window 附近时按住按钮以将棋盘设置为活动状态。因此,如果需要钉下三块板才能完全关闭 window,玩家必须靠近 window 并按住一个按钮,例如 10 秒才能放置一块板。第二板和第三板也一样。然而,这个过程可以被打断,window 只能钉上一两块木板。 Windows 具有检测玩家存在的隐形触发器。

这是 windows 附带的代码:

using System.Collections.Generic;
using UnityEngine;

public class ActivateBoards : MonoBehaviour
{
    public float delay = 10f;
    public List<GameObject> boards;
    private int currentAmount = 0;
    private int totalAmount;
    private float elapsed = 0f;
    // Start is called before the first frame update
    void Start()
    {
        totalAmount = boards.Count;
    }

    // Update is called once per frame
    void Update()
    {

    }

    private void OnTriggerStay(Collider other)
    {
        if (other.gameObject.CompareTag("Player") && Input.GetButtonDown("Fire1") && currentAmount != totalAmount)
        {
            elapsed += Time.deltaTime;
            if (elapsed >= delay)
            {
                boards[currentAmount].SetActive(true);
                currentAmount++;
                elapsed = 0;
            }
        }
    }
}

我尝试使用协同程序,但这是行不通的,因为玩家可以在 yield return new WaitForSeconds() 命令的中间释放按钮。另外,我想附上一个 UI 图像,它可以起到进度条的作用,并随着时间的推移而填满。在 Unity 中我真的不太适应时间——上面的代码根本不起作用。我想 Time.deltaTime 只适用于 Update() 方法?我需要 OnTriggerStay() 的功能来检测播放器和 Update() 的功能来计算时间。我怎样才能实现它?

我在目前正在制作的一款游戏中遇到了类似的问题。我解决它的方法实际上是创建一个进度条,该进度条在正常播放期间隐藏(禁用),然后在需要时恢复。我如何实现进度条是通过使用滑块并禁用它的可交互部分。然后通过从代码中更改滑块的值,我能够实现进度条的效果。如果您想自己尝试使用它,我为其编写的代码在下面。

using UnityEngine;
using UnityEngine.UI;
public class InterationMeter_Controller : MonoBehaviour
{
    GameManager GameManager;
    Slider Slider;

    // Start is called before the first frame update
    void Start()
    {
        //Ref to GameManager, (Tagged "GameController")
        GameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();
        Slider = gameObject.GetComponent<Slider>();
    }

    // Update is called once per frame
    void Update()
    {
        Slider.value -= Time.deltaTime; //Counts down in rl seconds
        if (Slider.value <= 0) 
        {
            GameManager.UIManager.gameObject.SendMessage("OnInteractionMeterFinish");  //Call the UIManager to let it know the timer is done
        }
    }
}

基本上前提是当我想触发某种基于计时器的交互时。我调用我的 UI 管理器并通过设置滑块的值告诉它 运行 进度条 x 秒。然后我的 UI 管理器中有一个接收器方法,如果进度条完成则调用该方法。如果我需要在中途停止进度条,我可以告诉 UI 管理器隐藏停止调用 Update 方法的进度条。这有效地重置了计时器,因为我在再次在屏幕上调用它之前重置了时间。

我认为您可以通过让 OnTriggerStay() 允许按下各种交互按钮来使用它。然后,您可以调用您的 UI 管理器版本来启动此计时器,当您需要停止计时器时,只需再次调用它即可。

我想说的是你的主要问题是你使用的是 GetButtonDown 这只是正确的 每个按钮按下一个 帧。

您应该使用 GetButton,即 true 每一帧 只要按钮保持按下状态!

private void OnTriggerStay(Collider other)
{
    if (!other.gameObject.CompareTag("Player") return;

    // instead of totalAmount you could directly use the boards.Length (or .Count for a List)
    // I would also rather check for < instead of !=
    if(Input.GetButton("Fire1") && currentAmount < boards.Length)
    {
        elapsed += Time.deltaTime;
        if (elapsed >= delay)
        {
            boards[currentAmount].SetActive(true);
            currentAmount++;
            elapsed = 0;
        }
    }
    else if (Input.GetButtonUp("Fire1"))
    {
        // Button was released
        elapsed = 0;
    }
}

// I would then also reset if player leaves the collider
private void OnTriggerExit (Collider other)
{
    if (!other.gameObject.CompareTag("Player") return;

    elapsed = 0;
}