首页 > 解决方案 > 如何在 Trigger 上输入和销毁其他游戏对象

问题描述

我想在 GameObject 击中触发器但有输入时销毁它。没有错误,但它不能统一工作

using UnityEngine;

public class DestroyTile : MonoBehaviour
{
    private void OnTriggerEnter(Collider other)
    {
        if (other.CompareTag("Tile"))
        {
            if(Input.GetKeyDown(KeyCode.Space))
            {
                Destroy(other.gameObject);
            }
        }
    }
}

我应该怎么做才能使这项工作?

标签: c#unity3d

解决方案


您不太可能设法在发生碰撞的同一帧中击键;)

作为快速修复而不是使用OnTriggerStay

OnTriggerStay 每次物理更新都会为每个碰撞触发器的其他碰撞器调用一次。

public class DestroyTile : MonoBehaviour
{
    // Called once every FixedUpdate for each trigger you are touching
    private void OnTriggerStay(Collider other)
    {
        if (other.CompareTag("Tile"))
        {
            if(Input.GetKeyDown(KeyCode.Space))
            {
                Destroy(other.gameObject);
            }
        }
    }
}

通过上述方式,只有最后一个问题:OnTriggerStay实际上并不是每一帧都调用,而是每调用一次,因此如果它发生在未调用FixedUpdate的帧中,您可能会错过按键操作。FixedUpdate因此,通常在FixedUpdate(或其他基于物理的连续方法)中获取用户输入是不可靠的,应始终在Update.

因此,您可以/应该做类似的事情,例如

public class DestroyTile : MonoBehaviour
{
    private readonly HashSet<GameObject> _currentlyTouching = new HashSet<GameObject>();

    private void OnTriggerEnter(Collider other)
    {
        if (!other.CompareTag("Tile") return;

        // For some reason we still have the other object stored
        if(_currentlyTouching .Contains(other.gameObject)) return;
       
        // Store the other object
        _currentlyTouching.Add(other.gameObject);
    }
    
    private void OnTriggerExit(Collider other)
    {
        // We don't have this other object stored
        if(!_currentlyTouching.Contains(other.gameObject) return;
        
        // remove this other object
        _currentlyTouching.Remove(other.gameObject);
    }
    
    private void Update()
    {
        // Are we touching anything?
        // This check is cheaper than Input.GetKeyDown
        if(_currentlyTouching.Count <= 0) return;

        if(!Input.GetKeyDown(KeyCode.Space)) return;
        
        // destroy (all) the touched object(s)
        foreach(var obj in _currentlyTouching)
        {
            Destroy(obj);
        }

        // Don't forget to also clear the HashSet in that case
        _currentlyTouching.Clear();
    }
}

这样,您可以将用户输入Update(每帧)分开,并且仅通过基于 Physcis 的系统跟踪进入和退出的对撞机。


推荐阅读