如何正确使用Physics.autoSimulation?

时间:2017-09-28 18:40:18

标签: c# unity3d

我试图使用Physics.autoSimulation预测游戏对象的位置(游戏对象附有刚体)。 问题是当我触发模拟时,对象有某种闪烁。像这样:

enter image description here

我读了这个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函数中重置。

感谢您的帮助!

1 个答案:

答案 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。 对象速度应该随着时间的推移而增加。

这与您的问题无关,但只是代码中的另一个错误。以下是对此的修复(新UpdateCheckPosition功能):

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