奇怪的对象旋转,即使旋转约束被冻结(Unity 引擎)
Weird object rotation even with rotation constraints frozen (Unity Engine)
我有一个 3D 世界的游戏space。游戏是二维的。因此,玩家的位置在 1 个轴上冻结,旋转在 2 个轴上冻结。位置冻结工作正常。然而,一些玩家在游戏过程中遇到了不想要的对象旋转,即使有冻结约束(我在 BETA 测试期间从未遇到过这样的问题)
我自己测试时的限制:
我的代码(玩家移动脚本)
public class Movement : MonoBehaviour
{
public Rigidbody rb;
public int clickForce = 500;
private Plane plane = new Plane(Vector3.up, Vector3.zero);
public float speed;
public Slider staminaBar;
private void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.centerOfMass = Vector3.zero;
rb.inertiaTensorRotation = Quaternion.identity;
}
void FixedUpdate()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Confined;
if (Input.GetMouseButton(0))
{
if (staminaBar.value > 0.25)
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float enter;
if (plane.Raycast(ray, out enter))
{
var hitPoint = ray.GetPoint(enter);
var mouseDir = hitPoint - gameObject.transform.position;
mouseDir = mouseDir.normalized;
rb.AddForce(mouseDir * clickForce);
}
Plane playerPlane = new Plane(Vector3.up, transform.position);
Ray rayy = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitdist = 0.0f;
if (playerPlane.Raycast(rayy, out hitdist))
{
Vector3 targetPoint = rayy.GetPoint(hitdist);
Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
}
}
}
}
}
提前致谢!
如@Iggy 所示,分配给变换会忽略并覆盖刚体约束。要解决此问题,您可以使用一些矢量数学和 Quaternion.LookRotation
的第二个参数将局部向上轴限制在其当前方向。评论中的解释:
if (playerPlane.Raycast(rayy, out hitdist))
{
Vector3 targetPoint = rayy.GetPoint(hitdist);
Vector3 targetDir = targetPoint - transform.position;
// Find direction orthogonal to both targetDir and current local up.
// this will become local right.
Vector3 newLocalRight = Vector3.Cross(transform.up, targetDir);
// If local up and target dir are colinear, do something sensible
// like not changing the rotation
if (newLocalRight == Vector3.zero)
{
/* something sensible */
/* doing nothing may be the sensible choice */
}
else
{
// If they are not colinear, determine the direction perpendicular to local up
// and local right. This will be the fixed forward direction.
Vector3 newLocalForward = Vector3.Cross(newLocalRight, transform.up);
// Assign a rotation using the fixed forward direction, and the current local up
Quaternion targetRotation = Quaternion.LookRotation(newLocalForward,
transform.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,
speed * Time.deltaTime);
}
}
我有一个 3D 世界的游戏space。游戏是二维的。因此,玩家的位置在 1 个轴上冻结,旋转在 2 个轴上冻结。位置冻结工作正常。然而,一些玩家在游戏过程中遇到了不想要的对象旋转,即使有冻结约束(我在 BETA 测试期间从未遇到过这样的问题)
我自己测试时的限制:
我的代码(玩家移动脚本)
public class Movement : MonoBehaviour
{
public Rigidbody rb;
public int clickForce = 500;
private Plane plane = new Plane(Vector3.up, Vector3.zero);
public float speed;
public Slider staminaBar;
private void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.centerOfMass = Vector3.zero;
rb.inertiaTensorRotation = Quaternion.identity;
}
void FixedUpdate()
{
Cursor.visible = false;
Cursor.lockState = CursorLockMode.Confined;
if (Input.GetMouseButton(0))
{
if (staminaBar.value > 0.25)
{
var ray = Camera.main.ScreenPointToRay(Input.mousePosition);
float enter;
if (plane.Raycast(ray, out enter))
{
var hitPoint = ray.GetPoint(enter);
var mouseDir = hitPoint - gameObject.transform.position;
mouseDir = mouseDir.normalized;
rb.AddForce(mouseDir * clickForce);
}
Plane playerPlane = new Plane(Vector3.up, transform.position);
Ray rayy = Camera.main.ScreenPointToRay(Input.mousePosition);
float hitdist = 0.0f;
if (playerPlane.Raycast(rayy, out hitdist))
{
Vector3 targetPoint = rayy.GetPoint(hitdist);
Quaternion targetRotation = Quaternion.LookRotation(targetPoint - transform.position);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
}
}
}
}
}
提前致谢!
如@Iggy 所示,分配给变换会忽略并覆盖刚体约束。要解决此问题,您可以使用一些矢量数学和 Quaternion.LookRotation
的第二个参数将局部向上轴限制在其当前方向。评论中的解释:
if (playerPlane.Raycast(rayy, out hitdist))
{
Vector3 targetPoint = rayy.GetPoint(hitdist);
Vector3 targetDir = targetPoint - transform.position;
// Find direction orthogonal to both targetDir and current local up.
// this will become local right.
Vector3 newLocalRight = Vector3.Cross(transform.up, targetDir);
// If local up and target dir are colinear, do something sensible
// like not changing the rotation
if (newLocalRight == Vector3.zero)
{
/* something sensible */
/* doing nothing may be the sensible choice */
}
else
{
// If they are not colinear, determine the direction perpendicular to local up
// and local right. This will be the fixed forward direction.
Vector3 newLocalForward = Vector3.Cross(newLocalRight, transform.up);
// Assign a rotation using the fixed forward direction, and the current local up
Quaternion targetRotation = Quaternion.LookRotation(newLocalForward,
transform.up);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,
speed * Time.deltaTime);
}
}