父旋转的统一旋转问题

首先,这里是问题的视频:
link to video,这里是package
这是分层的屏幕截图:

GUN是具有脚本(空游戏对象)的父级.悬架被放到towerRotateObj上,而Gun则被放到turretRotateObj上.悬架和Gun也是空的游戏对象.它们只是某种组对象
这里的代码

public class WeaponMover : MonoBehavIoUr
{
    public Transform target;
    public GameObject turretRotateObj;
    public GameObject towerRotateObj;

    public float maxTowerRotationSpeed = 360.0f;
    public float maxTurretRotationSpeed = 360.0f;

    public float smoothFactorTower = 0.125f;
    public float smoothFactorTurret = 0.125f;

    public float maxTowerRotation = 130.0f;
    public float maxTurretRotation = 50.0f;

    private Vector3 m_newRotation;
    private Vector3 m_angles;
    private float m_minTowerAngle;
    private float m_maxTowerAngle;
    private float m_minTurretAngle;
    private float m_maxTurretAngle;
    private float m_velTower;
    private float m_velTurret;

    private bool m_isTransNecTower = false;
    private bool m_isTransNecTurret = false;

    // initialization
    void Start()
    {
       m_newRotation = Vector3.zero;
       m_angles = Vector3.zero;

       m_maxTowerAngle = towerRotateObj.transform.eulerAngles.y + maxTowerRotation/2;
       m_minTowerAngle = towerRotateObj.transform.eulerAngles.y - maxTowerRotation/2;

       m_maxTurretAngle = turretRotateObj.transform.eulerAngles.z + maxTurretRotation/2;
       m_minTurretAngle = turretRotateObj.transform.eulerAngles.z - maxTurretRotation/2;

       // check if rotation happens between 0/360
       // tower
       if(m_minTowerAngle <= 0.0f)
         m_minTowerAngle += 360.0f;

       if(m_maxTowerAngle >= 360.0f)
         m_maxTowerAngle -= 360.0f;

       if(m_minTowerAngle > m_maxTowerAngle)
         m_isTransNecTower = true;

       // turret
       if(m_minTurretAngle <= 0.0f)
         m_minTurretAngle += 360.0f;

       if(m_maxTurretAngle >= 360.0f)
         m_maxTurretAngle -= 360.0f;

       if(m_minTurretAngle > m_maxTurretAngle)
         m_isTransNecTurret = true;
    }

    void Update()
    {
       m_newRotation = Quaternion.LookRotation(target.position - towerRotateObj.transform.position).eulerAngles;
       m_angles = towerRotateObj.transform.rotation.eulerAngles;
       towerRotateObj.transform.rotation = Quaternion.Euler(m_angles.x,
         ClampAngle(Mathf.SmoothdampAngle(m_angles.y, 
          m_newRotation.y - 90.0f, 
          ref m_velTower, 
          smoothFactorTower, 
          maxTowerRotationSpeed), m_minTowerAngle, m_maxTowerAngle, m_isTransNecTower),
         m_angles.z);

       m_newRotation = Quaternion.LookRotation(target.position - turretRotateObj.transform.position).eulerAngles;
       m_angles = turretRotateObj.transform.rotation.eulerAngles;
       turretRotateObj.transform.rotation = Quaternion.Euler(m_angles.x,
         m_angles.y,
         ClampAngle(Mathf.SmoothdampAngle(m_angles.z, 
          -m_newRotation.x, 
          ref m_velTurret,
          smoothFactorTurret, 
          maxTurretRotationSpeed), m_minTurretAngle, maxTurretRotation, m_isTransNecTurret));
    }

    private float ClampAngle(float angle, float min, float max, bool isTranslationNecessary)
    {
       if(!isTranslationNecessary)
       {
         if(angle < min )
          return min;

         if(angle > max)
          return max;
       }
       else
       {
         if(angle > max && angle < min)
         {
          if(min - angle > angle - max)
              return max;
          else
              return min;
         }
       }

       return angle;
    }
}

因此,它具有类似的设置,例如坦克的塔和枪.
我已经发布了该问题here,但似乎很少有人看到该帖子.谢谢.

更新:

    m_newRotation = Quaternion.LookRotation(m_target.transform.position - towerRotateObj.transform.position).eulerAngles;
    m_newRotation.y -= 90f;
    m_angles = towerRotateObj.transform.rotation.eulerAngles;
    towerRotateObj.transform.rotation = Quaternion.Euler(m_angles.x, m_newRotation.y, m_angles.z);

    m_newRotation = Quaternion.LookRotation(m_target.transform.position - turretRotateObj.transform.position).eulerAngles;
    m_angles = turretRotateObj.transform.rotation.eulerAngles;
    turretRotateObj.transform.rotation = Quaternion.Euler(m_angles.x, m_angles.y, -m_newRotation.x);

问题保持不变:(

解决方法:

所以我的猜测是,万向节锁,就像在其他答案中所说的那样.但是,考虑到您正在将四元数传递给欧拉,反之亦然,因此我不确定我是否会尝试解决该问题.如果必须这样做,我就不会像您那样做,因为在对象之间使用四元数进行育儿就等于头痛不已.

首先,当您为对象做父母时,您没有使用该功能!这是Unity的一项非常可靠的功能.统一育儿:http://docs.unity3d.com/Documentation/ScriptReference/Transform-parent.html

您的每个转塔对象仅在单个局部轴上旋转.而Unity可以处理以下问题:http://docs.unity3d.com/Documentation/ScriptReference/Transform-localRotation.html

一个对象成为另一个对象的父对象时,可以在所需的轴上本地旋转它. Unity自行处理整个矩阵转换.修改对象的全局旋转时,基本上是覆盖来自育儿的转换.在这一点上,随时间推移,任何层次结构都很容易获得错误和不精确性.

编辑:有了你的包裹,我能够写出我的意思:

public class WeaponMover : MonoBehavIoUr
{
    public GameObject boat;
    public GameObject turretRotateObj;
    public GameObject towerRotateObj;
    public GameObject target;

    private Vector3 lastDirection;

    // initialization
    void Start()
    {
        lastDirection = boat.transform.forward;
    }

    void Update()
    {
        // Find direction toward our target. Use turret as origin.
        Vector3 wantedDirection = target.transform.position - turretRotateObj.transform.position;
        // Rotate our last direction toward that new best direction. Change floats to make it move faster or slower.
        lastDirection = Vector3.Rotatetowards(lastDirection, wantedDirection, 0.01f, 0.01f);

        // Find the direction local to the tower as the boat can move around!
        Vector3 towerDirection = boat.transform.InverseTransformDirection(lastDirection);
        // Remove unwanted axis
        towerDirection = new Vector3(-towerDirection.z, 0, towerDirection.x);
        towerDirection.normalize();
        // Set local rotation
        towerRotateObj.transform.localRotation = Quaternion.LookRotation(towerDirection);

        // Find the direction local to the gun, as the tower may have rotated!
        Vector3 turretDirection = towerRotateObj.transform.InverseTransformDirection(lastDirection);
        // Remove unwanted axis.
        turretDirection = new Vector3(turretDirection.x, turretDirection.y, 0);
        turretDirection.normalize();
        // Set local rotation
        turretRotateObj.transform.localRotation = Quaternion.LookRotation(turretDirection);
    }
}

注意:由于我很懒,我不得不将枪管移动到Z轴而不是X轴.因此,如果仅复制粘贴此代码,则枪管将指向框架,但枪支将正确跟随目标.

由于旋转现在是本地的,因此您可以旋转船数年,并且喷枪永远不会偏移.

相关文章

前言 本文记录unity3D开发环境的搭建 unity安装 unity有中文...
前言 有时候我们希望公告牌跟随镜头旋转永远平行面向屏幕,同...
前言 经过一段时间的学习与实际开发,unity3D也勉强算是强行...
前言 在unity中我们常用的获取鼠标点击的方法有: 1、在3D场...
前言 在之前的例子中,我们都没有用到unity的精髓,例如地形...
这篇文章将为大家详细讲解有关Unity3D中如何通过Animator动画...