Как я могу ввести и уничтожить другой игровой объект при запуске

#c# #unity3d

Вопрос:

Я хочу уничтожить игровой объект, когда он нажимает на триггер, но с вводом. Ошибок нет, но в unity это не работает

 using UnityEngine;

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

что я должен сделать, чтобы это сработало??

Ответ №1:

Очень маловероятно, что вам удастся нажать клавишу точно в том же кадре, в котором произойдет столкновение 😉

В качестве быстрого решения скорее используйте 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.