Как настроить скрипт ближнего боя, чтобы он был более отзывчивым? - PullRequest
0 голосов
/ 14 февраля 2020

Я следил за этим видео, чтобы получить сценарий повреждения: https://www.youtube.com/watch?v=aSeE7u8Cs-I&list=PLZ1b66Z1KFKiaTYwyayb8-L7D6bdiaHzc&index=11

Проблема в том, что это из-за оружия, и по какой-то причине, даже когда лучевая передача мертва впереди, иногда нож хит не зарегистрируется. Можно ли как-то просто сделать так, чтобы что-либо, находящееся передо мной, получало урон от клика / атаки?

Это мой текущий код:

void Start()
    {
        animator = GetComponentInChildren<Animator>();
    }


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

        if (Input.GetButtonDown("Attack"))
        {
            StartCoroutine(Poke());
        }
        else
        {

        }

        IEnumerator Poke()
        {
            RaycastHit knife;
            //this line was causing weird delay but I can't remember 100% what it was for and if it's still needed
            //isAttacking = true;
                if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out knife))

                {
                    knife.transform.SendMessage("DamageZombie", DamageAmount, SendMessageOptions.DontRequireReceiver);
                }
                animator.SetBool("isAttacking", true);
                yield return new WaitForSeconds(.1f);
                animator.SetBool("isAttacking", false);
            }
    }
} ```


Ответы [ 2 ]

0 голосов
/ 14 февраля 2020

Что ж, вы, вероятно, сталкиваетесь с каким-то другим коллайдером, некоторым GameObject, к которому не подключен ни один компонент, и имеет метод с именем DamageZombie.

Существует несколько способов ограничить Raycast указанием c цели:

  1. Physics.Raycast принимает дополнительные параметры

    maxDistance
    Максимальное расстояние луча должен проверять наличие столкновений.

    layerMask
    Маска слоя, используемая для выборочного игнорирования коллайдеров при наведении луча.

    Так что ставьте своих врагов цели на указанном c Layer вы уже можете ограничить Raycast, чтобы он попадал только в них и только тогда, когда они достаточно близко:

    // Adjust here which layer(s) you want to hit via the Inspector
    public LayerMask targetLayers;
    
    ...
    
    if (Physics.Raycast(new Ray(transform.position, transform.forward), out var hit, 1f, (int)targetLayers))
    {
        // Do something
    }
    

    Так что это уже фильтрует лучевую трансляцию и только попадает на первый объект, найденный в пределах диапазона 1, и только на слой (слои), настроенный в targetLayers.

  2. Как вы и сказали, что хотели на hit everything вы можете использовать Physics.RaycastAll и затем выполнять тьфу все попадания

    var hits = Physics.RaycastAll(new Ray(transform.position, transform.forward), 1f, targetLayers);
    foreach(var hit in hits)
    {
        // Do something
    }
    

    Теперь это в основном делает то же самое, что и раньше, но теперь поражает каждый объект в пределах диапазона 1 юнитов и на слое (ях), настроенных в targetLayers.

  3. Используя Теги , вы можете еще больше ограничиться и проверить после того, как Raycast, что вы нажали.

    foreach(var hit in hits)
    {
        if(!hit.CompareTag("Zombie")) continue;
    
        // Do something
    }
    

Наконец, вообще НЕ используйте SendMessage! Это крайне неэффективно и небезопасно ... вы никогда не узнаете, есть ли у объекта, который вы ударили, даже компонент, реализующий такой метод вообще ... или если вы изменили эту строку в каждом месте после переименования метода ...

Скорее получите компонент, который хотите поразить!

var damageScript = hit.GetComponent<YOURSCRIPT>();
if(damageScript)
{
    damageScript.DamageZombie(DamageAmount);
}
0 голосов
/ 14 февраля 2020

Попробуйте:

bool isAttacking = false;

void Start() {
    animator = GetComponentInChildren<Animator>();
}

void Update() {
    if (Input.GetButtonDown("Attack")) {
        StartCoroutine(Poke());
    }
}

IEnumerator Poke() {
    if(!isAttacking){
        isAttacking = true;
        RaycastHit knife;
        if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out knife)) {
            knife.transform.SendMessage("DamageZombie", DamageAmount, SendMessageOptions.DontRequireReceiver);
        }
        animator.SetBool("isAttacking", true);
        yield return new WaitForSeconds(.1f);
        animator.SetBool("isAttacking", false);
        isAttacking = false;
    }
}

Также имейте в виду, что Physics.Raycast может использовать LayerMask для обнаружения объектов, если ничего не работает, посмотрите на что.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...