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 的练习。提示:有时 targetAngle
和 desiredParentAngle
也有多个有效值 ;)
我有一个角色只能开启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 的练习。提示:有时 targetAngle
和 desiredParentAngle
也有多个有效值 ;)