You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中OnTriggerStay触发时按G键切换GameObject状态重复执行问题

解决Unity触发区域内按键多次触发的问题

我写了下面这段Unity脚本,想要实现:当玩家处于触发区域内时,按下G键切换G1和G2的激活状态——第一次按G激活G1,再按一次就关闭G1、激活G2。但实际运行时发现,OnTriggerStay的逐帧调用会导致按一次G键时,if-else语句执行两三次,加延迟也解决不了。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StayonGallery2 : MonoBehaviour
{
    public GameObject G1;
    public GameObject G2;
    void Start()
    {
        G1.SetActive(false);
        G2.SetActive(false);
        
    }

    private bool _isStay;

    void OnTriggerStay(Collider player)
    {
        if (player.gameObject.tag == "Player")
        {
            _isStay = true;
        }
           
    }

    void Update()
    {
        if (_isStay)
        {
            _isStay = false;
            
            if (Input.GetKeyDown("g")) //If G is pressed
            {
                if (!G1.activeInHierarchy)
                {
                    G1.SetActive(true);
                    G2.SetActive(false);
                }
                else if (G1.activeInHierarchy)
                {
                    G1.SetActive(false);
                    G2.SetActive(true);
                }
            }

        }
    }
}

问题根源

你用OnTriggerStay每帧把_isStay设为true,又在Update里每次进入判断就把_isStay设为false,这种逻辑会让每帧都执行按键检测。哪怕Input.GetKeyDown只在按键按下的第一帧返回true,但频繁的状态重置还是会导致单次按键被多次处理。

修正方案

改用OnTriggerEnter和OnTriggerExit来维护玩家是否在触发区域的状态,这样状态只会在进入/离开时更新,不会每帧乱跳。然后在Update里只在玩家处于区域内时检测按键,确保单次按键只触发一次切换。

修正后的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class StayonGallery2 : MonoBehaviour
{
    public GameObject G1;
    public GameObject G2;
    private bool _isInTrigger;

    void Start()
    {
        G1.SetActive(false);
        G2.SetActive(false);
    }

    void OnTriggerEnter(Collider player)
    {
        if (player.CompareTag("Player"))
        {
            _isInTrigger = true;
        }
    }

    void OnTriggerExit(Collider player)
    {
        if (player.CompareTag("Player"))
        {
            _isInTrigger = false;
        }
    }

    void Update()
    {
        if (_isInTrigger && Input.GetKeyDown(KeyCode.G))
        {
            if (!G1.activeInHierarchy)
            {
                G1.SetActive(true);
                G2.SetActive(false);
            }
            else
            {
                G1.SetActive(false);
                G2.SetActive(true);
            }
        }
    }
}

关键改动

  • 用_isInTrigger标记玩家是否在区域内,通过OnTriggerEnter/OnTriggerExit更新,状态更稳定
  • 把按键检测和区域状态判断合并在Update里,确保只有符合条件时才执行切换
  • 用CompareTag代替直接访问tag,这是Unity推荐的更高效的标签检查方式
  • 简化else分支逻辑,因为G1的状态只有两种,无需重复判断

内容的提问来源于stack exchange,提问作者Carl

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 07:05:32