提前预测刚体移动轨迹 预测运动轨迹

提前预测刚体移动轨迹 预测运动轨迹

  • 一、效果
  • 二、介绍
  • 三、脚本
    • RigidbodyExtension.cs 计算工具类
    • DrawLine.cs 画线工具类
  • 四、资源分享

一、效果

在这里插入图片描述

二、介绍

通过计算Unity物理系统的运动方位来判断下一步移动的位置,主要用于物体运动的提前预测,通常使用于炮弹发射,机枪发射,足球篮球网球的运动等多种真实运动的物体。

三、脚本

RigidbodyExtension.cs 计算工具类

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace Dweiss
{
    public static class RigidbodyExtension
    {
        public static Vector3[] CalculateMovement(this Rigidbody that,
               int stepCount, float timeBeteenStep)
        {
            return that.CalculateMovement(stepCount, timeBeteenStep, Vector3.zero, Vector3.zero);
        }
        public static Vector3[] CalculateMovement(this Rigidbody that,
               int stepCount, float timeBeteenStep, Vector3 addedSpeed)
        {
            return that.CalculateMovement(stepCount, timeBeteenStep, addedSpeed, Vector3.zero);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="that"></param>
        /// <param name="stepCount">Number of steps</param>
        /// <param name="timeBeteenStep">number of frames to skip</param>
        /// <param name="addedSpeed"></param>
        /// <param name="addedForce"></param>
        /// <returns></returns>
        public static Vector3[] CalculateMovement(this Rigidbody that,
               int stepCount, float timeBeteenStep, Vector3 addedSpeed, Vector3 addedForce)
        {


            //var ret = new Vector3[stepCount];

            // var addedV = (addedForce / that.mass) * Time.fixedDeltaTime;
            var v = (that.isKinematic == false ? that.velocity : Vector3.zero);// + addedSpeed + addedV;
            var a = (that.useGravity && that.isKinematic == false ? Physics.gravity : Vector3.zero);
            return CalculateMovement(that.transform.position, v, a, stepCount, timeBeteenStep, addedSpeed, addedForce, that.mass, that.drag);

            //var x = that.transform.position;
            //var calc = new Vector3[] { x, v };
            //for (var i = 0; i < stepCount; ++i)
            //{
            //    calc = CalculateNewPos(calc[0], calc[1], a, that.drag, timeBeteenStep);
            //    ret[i] = calc[0];
            //}
            //return ret;
        }

        public static Vector3[] CalculateMovement(Vector3 position, Vector3 velocity, Vector3 acc, 
               int stepCount, float timeBeteenStep, Vector3 addedSpeed, Vector3 addedForce, float mass, float drag)
        {
            var ret = new Vector3[stepCount];

            var addedV = (addedForce / mass) * Time.fixedDeltaTime;
            var v = velocity + addedSpeed + addedV;
            var a = acc;

            var x = position;
            var calc = new Vector3[] { x, v };
            for (var i = 0; i < stepCount; ++i)
            {
                calc = CalculateNewPos(calc[0], calc[1], a, drag, timeBeteenStep);
                ret[i] = calc[0];
            }
            return ret;
        }

        private static Vector3[] CalculateNewPos(Vector3 x, Vector3 v, Vector3 a, float drag, float deltaTimeCount)
        {
            var dt = Time.fixedDeltaTime;
            var aDt = a * dt;
            var dragDt = 1 - drag * dt;
            dragDt = dragDt < 0 ? 0 : dragDt;
            var acc = .5f * a * dt * dt;
            for (int i = 0; i < deltaTimeCount; ++i)
            {
                v = (v + aDt) * dragDt;
                x = x + v * dt + acc;
            }
            return new Vector3[]{ x, v };
        }


        private static Vector3 CalculateVDrag(Vector3 v, Vector3 a, float drag, int deltaTimeCount)
        {
            var dt = Time.fixedDeltaTime;
            for(int i=0; i < deltaTimeCount; ++i)
                v = (v + a * dt) * (1 - drag * dt);
            return v;
        }

        Doesn't supports 
        public static Vector3[] CalculateTime(this Rigidbody that, Vector3 targetPos)
        {
            return CalculateTime(that, targetPos, Vector3.zero, Vector3.zero);
        }
        public static Vector3[] CalculateTime(this Rigidbody that, Vector3 targetPos,
            Vector3 addedSpeed)
        {
            return CalculateTime(that, targetPos, addedSpeed, Vector3.zero);
        }
        public static Vector3[] CalculateTime(this Rigidbody that, Vector3 targetPos, 
            Vector3 addedSpeed, Vector3 addedForce)
        {

            var addedV = (addedForce / that.mass) * Time.fixedDeltaTime;

            var v = that.velocity + addedSpeed + addedV;

            var a = (that.useGravity && that.isKinematic == false ? Physics.gravity : Vector3.zero);

            var x0 = that.transform.position;
            //x = x0 +vt + .5*a*t^2
            //-b +- SQR(b*b - 4*a*c)/2*a // a= .5*a//b=v//a=x0-x
            //t12 = -v +- SQR(v*v -4 * .5 * a * (x0-x))/ 2 * .5 * a
            var x = x0 - targetPos;
            var sqr = (v.PointMul(v) - 4 * .5f * a.PointMul(x)).Sqrt();
            var t1 = (-v + sqr).PointDiv(2 * .5f * a);
            var t2 = (-v - sqr).PointDiv(2 * .5f * a);

            // a=0: (x0-x) + vt -> t = (x-x0)/v
            var tWhenA0 = x.PointDiv(v);
            //a = 0
            if (float.IsNaN(t1.x)) { t2.x = t1.x = tWhenA0.x; }
            if (float.IsNaN(t1.y)) { t2.y = t1.y = tWhenA0.y; }
            if (float.IsNaN(t1.z)) { t2.z = t1.z = tWhenA0.z; }
            // a = 0 && v = 0
            if (float.IsNaN(t1.x) && x0.x == targetPos.x) { t2.x = t1.x = 0; }
            if (float.IsNaN(t1.y) && x0.y == targetPos.y) { t2.y = t1.y = 0; }
            if (float.IsNaN(t1.z) && x0.z == targetPos.z) { t2.z = t1.z = 0; }
            return new Vector3[] { t1, t2 };
        }

        public static Vector3 Sqrt(this Vector3 v)
        {
            return new Vector3(Mathf.Sqrt(v.x), Mathf.Sqrt(v.y), Mathf.Sqrt(v.z));
        }
        public static Vector3 PointMul(this Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z);
        }

        public static Vector3 PointDiv(this Vector3 v1, Vector3 v2)
        {
            return new Vector3(v1.x / v2.x, v1.y / v2.y, v1.z / v2.z);
        }

    }
}

DrawLine.cs 画线工具类

using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Dweiss;

[RequireComponent(typeof(LineRenderer))]
public class DrawLine : MonoBehaviour {

    /// <summary>
    /// 引导线
    /// </summary>
    public LineRenderer _lr;

    /// <summary>
    /// 刚体
    /// </summary>
    public Rigidbody _rb;

    /// <summary>
    /// 跨度
    /// </summary>
    public float timeBeteenStep = 1;

    /// <summary>
    /// 跨度数量
    /// </summary>
    public int stepCount = 30;
    
    /// <summary>
    /// 加速度
    /// </summary>
    public Vector3 addedV, addedF;

    void Start() {
        
        //找引导线
        _lr = GetComponent<LineRenderer>();
        //找刚体
        _rb = GetComponent<Rigidbody>();
    }

    public void AddPower(Vector3 dir)
    {
        CalcTime();
        _rb.velocity += addedV;
        addedV = Vector3.zero;
        _rb.AddForce(dir, ForceMode.Force);
        addedF = Vector3.zero;
    }


    private void CalcTime()
    {

        Vector3[] t = _rb.CalculateTime(new Vector3(0, 0, 0),
            addedV, addedF);

        var timeT = new Vector3[]{
            new Vector3(Time.time + t[0].x, Time.time + t[0].y, Time.time + t[0].z),
            new Vector3(Time.time + t[1].x, Time.time + t[1].y, Time.time + t[1].z)
        };
    }

    #region 抛物曲线

    /// <summary>
    /// 移动走向曲线
    /// </summary>
    private void DrawMovementLine()
    {
        var res = _rb.CalculateMovement(stepCount, timeBeteenStep, addedV, addedF);
        _lr.positionCount = stepCount + 1;
        _lr.SetPosition(0, transform.position);
        for (int i = 0; i < res.Length; ++i)
        {
            _lr.SetPosition(i + 1, res[i]);
        }
    }

    #endregion

    void Update ()
    {
        DrawMovementLine();

        if (Input.GetKeyDown(KeyCode.W))
        {
            AddPower((Vector3.right + Vector3.up) * 500f);
        }
    }
}

四、资源分享

CSDN下载链接

在我的资源中搜索 RigidBodyExtension

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/265730.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

比 Eslint 快 100 倍!新一代 JS Linter 发布!

比 Eslint 快 100 倍&#xff01;新一代 JS Linter 发布&#xff01; Oxc 是用 Rust 编写的 JavaScript 语言的高性能工具集合。他们的目标是构建 JavaScript 的基本编译器工具&#xff1a;解析器、linter、格式化程序、转译器、压缩器和解析器等等&#xff0c;这次他们发布了一…

3.18 Linux 防火墙

1、iptables 概述 a. 概念介绍 自Centos7.X开始,系统自带的防火墙是filewalld,但是也同样支持iptables, 我们仍然可以用iptables来作为防火墙。 netfilter/iptables&#xff1a;IP信息包过滤系统&#xff0c;它实际上由两个组件netfilter 和 iptables 组成。 netfilter 组件…

Nginx 安装(源码编译安装)

Nginx服务器提供了Windows和Linux版本&#xff0c;本文为Linux环境下Nginx服务器的详细安装步骤。 安装环境&#xff1a; Linux服务器操作系统&#xff1a;CentOs 8.1.1911 Nginx版本&#xff1a;1.21.4&#xff08;Linux&#xff09; 安装步骤&#xff1a; 1、安装GCC、aut…

过度加大SSD内部并发何尝不是一种伤害-part1

之前存储随笔有发布过一篇关于如何通过IO并发度提升性能相关的文章&#xff1a; 扩展阅读&#xff1a;SSD基础架构与NAND IO并发问题探讨 SSD整体优化策略就是要低延迟&#xff0c;高带宽&#xff0c;增加NAND的并发度。 本文&#xff0c;我们从另外一个角度来做一些讨论。现…

MySQL代码笔记

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;那个传说中的man的主页 &#x1f3e0;个人专栏&#xff1a;题目解析 &#x1f30e;推荐文章&#xff1a;题目大解析&#xff08;3&#xff09; 目录 &#x1f449;&#x1f3fb;表的增删查改创建表格&…

TLC2543(12位A/D转换器)实现将输入的模拟电压显示到数码管上

代码&#xff1a; #include <reg51.h> #define uchar unsigned char #define uint unsigned int// 数码管0-9 unsigned char seg[] {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F}; sbit SDO P1^0; sbit SDI P1^1; sbit CS P1^2; sbit CLK P1^3; s…

Linux(一)Linux理论

文章目录 一、Linux概述1.1 体系结构1.1.1 Linux内核1.1.2 用户态与内核态1.1.3 交换空间1.1.4 CLI和GUI 1.2 开机启动过程1.3 系统运行级别1.4 Linux进程1.4.1 Linux进程通信的方法1.4.2 Linux进程状态 二、文件2.1 Linux文件系统2.2 目录结构2.3 绝对路径和相对路径2.4 日志文…

增量式旋转编码器在STM32平台上的应用

背景 旋钮是仪器仪表上一种常见的输入设备&#xff0c;它的内部是一个旋转编码器&#xff0c;知乎上的这篇科普文章对其工作原理做了深入浅出的介绍。 我们公司的功率分析仪的前面板也用到了该类设备&#xff0c;最近前面板的MCU从MSP430切换成了STM32&#xff0c;因此我要将…

HarmonyOS 多态样式

还记得我们css中有 按压 失去焦点 点击后 正常状态 的各种样式设置 那么作为前端开发 TS JS的改版 harmonyos自然也有 这里 我们编写代码如下 Entry Component struct Index {build() {Row() {Column() {TextInput()TextInput().stateStyles({//正常状态normal: {.background…

Pytorch项目,肺癌检测项目之四

# 安装图像处理 的两个包 simpleITK 和 ipyvolume # 安装缓存相关的两个包 diskcache 和 cassandra-driver import gzip from diskcache import FanoutCache, Disk from cassandra.cqltypes import BytesType from diskcache import FanoutCache,Disk,core from diskcache…

计算机组成原理第6章-(计算机的运算方法)【上】

机器数与真值 把符号“数字化”的数称为机器数,而把带“+”、“-”符号的数称为真值。 原码表示法 原码是机器数中最简单的一种表示形式,0表示整数,1表示负数。 约定整数的符号位和数值位之间用“逗号”隔开。 在原码中,0有两种表示形式:“+0”和“-0”是不一样的。 反…

C++内存管理和模板初阶

C/C内存分布 请看代码&#xff1a; int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int* ptr1 (int*)mallo…

7.5组合总和②(LC40-M)

算法&#xff1a; 相比于上一题&#xff0c;数组candidates有重复元素&#xff0c;而要求不能有重复的组合&#xff0c;所以相对于39.组合总和 (opens new window)难度提升了不少。 如何去重&#xff1f; 先把candidates排序&#xff0c;让重复的元素都在一起 单层递归时&a…

二叉搜索树 --- C++实现

目录 1.二叉搜索树的概念 2.二叉搜索树的操作 3. 二叉树的实现 4.二叉搜索树的应用 5. 二叉树的性能分析 6. 二叉树进阶练习题 1.二叉搜索树的概念 二叉搜索树又称二叉排序树&#xff0c;它或者是一棵空树&#xff0c;或者是具有以下性质的二叉树&#xff1a; 若它的左…

LDO频率补偿

频率补偿 为了维持系统稳定的条件&#xff0c;一般的做法是建立一个低频几点&#xff0c;并把第二个极点放在单位增益频率 f0db 附近。在线性稳压器中&#xff0c;这两个极点是输出极点Po和误差放大器极点Pe。在确定了哪一个极点应该是主极点后&#xff0c;补偿的目的就是理解系…

(Mac上)使用Python进行matplotlib 画图时,中文显示不出来

【问题描述】 ①报错确缺失字体&#xff1a; ②使用matplotlib画图&#xff0c;中文字体显示不出来 【问题思考】 在网上搜了好多&#xff0c;关于使用python进行matplotlib画图字体显示不出来的&#xff0c;但是我试用了下&#xff0c;对我来说都没有。有些仅使用于windows系…

Laravel框架使用phpstudy本地安装的composer用Laravel 安装器进行安装搭建

一、首先需要安装Laravel 安装器 composer global require laravel/installer 二、安装器安装好后&#xff0c;可以使用如下命令创建项目 laravel new sys 三、本地运行 php artisan serve 四、 使用Composer快速安装Laravel5.8框架 安装指定版本的最新版本&#xff08;推荐&a…

2023 年第四季度 Chainlink 产品更新

在回顾 2023 年时&#xff0c;可以明显看到 Chainlink 生态系统所取得的进步是非常显著的。 我们以三个优先事项开始了这一年&#xff1a; 推出了 CCIP&#xff08;我们的跨链互操作协议&#xff09;&#xff0c;使得跨链交易和活动更加安全。推出数据流&#xff08;Data Str…

管理 Jenkins 详细指南

目录 系统配置 安全 状态信息 故障 排除 工具和操作 系统配置 系统&#xff0c;配置全局设置和路径&#xff0c;端口更改&#xff0c;下载地址等。 工具&#xff0c;配置工具、其位置和自动安装程序。 插件&#xff0c;添加、删除、禁用或启用可以扩展 Jenkins 功能的插…

<JavaEE> 网络编程 -- 网络编程和 Socket 套接字

目录 一、网络编程的概念 1&#xff09;什么是网络编程&#xff1f; 2&#xff09;网络编程中的基本概念 1> 收发端 2> 请求和响应 3> 客户端和服务端 二、Socket套接字 1&#xff09;什么是“套接字”&#xff1f; 2&#xff09;Socket套接字的概念 3&…
最新文章