Unity Physic.Simulate多场景模拟物理仿真效果、绘制运动轨迹

71 篇文章 3 订阅
40 篇文章 8 订阅

Chinar blog www.chinar.xin

Physic API 绘制运动轨迹


本文提供全流程,中文翻译。

Chinar 的初衷是将一种简单的生活方式带给世人

使有限时间 具备无限可能

Chinar —— 心分享、心创新!

助力快速理解 Physic.Simulate 绘制运动轨迹

为初学者节省宝贵的时间,避免采坑!

Chinar 教程效果:

在这里插入图片描述



全文高清图片,点击即可放大观看 (很多人竟然不知道)


1

Presentation —— 介绍


同一场景,解决多种物理效果并存问题
愤怒小鸟、桌球、爆炸....

Unity 2018.3以后支持多个物理场景

用以解决物理限制问题

看了下官方发布的视频中一个比较有意思的案例

台球轨迹案例
但我没找到官方的例子 地址在哪

于是自己实现了一个简单的效果,供大家参考学习了解 PhysicsScene的用法所在

本质就是,一个场景下 有多种物理效果。可自己定义,如何表现

举个例子

大家可以自己看下发布文档,地址如下:

Unity 2018.3发布文档!( Chinar Blog )


2

Demo —— 栗子

一个桌球场景,我们先来模拟被击打白球的运动轨迹

原理就是创建一个 白球克隆对象,在第二场景中模拟白球的物理运动轨迹,并记录轨迹!

也就是创建一个不可见的场景,用来模拟白球的运动轨迹绘制。

点击鼠标左键,击打白球,验证轨迹是否正确。二者互不影响

注意物理:两个场景完全独立

举个例子

在这里插入图片描述

代码


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.SceneManagement;
using UnityEngine.UI;


/// <summary>
/// 模拟轨迹
/// </summary>
public class ChinarForece : MonoBehaviour
{
    public  Transform    DirectionBall;      //指向方向的球
    public  Transform    TrackBallTransform; //轨迹球
    private Rigidbody    trackBallRigidbody; //
    public  Slider       VelocitySlider;     //力度值 滑动器
    public  Slider       AngleSlider;        //角度值 
    private PhysicsScene physicsScene;       //物理场景
    public  GameObject[] OtherGameObjects;   //所有小球
    public  int          TrackFrames = 80;   //轨迹帧率
    private int          ICount;             //对象计数
    private float        timer;

    /// <summary>
    /// 对象池字典
    /// </summary>
    private readonly Dictionary<int, Transform> goDict = new Dictionary<int, Transform>();


    void Start()
    {
        AngleSlider.onValueChanged.AddListener(OnValueChanged);
        trackBallRigidbody     = TrackBallTransform.GetComponent<Rigidbody>();
        Physics.autoSimulation = false;
        CreatePhysicsScene();
        GeneratePool();
    }


    /// <summary>
    /// 创建一个用于模拟的场景
    /// </summary>
    private void CreatePhysicsScene()
    {
        var scene = SceneManager.CreateScene("指向模拟场景");
        physicsScene = scene.GetPhysicsScene();
        SceneManager.MoveGameObjectToScene(DirectionBall.parent.gameObject, scene);
        for (int i = 3; i < OtherGameObjects.Length; i++)
        {
            SceneManager.MoveGameObjectToScene(OtherGameObjects[i], scene);
        }
    }


    /// <summary>
    /// 生成池子
    /// 轨迹球 重复利用
    /// </summary>
    private void GeneratePool()
    {
        var GoPoolPos = new Vector3(100, 100, 100);
        for (int i = 0; i < TrackFrames; i++)
        {
            var iclone = Instantiate(TrackBallTransform);
            iclone.position = GoPoolPos;
            iclone.localScale=Vector3.one*0.5f;
            goDict.Add(i, iclone);
        }
    }


    /// <summary>
    /// 重置球位置
    /// 其他球要隐形的
    /// </summary>
    private void resetOtherBall()
    {
        for (int i = 0; i < 3; i++)
        {
            OtherGameObjects[i + 3].transform.position = OtherGameObjects[i].transform.position;
        }
    }


    /// <summary>
    /// 角度发生改变时
    /// </summary>
    public void OnValueChanged(float value)
    {
        Physics.autoSimulation        = false; //关闭 物理模拟
        TrackBallTransform.position   = transform.position;
        trackBallRigidbody.velocity   = Vector3.zero;
        DirectionBall.parent.rotation = Quaternion.Euler(0, value, 0);
        Vector3 vector3 = DirectionBall.position - transform.position;
        trackBallRigidbody.AddForce(vector3 * VelocitySlider.value);
        for (int i = 0; i < TrackFrames; i++)
        {
            physicsScene.Simulate(0.02f);
            GoPool().position = TrackBallTransform.position;
        }
    }


    /// <summary>
    /// 简化版对象池
    /// 每次调用返回一个新对象
    /// </summary>
    private Transform GoPool()
    {
        ICount++;
        if (ICount == TrackFrames - 1)
        {
            ICount = 0;
        }

        return goDict[ICount];
    }


    void Update()
    {
        
        if (!EventSystem.current.IsPointerOverGameObject())
        {
            if (Input.GetMouseButtonUp(0))
            {
                Physics.autoSimulation = true;
                Vector3 vector3 = DirectionBall.position - transform.position;
                GetComponent<Rigidbody>().AddForce(vector3 * VelocitySlider.value);
            }
        }
    }
}

3

Demo 2 —— 栗子 2

碰撞后,被碰撞物体的运动轨迹绘制

将动量传递给碰撞对象,得到碰撞的对象。 从而记录被碰撞对象的运动轨迹

调用 physicsScene.Simulate(0.02f);完成轨迹预测;

这个API 需要 Physics.autoSimulation = false;//关闭 物理模拟

然后自行调用,每调用一次 执行一帧物理刷新

举个例子

官方文档 physicsScene.Simulate( )


支持

May Be —— 开发者,总有一天要做的事!


拥有自己的服务器,无需再找攻略

Chinar 提供一站式《零》基础教程

使有限时间 具备无限可能!

先点击领取 —— 阿里全产品优惠券 (享受最低优惠)


Chinar 免费服务器、建站教程全攻略!( Chinar Blog )


Chinar

END

本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究

对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com

对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是使用UnityPhysics.Simulate函数模拟物体沿坐标运动轨迹的程序示例: ``` using UnityEngine; public class ObjectMotion : MonoBehaviour { public float speed = 5f; // 物体移动速度 private Rigidbody rb; private Vector3 initialPosition, newPosition; private bool moveForward = true; void Start() { rb = GetComponent<Rigidbody>(); initialPosition = transform.position; newPosition = transform.position + Vector3.forward * speed; } void Update() { // 判断是否到达目标位置,如果是则反向运动 if (Vector3.Distance(transform.position, newPosition) < 0.1f) { moveForward = false; newPosition = initialPosition; } else if (Vector3.Distance(transform.position, initialPosition) < 0.1f) { moveForward = true; newPosition = transform.position + Vector3.forward * speed; } // 根据物体的移动方向进行运动模拟 if (moveForward) { Physics.Simulate(Time.fixedDeltaTime); rb.MovePosition(transform.position + Vector3.forward * speed * Time.fixedDeltaTime); } else { Physics.Simulate(Time.fixedDeltaTime); rb.MovePosition(transform.position - Vector3.forward * speed * Time.fixedDeltaTime); } } } ``` 在此示例中,我们使用了Unity中的Rigidbody来模拟物体的运动。首先在Start函数中初始化一些变量,包括物体的初始位置和目标位置,以及物体的初始运动方向为前进方向。然后在Update函数中,通过比较物体当前的位置与目标位置之间的距离,判断物体是否需要反向运动。最后,根据物体当前的运动方向调用Physics.Simulate函数进行模拟,并通过Rigidbody的MovePosition函数移动物体的位置。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值