我试图使用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
函数中重置。
感谢您的帮助!
答案 0 :(得分:2)
您正在使用Physics.autoSimulation
。问题是如何重置位置。
修改Rigidbody的位置和旋转不同于修改其变换的位置和旋转。您想要使用变换而不是Rigidbody重置Object的变换,以便移动将立即发生,而不是在多个帧上,因为这将使其对屏幕可见。
替换:
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,然后在模拟后将它们应用回Rigidbody。 对象速度应该随着时间的推移而增加。
这与您的问题无关,但只是代码中的另一个错误。以下是对此的修复(新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 CheckPosition