Unity RigidBody Physics: Столкновение, когда НЕ перекрывающийся слой - PullRequest
0 голосов
/ 17 октября 2019

Есть ли в Unity что-то вроде метода CollideWhenRigidBodyLeavesLayer? Вот почему:

У моих NPC три типа движения: Walk, Swim и Fly

Они используют твердое тело для своих движений, и это прекрасно работает для персонажей, которые ходят.

Это также хорошо работает для персонажей, которые летают. Вызывая Physics.IgnoreLayerCollision (FlyingCharacterLayer, WaterLayer) Летающие персонажи теперь могут летать над водой.

Мой вопрос заключается в том, как заставить мое плавательное существо оставаться перекрывающим слой воды?

Iвключили Physics.IgnoreLayerCollision (SwimCharacterLayer, WaterLayer) Так что теперь плавающие персонажи могут перекрывать воду.

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

Мой уровень (и, следовательно, вода) генерируется динамически, поэтому добавление периметра для проверки столкновений не очень хороший вариант.

Кроме того,«слой» земли / слоя существует под слоем воды, поэтому я не думаю, что есть хороший способ проверить его на столкновение с землей, потому что моя рыба перекрывает землю и воду одновременно.

Iнадеюсь, я упускаю что-то базовое:)

Спасибо!

ОБНОВЛЕНИЕ:Я могу проверить, не перекрывает ли мой персонаж плавание воду с помощью Physics.CheckSphere

Но я не могу понять, что делать дальше. Если я пытаюсь повернуть его на 180 градусов, он переворачивает каждый кадр, а иногда возвращается к воде, иногда нет ...

if(Physics.CheckSphere(transform.position, 0.25f, LayerMask.NameToLayer("Water")) == false)
{
    // Now I know that my fish is out of the water
    // but I can not figure out how to turn him around
}

1 Ответ

0 голосов
/ 17 октября 2019

Я на самом деле не горжусь этим, но после возни вот что я придумала.

Кажется, что рыба в пруду держится, но отскоки не очень красивые.

Это также полностью нарушает правило "Не суетись с преобразованием твердых тел" ... но так как физическая система все равно не будет работать со мной ...

enum CheckDirection { AHEAD, LEFT, RIGHT };
bool CheckAheadIsWater(CheckDirection dir = CheckDirection.AHEAD)
    {
        if(dir == CheckDirection.AHEAD)
            return Physics.CheckSphere(transform.position + transform.forward * 1.5f, 0.5f, LayerMask.GetMask(Settings.LayerWater));
        if(dir == CheckDirection.RIGHT)
            return Physics.CheckSphere(transform.position + forward + transform.right * 2f, 0.5f, LayerMask.GetMask(Settings.LayerWater));
        if(dir == CheckDirection.LEFT)
            return Physics.CheckSphere(transform.position + transform.forward - transform.right * 2f, 0.5f, LayerMask.GetMask(Settings.LayerWater));

        throw new System.Exception("No Check Existes For " + dir);
    }

void Update()
{
       if (!CheckAheadIsWater(CheckDirection.RIGHT))
        {
            print("about to leave water RIGHT");

            //turn left 45 degrees
            transform.rotation = Quaternion.LookRotation(transform.forward + transform.right * 0.5f);
        }

        if (!CheckAheadIsWater(CheckDirection.LEFT))
        {
            print("about to leave water LEFT");

            //turn right 45 degrees           
            transform.rotation = Quaternion.LookRotation(transform.forward - transform.right * 0.5f);
        }

        if (!CheckAheadIsWater())
        {
            print("about to leave water AHEAD");

            //bounce back 1 unit
            physicalBody.MovePosition(transform.position - transform.forward);
            //swim the opposite direction
            transform.rotation = Quaternion.LookRotation(-transform.forward);
        }
}

...