问题描述
我有一个只能在Y轴上旋转的字符,所以如果up是Vector3.up,则基本上是左右。角色有一个孩子,这是手榴弹产生的位置(他的右手),现在我试图弄清楚如何为父母计算正确的旋转角度,以便孩子准确地瞄准目标,但只能“水平地”瞄准目标。 ”。父级的x和z旋转必须为0。有没有办法做到这一点?如果孩子只在“水平平面”上朝着正确的方向看,而没有向上或向下看以完美面对目标,那很好。
这个答案几乎可以满足我的要求:http://answers.unity.com/comments/1339850/view.html
唯一的问题是,产生的旋转是所有三个轴的混合,而不仅仅是y旋转。
解决方法
Afaik,您只需要反转孩子的localEulerAngles.y
localEulerAngles
是子项相对于父项以欧拉角偏移的旋转角度。因此,仅采用y
组件已经可以告诉您孩子相对于其父级的偏移量。
所以我想为了将父级相应地旋转回去,例如,
// 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,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);
注意:我在智能手机上打字,但我希望这些想法能弄清楚
,我将使用三角函数解决此问题。注释中的解释:
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,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;
有趣的是,在某些情况下,可能有两次旋转。确定是什么情况,以及第二轮旋转留给读者练习。提示:targetAngle
和desiredParentAngle
有时也有多个有效值;)