类似《毁灭战士》的基于角度的精灵变换。

5

我正在尝试制作一款第一人称游戏,使用类似于《毁灭战士》、《杜克·纽科姆》等游戏的精灵机制。

目前为止,我可以确定自己与静态物体之间的角度关系,但不能确定旋转物体。我有一些“敌人”会改变旋转方向并开始跟随我,但是计算切线角度(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;
}

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

3个回答

5
你说你[唯一]的问题是它没有考虑旋转-我猜想这意味着当精灵面对前方时,你没有问题地实现了billboarding和旋转。为此:
向量a和b的点积等于cos(theta)* magnitude(a)* magnitude(b)。因此,如果a是从相机到对象的向量:
var a = cam.transform.position - transform.parent.position

并且 b 是对象的前进方向:

var b = transform.parent.forward

我们知道a和b的大小都为1。

a.Normalize();
//b is already normalized

那么我们知道这等于cos(theta),其中theta是它们之间的夹角。
var theta = Mathf.Acos(Vector3.Dot(a, b)) * Mathf.Rad2Deg;

然而,Theta是最短的必要角度 - 因此它将从0到180。根据您上面的开关表,我们知道当我们希望走错路线时,我们会处于错误的位置。因此,为了解决这个问题:

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

然后我们只需将其插入并运行。以下是我项目中的完整文件:

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);
    }
}

如果需要更多背景信息,这是我的项目链接:https://github.com/AdamRGrey/22623013

建议点击播放按钮,但注意观看场景窗口而不是游戏窗口。


-2

-2
也许我没有完全理解您在此处尝试创建的确切效果(如果是这样,请在帖子中提供更多信息,例如屏幕截图),但您应该能够简单地使用Transform.LookAt()。 这些通常被称为广告牌精灵

示例:

Transform.LookAt(Camera.main.transform.position, Vector3.up)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接