如何旋转至面向某个物体

来源:互联网 发布:java开发人员简历 编辑:程序博客网 时间:2024/06/05 15:22

为了使某个物体A通过旋转面向另一物体B,如AI转向玩家。

旋转1

通常会先考虑判断B在A的左边还是右边,然后在控制A向左转或者向右转。当A的forward和B的夹角小于某一个值时则认为A已经面向了B,这时停止旋转。

        //先将目标坐标转换到本地坐标系        Vector3 pos = transform.InverseTransformPoint(target.position);               //将A和B转到同一平面               pos.y = 0;         if (Vector3.Angle(Vector3.forward, pos) > 1)        {            //用向量乘积判断左右            Vector3 cross = Vector3.Cross(Vector3.forward, pos);            if (cross.y > 0)            {                //右边                transform.Rotate(new Vector3(0, rotateSpeed * Time.deltaTime, 0));            }            else            {                //左边                transform.Rotate(new Vector3(0, -1 * rotateSpeed * Time.deltaTime, 0));            }        }


旋转2

平滑的旋转

用到了两个API
public static Quaternion LookRotation(Vector3forward,Vector3upwards = Vector3.up);

参数:
        forward        要面向的方向
        upwards      定义up方向的向量

描述:
       用forward和upwards创建一个旋转。
       返回一个经过计算的四元数。如果用来确定Transform的方向,z轴与 forward对齐,y轴与upwards对齐。


public static Quaternion Slerp(Quaterniona,Quaternionb,floatt);


描述:

       通过t返回a和b之间的差值。t必须在0和1之间。

        


代码:

        Vector3 lookForward = target.position - transform.position;        lookForward.y = 0;        Quaternion lookQua = Quaternion.LookRotation(lookForward);        transform.rotation = Quaternion.Slerp(transform.rotation, lookQua, rotateSpeed * Time.deltaTime);
这种方式会产生一个平滑的旋转,旋转速度会在快要结束时逐渐减小。




旋转3

有时候我们希望每次的旋转幅度都是常量,而不是在结尾的时候减小。

用到的API

public static float MoveTowardsAngle(float current,float target,float maxDelta);


描述:

      类似于MoveTowards, 但是这个函数确保其值在超过360度时仍然是正确的。

      变量current和target被假定为角度。为了最优化的原因,不支持maxDelta为负值,如果为负值肯能出现摆动。

      (这个函数每次执行就是在current的基础上增加maxDelta,但是结果不会超过target。如果target大于current,就执行current+maxDelta,如果target小于current则执行   current-maxDelta)


代码:

Vector3 lookForward = target.position - transform.position;        lookForward.y = 0;        Quaternion lookQua = Quaternion.LookRotation(lookForward);        float targetAngle = lookQua.eulerAngles.y;        float currentAngle = transform.rotation.eulerAngles.y;        float nextAngle = Mathf.MoveTowardsAngle(currentAngle, targetAngle, rotateSpeed * Time.deltaTime);        transform.eulerAngles = new Vector3(0, nextAngle, 0);

这种方式不用考虑向左转还是向右转的问题

 

0 0