Parent 特定 child 位置和旋转的旋转

Parent rotation for specific child position and rotation

我有一个角色只能开启Y-axis,所以基本上是左右左右,如果向上就是Vector3.up。该角色有一个 child,这是手榴弹产生的位置(他的右手),现在我想弄清楚如何计算 parent 的正确旋转,所以 child 准确地看着一个目标,但只是“水平地”。 parent 的 x 和 z 旋转必须为 0。有没有办法做到这一点?如果 child 只在“水平面”上看向正确的方向,而不向上或向下看以完美地面对目标,那就可以了。

这个答案几乎符合我的要求:http://answers.unity.com/comments/1339850/view.html

唯一的问题是产生的旋转是所有三个轴的混合,而不仅仅是 y-rotation。

Afaik 你只需要反转 child 的 localEulerAngles.y

localEulerAngles 是 child 相对于 parent 的欧拉角偏移旋转。所以只取 y 分量已经告诉你 child 相对于它的 parent.

的偏移量

所以我想为了相应地旋转 parent 你会做例如

// as usual get the direction from child to target
var targetDirection = targetObject.transform.position - childObject.transform.position;

// flatten the direction by erasing any difference in the Y-axis
var targetDirectionFlat = Vector3.Scale(new Vector3(1,0,1), targetDirection).normalized;

// get the Y angle offset between parent and child 
var offset = -childObject.transform.localEulerAngles.y;

// rotate the parent to face the flattened direction minus the offset
// both are rotations around the Y axis only
parent.transform.rotation = Quaternion.LookDirection(targetDirectionFlat) * Quaternion.Euler(Vector3.up * offset);

注意:在智能手机上打字,但我希望ides能看清楚

我会用三角函数来解决这个问题。评论中的解释:

Vector3 rotAxis = Vector3.up;

// flatten child pos, target pos, char pos, and child forward.
Vector3 flatChildPos = Vector3.ProjectOnPlane(childTransform.position, rotAxis);
Vector3 flatTargetPos = Vector3.ProjectOnPlane(targetTransform.position, rotAxis);
Vector3 flatCharPos = Vector3.ProjectOnPlane(charTransform.position, rotAxis);
Vector3 flatChildForward = Vector3.ProjectOnPlane(childTransform.forward, rotAxis);

Vector3 flatCharToTarget = flatTargetPos-flatCharPos;
Vector3 flatChildToChar = flatCharPos-flatChildPos;

// Find the angle going from the direction of child to parent to the child's forward
// The sign will come in handy later
float childAngle = Vector3.SignedAngle(flatChildToChar, flatChildForward,
        rotAxis);
float absChildAngle = Mathf.Abs(childAngle);

// Find the distance between child and character:
float childDist = flatChildToChar.magnitude;

// Find the distance between character and target:
float targetDist = flatCharToTarget.magnitude;

// Consider the triangle made by character position, position of target, and
// desired child position. Use sin rule to find angle of target's corner
float targetAngle = Mathf.Rad2Deg * Mathf.Asin(
        Mathf.Sin(absChildAngle * Mathf.Deg2Rad)
        * childDist/targetDist);

// determine angle in parent's corner:
float desiredParentAngle = 180f - absChildAngle - targetAngle;

// Determine sign of angle at character from target to child. 
// It's the same as the sign of angle at child from char to target.
float sign = Mathf.Sign(childAngle);

// Consider the triangle made by character position, position of target, and 
// current child position. Determine the current signed angle in character corner.
float currentParentAngle = Vector3.SignedAngle(flatCharToTarget, -flatChildToChar, 
        rotAxis);

// Calculate the diff in angle needed to make the current triangle the desired one.
float diffAngle = desiredParentAngle * sign - currentParentAngle;

// Apply the diff in world space
Quaternion newRot = Quaternion.AngleAxis(diffAngle, rotAxis) * charTransform.rotation;

有趣的是,在某些情况下可能有两种可能的轮换。确定什么时候是这种情况以及第二次轮换留给 reader 的练习。提示:有时 targetAngledesiredParentAngle 也有多个有效值 ;)