2012-10-23 28 views
3

首先,这里的问题视频: link to video,这里的package 这里是hierachey的截图: enter image description here 的枪是用脚本(空游戏对象)父暂停下降到towerRotateObj和枪被丢弃在turretRotateObj。悬浮和枪也是空的gameobjects。他们只是某种对象组 和这里的代码:团结旋转问题

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

问题保持不变:(

+0

该帖子太大。不太可能有人花费所有时间来了解问题所在。也不会寻找答案。尝试仅用最相关的代码提出详细的问题。 –

+1

非常有帮助。如何缩短,如果我不知道问题是什么。如果你看一看视频,你会发现问题,如果我会写出发生的事情,理解起来需要更长的时间。 – immerhart

回答

3

所以我的猜测,万向节锁,就像在其他答案中说的那样。但是,我不确定我会试图解决这个问题,考虑到你正在将四元数传递给euler,反之亦然。如果我必须这样做,我不会像你这样做,因为使用四元数来实现对象之间的父母教育等同于头痛。

首先,虽然你是父母的对象,你没有使用该功能!这是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轴的,因为我是个懒人。所以,如果你只复制粘贴这个代码,枪管将指向框架,但枪会正确地跟踪目标。

由于旋转现在是本地的,您可以旋转船舶数年,并且枪永远不会有任何偏移。

+0

http://www.file-upload.net/download-6745903/rotation.rar.html这是包。你是什​​么意思:你不是在彼此之间养育你的对象?你可能会在帖子的图片上看到,我正在使用父母... – immerhart

+0

@immerhart:那你为什么要修改对象的全局旋转而不是使用“localRotation”,而只是在一个轴上旋转对象? – LightStriker

+0

@immerhart:在这里,你可以用你的软件包来写我的意思。我使用修复代码更新了我的答案。 – LightStriker

1

好吧,我不知道,但好像你正在运行到Gimbal Lock问题虽然你的计算四元数的开始有可能。 Mathf.SmoothDampAngle这两个调用是长期的根本原因

所以,我会建议首先删除所有平滑,然后,如果这原来是罪魁祸首,取代这些方法pur基于四元数的方法,如Quaternion.Slerp

+0

k,thx。我会试试这个! – immerhart

+0

我做了更新。 – immerhart

+0

另一点是,我一次只旋转一个轴,而不是同时旋转三个轴。那么,万向节锁可以发生吗?此外,我只使用四元数,如你所说(在更新中)..:| 不,想法。我在数学不好 – immerhart

0

将更新更改为LateUpdate后,我无法重现您的问题。也许我并不像你那样反复旋转,但我认为Gizmo的旋转是在炮塔旋转前后应用的,而且错误在积累。

+0

如果是这样,游戏运行时也会累积一个错误,并且任何老化测试都会显示错误。应该构建代码,以便随着时间的推移偏移或错误永远不会累积。 – LightStriker

+0

这就是切换到LateUpdate的原因。 – Calvin

+0

无论如何,它会在LateUpdate上执行此操作,因为他正在修改先前的全局轮换。这样做时肯定会存在不精确性,因为您在每个帧处堆叠浮动不精确度,并且永远不会摆脱它。 – LightStriker