Unity旋转角度面向目标的各种方式

发布于 2023-02-23  174 次阅读


 // 转向目标,并且向其启动
    public void TurnAndRun(Vector3 targetPos)
    {
        if (!isAlive) return; 
        // 方式1:使用四元数插值转向
        //TrunMethodByRotation(targetPos);
        // 方式2: 叉积实现
        TrunMethodByCrossRotate(targetPos);
        // 方式3: 点积实现 TODO Fix Me 这个还有点问题...
        //TrunMethodByDotRotate(targetPos);
        // 方式4: 无脑实现
        //transform.LookAt(targetPos);


        // 移动到目标点
        /*GoToTarget();*/
    }


    // 方式1:使用四元数插值转向
    public void TrunMethodByRotation(Vector3 targetPos) {
        // 计算需要旋转的四元数,目标位置减去坦克位置,旋转轴用Y
        Quaternion targetRotation = Quaternion.LookRotation(targetPos - transform.position, Vector3.up);
        // 使用 Slerp 插值来平滑旋转过渡
        transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
    }


    // 方式2:叉积实现 https://docs.unity.cn/cn/2019.4/ScriptReference/Vector3.Cross.html
    public void TrunMethodByCrossRotate(Vector3 targetPos) { 
        Vector3 forward = transform.forward;
        Debug.Log("before" + (targetPos - transform.position));
        Vector3 toTargetDir = (targetPos - transform.position).normalized;
        Debug.Log("normalized" + (targetPos - transform.position).normalized);
        Vector3 crossValue = Vector3.Cross(forward, toTargetDir);
         
        float angle = Vector3.Angle(forward, toTargetDir); 
        Debug.Log("crossValue" + crossValue);

        if (crossValue.y >= 0)
        {
            transform.Rotate(Vector3.up, angle);
        }
        if (crossValue.y < 0)
        {
            transform.Rotate(Vector3.up, -angle);
        }  
    }
    // 方式3:点积实现 TODO Fix Me https://docs.unity.cn/cn/2019.4/ScriptReference/Vector3.Dot.html
    public void TrunMethodByDotRotate(Vector3 targetPos)
    {
        Vector3 forward = transform.forward.normalized;
        Vector3 toTargetDir = (targetPos - transform.position).normalized;
        float dotValue = Vector3.Dot(forward, toTargetDir);
        float angle = Vector3.Angle(forward, toTargetDir);
      
        Debug.Log(dotValue);
        if (dotValue > 0)
        {
            transform.Rotate(Vector3.up, angle);
        }
        if (dotValue < 0)
        {
            transform.Rotate(Vector3.up, -angle);
        }
    }