基于类似 Doom 的角度的精灵改变

sal*_*157 5 c# rotation unity-game-engine

所以,我正在尝试制作一个第一人称游戏,它使用与 Doom、Duke Nukem 等游戏相同的精灵机制。

到目前为止,我可以识别与静态对象相关的角度,但不能识别与旋转对象相关的角度。我有一些“敌人”会改变旋转并开始跟随我,但计算切线角度 (Mathf.Atan2) 并没有考虑敌人的旋转。

这是我到目前为止使用的代码,它非常适合不旋转的对象:

 int GetAngleIndex()
 {
    var dir = cam.transform.position - transform.parent.forward;
    var enemyAngle = Mathf.Atan2(dir.z, dir.x) * Mathf.Rad2Deg;

    if (enemyAngle < 0.0f)
        enemyAngle += 360;

    Debug.Log("Angle from the player is: " + enemyAngle);

    if (enemyAngle >= 292.5f && enemyAngle < 337.5f)
        return 8;
    else if (enemyAngle >= 22.5f && enemyAngle < 67.5f)
        return 2;
    else if (enemyAngle >= 67.5f && enemyAngle < 112.5f)
        return 3;
    else if (enemyAngle >= 112.5f && enemyAngle < 157.5f)
        return 4;
    else if (enemyAngle >= 157.5f && enemyAngle < 202.5f)
        return 5;
    else if (enemyAngle >= 202.5f && enemyAngle < 247.5f)
        return 6;
    else if (enemyAngle >= 247.5f && enemyAngle < 292.5f)
        return 7;
    else if (enemyAngle >= 337.5f || enemyAngle < 22.5f)
        return 1;
    else return 0;
}
Run Code Online (Sandbox Code Playgroud)

我已经搜索了几个小时,但找不到解决方案:(

Ada*_*rey 5

你说你的[唯一]问题是它没有考虑到他们的轮换 - 我猜这意味着你在展示你的精灵时没有问题,当他们面向前方时你的轮换工作。为此:

向量 a 和 b 的点积等于 cos(theta)*magnitude(a)*magnitude(b)。所以如果 a 是从相机到物体的向量:

var a = cam.transform.position - transform.parent.position
Run Code Online (Sandbox Code Playgroud)

b 是对象的前向:

var b = transform.parent.forward
Run Code Online (Sandbox Code Playgroud)

我们知道 a 和 b 都为 1

a.Normalize();
//b is already normalized
Run Code Online (Sandbox Code Playgroud)

然后我们知道这等于 cos(theta),其中 theta 是它们之间的角度。

var theta = Mathf.Acos(Vector3.Dot(a, b)) * Mathf.Rad2Deg;
Run Code Online (Sandbox Code Playgroud)

然而。Theta 是最短的必要角度 - 因此它将是从 0 到 180。鉴于您在那里的开关表,我们知道当我们希望绕错方向时,我们将处于错误的位置。所以要解决这个问题:

if (a.x * a.z < 0)
    theta = 360.0f - theta;
Run Code Online (Sandbox Code Playgroud)

然后我们只需将其插入即可。这是我项目中的完整文件:

using UnityEngine;

public class spriteAngler : MonoBehaviour
{
    public Transform toFace;
    public SpriteRenderer toManipulate;
    public Sprite[] mySprites;
    private float theta;
    private Vector3 a;
    void Update()
    {
        toManipulate.sprite = mySprites[GetAngleIndex()];
    }
    int GetAngleIndex()
    {
        a = toFace.position - transform.position;

        a.Normalize();
        var b = transform.forward;

        theta = Mathf.Acos(Vector3.Dot(a, b)) * Mathf.Rad2Deg;

        if (a.x * a.z < 0)
            theta = 360.0f - theta;

        if (theta >= 292.5f && theta < 337.5f)
            return 7;
        else if (theta >= 22.5f && theta < 67.5f)
            return 1;
        else if (theta >= 67.5f && theta < 112.5f)
            return 2;
        else if (theta >= 112.5f && theta < 157.5f)
            return 3;
        else if (theta >= 157.5f && theta < 202.5f)
            return 4;
        else if (theta >= 202.5f && theta < 247.5f)
            return 5;
        else if (theta >= 247.5f && theta < 292.5f)
            return 6;
        else if (theta >= 337.5f || theta < 22.5f)
            return 0;
        else return 0;
    }

    private Rect guiPos = new Rect(0, 0, 720, 30);
    void OnGUI()
    {
        GUI.Label(guiPos, "Angle from the Player is: " + theta + " and forward=" + transform.forward + " and vectorToTarget=" + a);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果需要更多上下文,这是我的项目:https : //github.com/AdamRGrey/22623013

我建议点击播放但观看场景窗口而不是游戏窗口。