其他分享
首页 > 其他分享> > Unity计算两向量夹角以判断相对位置

Unity计算两向量夹角以判断相对位置

作者:互联网

项目场景:

在Unity中,通过计算两个向量之间的夹角判断两者之间的相对位置

因为玩家在进行旋转看向目标时,需要按需播放“左转”或“右转”动画,所以需要先判定目标与玩家的相对位置。


解决方案:

首先需要了解关于两个向量“点积”的知识。然后你才能理解求弧度的过程!

这里有个链接,我认为能很好帮你理解这一点。向量内积与外积

接下来就是解决思路了,首先创建一个脚本CaculateAngle.cs,定义两个Transform分别保存玩家与目标的位置信息,暂且面名为playerTrans(玩家)和targetTrans(目标)

获取需要计算的方向向量

因为我们默认玩家的正前方为起始朝向,而玩家到目标的方向,则是我们需要进行判定的方向。所以这里我们可以得到两个向量。我们暂且把他们命名为ori(起始向量)和dir(目标向量)

效果展示:

蓝色的是Cube,红色的Cube2
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源码:

public class CaculateAngle : MonoBehaviour
{
    public Transform playerTrans;//玩家transform信息
    public Transform targetTrans;//目标transform信息
    private void Start()
    {
        if (playerTrans == null)//如果不进行赋值则默认此脚本挂在物体为玩家
        {
            playerTrans = transform;
        }
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.C))//按下“C”进行计算
        {
            计算朝向(playerTrans.position, targetTrans.position);
        }
    }
    public 方向 计算朝向(Vector3 起点, Vector3 终点)
    {
        起点 = playerTrans.position;
        终点 = targetTrans.position;
        起点.y = 0;//这里是只在一个平面上考虑,不需要可把这两个y的赋值删除。但下面进行位置判定就需要多几步了
        终点.y = 0;
        Vector3 dir = 终点 - 起点;
        var f = Vector3.Dot(playerTrans.forward, dir);//求点积
        Debug.Log("点积:" + f);
        var a = Vector3.Magnitude(playerTrans.forward);//计算两个向量的“模”,如果不清楚“模”的概念可以先去了解一下“向量的模”
        var b = Vector3.Magnitude(dir);
        Debug.Log("两个向量的模:" + a + ":" + b);
        f = (f / (a * b));//计算两个向量夹角的余弦值
        Debug.Log("余弦值:" + f);
        var h = Mathf.Acos(f);//通过Acos函数可通过余弦值计算出对应弧度
        Debug.Log("弧度:" + h);
        var d = (h *= Mathf.Rad2Deg);//弧度转度。这里得到的始终为正值
        float x = dir.x;//因为我计算的平面是在xz上,所以x的值的正负可以判定在左(小于0)还是在有(大于0)
        //但只通过X的值是没法判定正前方和正后方的。所以还需要借助余弦的值进行判定。起始两向量的点积也能进行位置的判断,这里就不过多讨论了,感兴趣的小伙伴可以去试试。
        if (x > 0)
        {
            Debug.Log("<color=red>" + targetTrans.name + "</color>在" + playerTrans.name + "<color=red>" + 方向.右边 + "</color>");
            Debug.Log("度:" + d);
            return 方向.右边;
        }
        else if (x < 0)
        {
            Debug.Log("<color=red>" + targetTrans.name + "</color>在" + playerTrans.name + "<color=red>" + 方向.左边 + "</color>");
            d *= -1;//由于计算的度数值始终为正,我们再次做一下处理,将左边默认为负的度数。
            Debug.Log("度:" + d);
            return 方向.左边;
        }
        else
        {
            if (f == -1)
            {
                Debug.Log("<color=red>" + targetTrans.name + "</color>在" + playerTrans.name + "<color=red>" + 方向.正后 + "</color>");
                Debug.Log("度:" + d);
                return 方向.正后;
            }
            else if (f == 1)
            {
                Debug.Log("<color=red>" + targetTrans.name + "</color>在" + playerTrans.name + "<color=red>" + 方向.正前 + "</color>");
                Debug.Log("度:" + d);
                return 方向.正前;
            }
            else
            {
            	//因为可能会发生不可预料的错误(比如玩家和目标重合的极端情况),所以我们在此添加一个处理。
                Debug.Log("<color=red>" + targetTrans.name + "</color>在" + playerTrans.name + "<color=red>" + 方向.方向错误 + "</color>");
                Debug.Log("度:" + d);
                return 方向.方向错误;
            }
        }
    }
}
public enum 方向
{
    方向错误,
    左边,
    右边,
    正前,
    正后
}

源工程下载

链接:https://pan.baidu.com/s/1wwtHPp8QT6Y2b-4lsSZgdA
提取码:79an

如果对你有帮助不要忘记点赞+收藏!谢谢!

注明:若有错误,请指正!

标签:playerTrans,Log,Unity,targetTrans,Debug,夹角,向量,name
来源: https://blog.csdn.net/weixin_44870508/article/details/120968117