3

首先,这里是问题的视频: 链接到视频,这里是 ,这里是层次结构的屏幕截图: 在此处输入图像描述 GUN 是带有脚本的父级(空游戏对象) 暂停被丢弃到towerRotateObj并且 Gun 被丢弃在turretRotateObj. Suspension 和 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;
    }
}

所以,它是一个类似的设置,就像坦克的塔和枪......我已经在这里发布了这个问题,但似乎很少有人看到这个帖子......任何建议都值得赞赏!谢谢。

更新:

    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);

问题保持不变:(

4

3 回答 3

3

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

首先,当您为对象创建父对象时,您并没有使用该功能!这是 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 轴,因为我很懒惰。因此,如果您只复制粘贴此代码,枪管将指向框架,但枪会正确跟随目标。

由于旋转现在是局部的,你可以旋转船多年,枪永远不会得到任何偏移。

于 2012-10-28T13:45:57.260 回答
1

好吧,我不确定,但您似乎遇到了Gimbal Lock问题。尽管您的计算是从四元数开始的,但从长远来看,这两个调用可能Mathf.SmoothDampAngle是根本原因。

所以我建议首先删除所有平滑,然后,如果这是罪魁祸首,用纯四元数的方法替换这些方法,比如Quaternion.Slerp

于 2012-10-24T17:21:54.090 回答
0

从 Update 更改为LateUpdate后,我无法重现您的问题。也许我没有像你一样颠簸旋转,但我认为小玩意儿的旋转是在炮塔旋转之前和之后应用的,并且错误正在累积。

于 2012-10-29T07:17:04.383 回答