首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何正确使用Physics.autoSimulation?

如何正确使用Physics.autoSimulation?
EN

Stack Overflow用户
提问于 2017-09-28 18:40:17
回答 1查看 1.7K关注 0票数 3

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

我读过这个thread。我开始认为我没有正确地使用autoSimulation。这是我的密码:

代码语言:javascript
复制
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函数中。

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-10-01 21:08:31

您正确地使用了Physics.autoSimulation。问题是你如何重新设置这个位置。

修改刚体的位置和旋转与改变其变换的位置和旋转是不同的。您希望用转换而不是刚体重置对象的转换,这样移动就不会在多个帧上立即发生,因为这将使它在屏幕上可见。

取代:

代码语言:javascript
复制
defaultRb.position = defaultPos;
defaultRb.rotation = defaultRot;

使用

代码语言:javascript
复制
defaultRb.transform.position = defaultPos;
defaultRb.transform.rotation = defaultRot;

而且,由于这是一个滚动球,设置velocity并不足以阻止它。您还必须设置它的angularVelocity,因为球是旋转的,并且也是平移的:

代码语言:javascript
复制
defaultRb.velocity = Vector3.zero;
defaultRb.angularVelocity = Vector3.zero;

这是您的新CheckPosition函数,没有闪烁:

代码语言:javascript
复制
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。下面是对此的修复(新的UpdateCheckPosition函数):

代码语言:javascript
复制
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
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46476204

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档