【问题标题】:I need help on the math for detecting the "side" of collision on a rotating sprite我需要数学上的帮助来检测旋转精灵上的碰撞“侧面”
【发布时间】:2021-01-18 19:28:57
【问题描述】:

所以我正在制作一个以海军方式处理战斗的 2D 空间 shmup。所以你射出船的舷侧,你的盾牌和船体分为 4 个部分:前、右、左和后。我不是最擅长数学的人,但我设法找到了一个脚本来检测我的多边形对撞机被碰撞或抛射物击中的一侧。这一切都很好。

问题是我的精灵在 2D 空间中旋转。因此,当我与某物相撞时,例如与我的船头相撞,如果我的船头向上,则可以正确检测到碰撞。但是如果船旋转并且机头现在在左侧并且我与机头上的东西发生碰撞,脚本会将机头碰撞检测为左舷碰撞。有人可以帮我纠正数学以解释我的船的旋转吗?

Collision2DExtension.cs

using UnityEngine;

namespace PixelsoftGames
{
    public static class Collision2DExtensions
    {
        public static Collision2DSideType GetContactSide(Vector2 max, Vector2 center, Vector2 contact)
        {
            Collision2DSideType side = Collision2DSideType.None;
            float diagonalAngle = Mathf.Atan2(max.y - center.y, max.x - center.x) * 180 / Mathf.PI;
            float contactAngle = Mathf.Atan2(contact.y - center.y, contact.x - center.x) * 180 / Mathf.PI;

            if (contactAngle < 0)
            {
                contactAngle = 360 + contactAngle;
            }

            if (diagonalAngle < 0)
            {
                diagonalAngle = 360 + diagonalAngle;
            }

            if (
                ((contactAngle >= 360 - diagonalAngle) && (contactAngle <= 360)) ||
                ((contactAngle <= diagonalAngle) && (contactAngle >= 0))
            )
            {
                side = Collision2DSideType.Starboard;
            }
            else if (
                ((contactAngle >= 180 - diagonalAngle) && (contactAngle <= 180)) ||
                ((contactAngle >= 180) && (contactAngle <= 180 + diagonalAngle))
            )
            {
                side = Collision2DSideType.Port;
            }
            else if (
                ((contactAngle >= diagonalAngle) && (contactAngle <= 90)) ||
                ((contactAngle >= 90) && (contactAngle <= 180 - diagonalAngle))
            )
            {
                side = Collision2DSideType.Forward;
            }
            else if (
                ((contactAngle >= 180 + diagonalAngle) && (contactAngle <= 270)) ||
                ((contactAngle >= 270) && (contactAngle <= 360 - diagonalAngle))
            )
            {
                side = Collision2DSideType.Rear;
            }

            return side.Opposite();
        }

        static bool ranOnce = false;
        public static Collision2DSideType GetContactSide(this Collision2D collision)
        {
            Vector2 max = collision.collider.bounds.max;
            Vector2 center = collision.collider.bounds.center;
            Vector2 contact = collision.GetContact(0).point;

            if (!ranOnce)
            {
                ranOnce = true;
                Debug.Log("Max: " + max);
                Debug.Log("Center: " + center);
                Debug.Log("Contact: " + contact);
            }

            return GetContactSide(max, center, contact);
        }
    }
}

Collision2DSideTypeExtensions.cs

namespace PixelsoftGames
{
    public static class Collision2DSideTypeExtensions
    {
        public static Collision2DSideType Opposite(this Collision2DSideType sideType)
        {
            Collision2DSideType opposite;

            if (sideType == Collision2DSideType.Port)
            {
                opposite = Collision2DSideType.Starboard;
            }
            else if (sideType == Collision2DSideType.Starboard)
            {
                opposite = Collision2DSideType.Port;
            }
            else if (sideType == Collision2DSideType.Forward)
            {
                opposite = Collision2DSideType.Rear;
            }
            else if (sideType == Collision2DSideType.Rear)
            {
                opposite = Collision2DSideType.Forward;
            }
            else
            {
                opposite = Collision2DSideType.None;
            }

            return opposite;
        }
    }
}

Collision2DSideType

public enum Collision2DSideType { None, Port, Starboard, Forward, Rear }

【问题讨论】:

    标签: c# unity3d 2d


    【解决方案1】:

    在 GetContactSide 方法中你永远不会得到你的精灵的旋转,就像你的精灵角度总是 0

    对此的一种解决方案是将精灵的角度作为参数添加到方法中,并将该角度添加到条件以确定精灵的哪一侧

    它可能看起来像这样:

    public static class Collision2DExtensions
    {
        public static Collision2DSideType GetContactSide(Vector2 max, Vector2 center, Vector2 contact, float angle)
        {
            ...
            if (
                ((contactAngle >= (360 - diagonalAngle) + angle) && (contactAngle <= 360 + angle)) ||
                ((contactAngle <= diagonalAngle + angle) && (contactAngle >= 0 + angle))
            )
    

    ... `

    我认为您应该针对这些条件中的每一个都这样做

    【讨论】:

    • 非常感谢,效果很好!现在的问题是 Collision2DSideType.None 被调用了很多。我数学不太好哈哈。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-05
    • 1970-01-01
    相关资源
    最近更新 更多