Unity 实现2dLookAt

一、功能说明

        我们知道,3D情况下给定一个位置,我们可以令游戏体朝向该位置,也就是

transform.LookAt(target);

结果就是游戏体的z轴正方向朝向目标。但是在2D中不能直接用这个方法,因为2D情况下游戏体的z轴是永远垂直于屏幕的,并不代表游戏体的前方。此时游戏体的前方可以是y轴正方向,也可以是x轴正方向,这取决于你的游戏体的形状。

        综上,需要一个2D的LookAt函数。

二、功能实现

        首先定义函数,如下


// transform表示需要旋转的游戏体,forward表示游戏体需要朝向目标的方向,targetPos表示目标位置
void LookAt2D(Transform transform, Vector3 forward, Vector3 targetPos)
{
    Vector3 targetDir = targetPos - transform.position;
    ...
}

效果为forward方向旋转到目标方向。

        显然我们要计算两个方向的夹角,不妨再写一个函数,如下

//forwardDir、targetDir均为单位向量
float GetAngle(Vector3 forwardDir, Vector3 targetDir)
{
    float cosTheta = Mathf.Clamp(Vector3.Dot(forwardDir,targetDir),-1,1);//限制范围,否则可能会超出范围导致下一步报错  
    float Theta = Mathf.Acos(cosTheta) * 180 / Mathf.PI;//弧度制转角度制
    return Theta;
}

函数就是先做个内积得到余弦值,再取反函数。因为这个角度永远都是小于180°的,我们还需要决定旋转的方向。如果目标方向在forward轴的左半边则为正(顺时针转),如果在右半边则为负(逆时针转)。那么只需计算目标方向在右方向上的投影的正负即可(这里的右指的是正交于forward方向的轴的正方向),如下示意图

所以更改上面代码为

float GetAngle(Vector3 forward, Vector3 targetDir)
{       
    float cosTheta = Mathf.Clamp(Vector3.Dot(forward,targetDir),-1,1);//限制范围,否则可能会超出范围导致下一步报错  
    float Theta = Mathf.Acos(cosTheta) * 180 / Mathf.PI;//弧度制转角度制
    Vector3 right = new Vector3(forward.y,-forward.x,0);//得到右方向
    float rotDir = Mathf.Sign(Vector3.Dot(targetDir,-right));//得到旋转方向
    return Theta * rotDir;
}

其中为了得到右方向只需对forward方向逆时针旋转90°。

        现在可以对LookAt2D函数进行补充

void LookAt2D(Transform transform, Vector3 forward, Vector3 targetPos)
{
    Vector3 targetDir = (targetPos - transform.position).normalized;//获得目标方向单位向量
    Vector3 forwardDir = forward.normalized;//获得forward方向的单位向量
    float theta = GetAngle(forwardDir,targetDir);//计算旋转角度和方向
    transform.rotation *= Quaternion.Euler(0, 0, theta);//绕着z轴旋转theta角度
}

        最后,讲一下forward方向怎么获得。情况一,如果已知forward方向的向量表示,那就没问题。情况二,没有向量表示但是有相对transform.right的角度,可以用下面的方法得到

forward = transform.right * cos\theta + transform.forward * sin\theta

或者从transform.right出发旋转theta角度(即乘一个旋转矩阵)得到。

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值