как я могу открыть дверь с определенного расстояния c расстояние c# - PullRequest
1 голос
/ 07 мая 2020

Я хочу добавить двери в свой проект Unity, и до сих пор у меня есть код для работы с моей дверью, но я могу открыть ее с любого расстояния в сцене. Я хочу иметь возможность открывать его только с небольшого расстояния, но не могу понять как.

public class Door : MonoBehaviour
{
public bool doorIsOpen;
public Transform closedPos;
public Transform openPos;
public float openSpeed;
public float openRadius;

void Update()
{
    if(Physics.CheckSphere(gameObject.transform.position, openRadius))
    {
        if(Input.GetKeyDown(KeyCode.E))
         {
            doorIsOpen = !doorIsOpen;
         }
    }         

    if(doorIsOpen == true)
    {
        OpenDoor();
    }
    if(doorIsOpen == false)
    {
        CloseDoor();
    }

}

void OpenDoor()
{
    doorIsOpen = true;
    gameObject.transform.position = openPos.position;
    gameObject.GetComponent<Animator>().SetTrigger("OpenDoor");
    gameObject.GetComponent<Animator>().SetBool("DoorIsClosed", false);
    gameObject.GetComponent<Animator>().SetBool("DoorIsOpen", true);
}

void CloseDoor()
{
    doorIsOpen = false;
    gameObject.transform.position = closedPos.position;
    gameObject.GetComponent<Animator>().SetTrigger("CloseDoor");
    gameObject.GetComponent<Animator>().SetBool("DoorIsOpen", false);
    gameObject.GetComponent<Animator>().SetBool("DoorIsClosed", true);
}

}

Ответы [ 3 ]

0 голосов
/ 07 мая 2020

Вы можете увеличить значение 'openRadius', игра создает сферу в gameObject.transform.position с радиусом 'openRadius' и проверяет, есть ли какие-либо коллайдеры, перекрывающие сферу.

//...
if(Physics.CheckSphere(gameObject.transform.position, openRadius))
//...
0 голосов
/ 07 мая 2020

Одна проблема заключается в том, что вы постоянно устанавливаете триггеры в каждом кадре. Это нужно делать только при нажатии клавиши.

Затем также Physics.CheckSphere проверяет, есть ли какой-либо коллайдер в пределах диапазона. Это может быть любой коллайдер, а не только игрок. Чтобы убедиться, что это работает только в том случае, если игрок находится в пределах досягаемости, вы обязательно должны использовать Layers и дать игроку его собственный слой, например «Player». Затем вы можете передать параметр layerMask, чтобы убедиться, что двери проверяют только слой игрока.

, поэтому я бы просто использовал

// if possible already reference this in the Inspector
[SerializeField] private Animator _animator;

[Tooltip("Here select only the Layer(s) which you assigned to your Player object(s)")]
[SerializeField] LayerMask _playerLayer;

private void Awake()
{
    // as fallback get it ONCE on runtime
    if(!_animator) _animator = GetComponent<Animator>();
}

private void Update()
{
    // Afaik the Key is way cheaper to check so do it first
    // and use physics only if actually necessary
    if(Input.GetKeyDown(KeyCode.E))
    {
        // Only check for the Player's Layer and ignore other colliders
        if(Physics.CheckSphere(transform.position, openRadius, _playerLayer.value))
        {
            ToggleDoorState();
        }
    }
}

// Since manually changing the flag in the Inspector will not have
// any effect anymore in order to be able to test it you can use 
// the context menu of this component in the Inspector
[ContextMenu(nameof(ToggleDoorState))]
private void ToggleDoorState()
{
    // invert the flag
    doorIsOpen = !doorIsOpen;

    // use the flag in ternary expressions
    transform.position = doorIsOpen ? openPos.position : closedPos.position;
    _animator.SetTrigger(doorIsOpen ? "OpenDoor" : "CloseDoor");

    // use the value of the flag diectly
    _animator.SetBool("DoorIsClosed", !doorIsOpen);
    _animator.SetBool("DoorIsOpen", doorIsOpen);
}

Это немного похоже на то, как если бы вы иметь немного избыточности в вашем аниматоре. Я бы использовал либо Bools, чтобы инициировать переход, либо триггеры, чтобы оба варианта казались странными.

0 голосов
/ 07 мая 2020

Предварительные требования

Добавьте сферу с коллизионным телом вокруг экземпляра двери в Unity. Эта сфера работает как радиус, который запускает метод ChangeDoorState.

Изменить метод обновления

Обновление будет учитывать любые столкновения, происходящие в указанной сфере. Если есть хотя бы один объект в диапазоне (сфера столкновения) двери, то он открывает или закрывает экземпляр двери. Источник: https://docs.unity3d.com/ScriptReference/Physics.OverlapSphere.html

    void Update()
    {
        Collider[] hitColliders = Physics.OverlapSphere(center, radius);
        if (hitColliders.Length > 0)
        {
            ChangeDoorState();
        }
    }

Объединение методов OpenDoor и CloseDoor

        void ChangeDoorState()
        {
            doorClosureState = doorClosure ? true : false;
            gameObject.transform.position = doorClosureState ? closedPos.position : openPos.postition;
            gameObject.GetComponent<Animator>().SetTrigger("DoorClosure");
            gameObject.GetComponent<Animator>().SetBool("DoorIsOpen", doorClosureState);
            gameObject.GetComponent<Animator>().SetBool("DoorIsClosed", !doorClosureState);
        }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...