unity3d - 在 unity3d 中使用刚体的最佳导航代码?
问题描述
我想按一次键
我的立方体向右移动并旋转 90 度
旋转做得很好
但它并没有很好地移动
using UnityEngine;
using System.Collections;
public class Player : MonoBehaviour
{
public float speed;
public float time;
public GameObject contactPoint;
private Rigidbody rig;
private void Start()
{
rig = GetComponent<Rigidbody>();
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
StartCoroutine(RotatePlayer(Vector3.forward * 90, Vector3.right, time));
}
if (Input.GetKeyDown(KeyCode.A))
{
StartCoroutine(RotatePlayer(Vector3.back * 90, Vector3.left, time));
}
}
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
Quaternion fromAngle = contactPoint.transform.rotation;
Quaternion toAngle = Quaternion.Euler(transform.eulerAngles - byAngle);
for (float t = 0; t < 1; t += Time.deltaTime / inTime)
{
rig.MovePosition(transform.position + (dir * speed * Time.deltaTime));
rig.MoveRotation(Quaternion.Slerp(fromAngle, toAngle, t));
yield return null;
}
}
}
解决方案
您的主要问题是:您应该做与物理相关的事情,例如Rigidbody
仅在FixedUpdate
.
对于 Coroutines,Unity 提供WaitForFixedUpdate
的功能与名称完全相同,确保在FixedUpdate
物理调用中执行之后的代码。
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
yield return new WaitForFixedUpdate();
// here I would also use "rig" instead of "transform"
Quaternion fromAngle = contactPoint.transform.rotation;
Quaternion toAngle = Quaternion.Euler(rig.eulerAngles - byAngle);
for (float t = 0; t < 1; t += Time.deltaTime / inTime)
{
yield return new WaitForFixedUpdate();
// here I would also use "rig" instead of "transform"
rig.MovePosition(rig.position + (dir * speed * Time.deltaTime));
rig.MoveRotation(Quaternion.Slerp(fromAngle, toAngle, t));
}
}
除此之外,有点不清楚你到底定义了什么not move well
。您还应该以某种方式确保一次只运行一个例程。通过终止已经运行的例程,例如
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
StopAllCoroutines();
StartCoroutine(RotatePlayer(Vector3.forward * 90, Vector3.right, time));
}
if (Input.GetKeyDown(KeyCode.A))
{
StopAllCoroutines();
StartCoroutine(RotatePlayer(Vector3.back * 90, Vector3.left, time));
}
}
或防止新的例程开始,直到当前的例程完成使用类似的标志
private bool alreadyRotating;
private IEnumerator RotatePlayer(Vector3 byAngle, Vector3 dir, float inTime)
{
if(alreadyRotating) yield break;
alreadyRotating = true;
......
alreadyRotating = false;
}
推荐阅读
- jmeter - Jmeter 与 UI 和数据库的交互同时插入
- android - 如何在反应原生中使用高程在android中插入盒子阴影?
- angular - ng-packagr 无法将 Angular 包发布到 npm 或如何修复 Angular Valunerablities
- javascript - 破碎的 apexcharts 图例(vue-apexcharts)
- asp.net - Azure Redis - 当模式=自定义时如何在 ASP.NET 应用程序中模拟 session_end 事件?
- c# - 我怎样才能把这个 onpaint 方法放在点击功能上?C#
- c# - 我可以为“valuetype”的 getter 和 setter 设置不同的返回类型吗?特性?
- .net-framework-version - 如何解决dotNet framework 3.5安装错误0x80080005?
- c++ - C++ 编译器可以优化这个吗
- javascript - 导航栏在不同浏览器上的显示不一致