我试图用Physics.autoSimulation来预测游戏对象的位置(游戏对象有一个刚体)。问题是,当我触发模拟时,物体会有某种闪烁。如下所示:

我读过这个thread。我开始认为我没有正确地使用autoSimulation。这是我的密码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestBall : MonoBehaviour {
public float timeCheck = 3f;
public float force = 10f;
private Rigidbody rb;
void Start () {
rb = GetComponent<Rigidbody>();
}//end Start
void Update () {
if (Input.GetKeyDown(KeyCode.Space)) {
//Starts the simulation...
Physics.autoSimulation = false;
rb.AddForce(Vector3.right * force, ForceMode.Impulse);
Vector3 futurePosition = CheckPosition(rb);
print("Future position at " + futurePosition);
//...and move the GameObject for real
rb.AddForce(Vector3.right * force, ForceMode.Impulse);
}//end if
}//end Update
Vector3 CheckPosition (Rigidbody defaultRb) {
Vector3 defaultPos = defaultRb.position;
Quaternion defaultRot = defaultRb.rotation;
float timeInSec = timeCheck;
while (timeInSec >= Time.fixedDeltaTime) {
timeInSec -= Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
}//end while
Vector3 futurePos = defaultRb.position;
Physics.autoSimulation = true;
defaultRb.velocity = Vector3.zero;
defaultRb.position = defaultPos;
defaultRb.rotation = defaultRot;
return futurePos;
}//end CheckPosition
}//end TestBall就像在一个很小的时刻,游戏对象在模拟结束时移动,然后返回,因为位置重置在CheckPosition函数中。
谢谢你的帮助!
发布于 2017-10-01 21:08:31
您正确地使用了Physics.autoSimulation。问题是你如何重新设置这个位置。
修改刚体的位置和旋转与改变其变换的位置和旋转是不同的。您希望用转换而不是刚体重置对象的转换,这样移动就不会在多个帧上立即发生,因为这将使它在屏幕上可见。
取代:
defaultRb.position = defaultPos;
defaultRb.rotation = defaultRot;使用
defaultRb.transform.position = defaultPos;
defaultRb.transform.rotation = defaultRot;而且,由于这是一个滚动球,设置velocity并不足以阻止它。您还必须设置它的angularVelocity,因为球是旋转的,并且也是平移的:
defaultRb.velocity = Vector3.zero;
defaultRb.angularVelocity = Vector3.zero;这是您的新CheckPosition函数,没有闪烁:
Vector3 CheckPosition(Rigidbody defaultRb)
{
Vector3 defaultPos = defaultRb.position;
Quaternion defaultRot = defaultRb.rotation;
float timeInSec = timeCheck;
while (timeInSec >= Time.fixedDeltaTime)
{
timeInSec -= Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
}//end while
Vector3 futurePos = defaultRb.position;
Physics.autoSimulation = true;
defaultRb.velocity = Vector3.zero;
defaultRb.angularVelocity = Vector3.zero;
defaultRb.transform.position = defaultPos;
defaultRb.transform.rotation = defaultRot;
return futurePos;
}//end CheckPosition最后,您的当前代码没有在旧的强制之上添加强制。这意味着,如果您按下空格键,并再次按它,力不会添加到旧的力量之上。相反,对象被停止,然后添加一个新的力。旧的丢了。
如果您想在旧力的基础上添加新的力,则必须在仿真之前存储当前的速度和angularVelocity,然后将它们应用到仿真后的刚体中。物体的速度应该随着时间的推移而增加。
这与您的问题无关,只是代码中的另一个bug。下面是对此的修复(新的Update和CheckPosition函数):
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
//Get current velocity and angularVelocity
Vector3 defaultVelocity = rb.velocity;
Vector3 defaultAngularVelocity = rb.angularVelocity;
//Starts the simulation...
Physics.autoSimulation = false;
rb.AddForce(Vector3.right * force, ForceMode.Impulse);
Vector3 futurePosition = CheckPosition(rb, defaultVelocity, defaultAngularVelocity);
print("Future position at " + futurePosition);
//...and move the GameObject for real
rb.AddForce(Vector3.right * force, ForceMode.Impulse);
}//end if
}//end Update
Vector3 CheckPosition(Rigidbody defaultRb, Vector3 defaultVelocity, Vector3 defaultAngularVelocity)
{
Vector3 defaultPos = defaultRb.position;
Quaternion defaultRot = defaultRb.rotation;
float timeInSec = timeCheck;
while (timeInSec >= Time.fixedDeltaTime)
{
timeInSec -= Time.fixedDeltaTime;
Physics.Simulate(Time.fixedDeltaTime);
}//end while
Vector3 futurePos = defaultRb.position;
Physics.autoSimulation = true;
//Stop object force
defaultRb.velocity = Vector3.zero;
defaultRb.angularVelocity = Vector3.zero;
//Reset Position
defaultRb.transform.position = defaultPos;
defaultRb.transform.rotation = defaultRot;
//Apply old velocity and angularVelocity
defaultRb.velocity = defaultVelocity;
defaultRb.angularVelocity = defaultAngularVelocity;
return futurePos;
}//end CheckPositionhttps://stackoverflow.com/questions/46476204
复制相似问题