物理模拟重力 斜抛运动计算 抛物线计算

news2025/1/19 8:07:08

物理模拟重力 斜抛运动计算 抛物线计算

  • 一、介绍
  • 二、原理
  • 三、实现如下
    • PhysicsUtil.cs 工具类
    • Missile.cs
  • 四、资源分享

一、介绍

在这里插入图片描述
模拟Unity原始重力系统进行重写,可是实现发射到指定目标位置并能继续当前力进行自身的弹力与摩擦继续运动

二、原理

将Unity原始不受控制的物理系统使用一个模拟重力的方式进行斜抛等操作,在其落地瞬间将模拟的重力还原给Unity的原始重力,从而达到可任意抛物线移动的物理系统

三、实现如下

PhysicsUtil.cs 工具类

using UnityEngine;

/// <summary> 物理计算工具
/// <para>ZhangYu 2018-05-10</para>
/// </summary>
public static class PhysicsUtil
{

    /**findInitialVelocity
     * Finds the initial velocity of a projectile given the initial positions and some offsets
     * @param Vector3 startPosition - the starting position of the projectile
     * @param Vector3 finalPosition - the position that we want to hit
     * @param float maxHeightOffset (default=0.6f) - the amount we want to add to the height for short range shots. We need enough clearance so the
     * ball will be able to get over the rim before dropping into the target position
     * @param float rangeOffset (default=0.11f) - the amount to add to the range to increase the chances that the ball will go through the rim
     * @return Vector3 - the initial velocity of the ball to make it hit the target under the current gravity force.
     * 
     *      Vector3 tt = findInitialVelocity (gameObject.transform.position, target.transform.position);
            Rigidbody rigidbody = gameObject.GetComponent<Rigidbody> ();
            Debug.Log (tt);
            rigidbody.AddForce(tt*rigidbody.mass,ForceMode.Impulse);
     */
    public static Vector3 GetParabolaInitVelocity(Vector3 from, Vector3 to, float gravity = 9.8f, float heightOff = 0.0f, float rangeOff = 0.11f)
    {
        // get our return value ready. Default to (0f, 0f, 0f)
        Vector3 newVel = new Vector3();
        // Find the direction vector without the y-component
        /// /找到未经y分量的方向矢量//
        Vector3 direction = new Vector3(to.x, 0f, to.z) - new Vector3(from.x, 0f, from.z);
        // Find the distance between the two points (without the y-component)
        //发现这两个点之间的距离(不y分量)//
        float range = direction.magnitude;
        // Add a little bit to the range so that the ball is aiming at hitting the back of the rim.
        // Back of the rim shots have a better chance of going in.
        // This accounts for any rounding errors that might make a shot miss (when we don't want it to).
        range += rangeOff;
        // Find unit direction of motion without the y component
        Vector3 unitDirection = direction.normalized;
        // Find the max height
        // Start at a reasonable height above the hoop, so short range shots will have enough clearance to go in the basket
        // without hitting the front of the rim on the way up or down.
        float maxYPos = to.y + heightOff;
        // check if the range is far enough away where the shot may have flattened out enough to hit the front of the rim
        // if it has, switch the height to match a 45 degree launch angle
        //if (range / 2f > maxYPos)
        //  maxYPos = range / 2f;
        if (maxYPos < from.y)
            maxYPos = from.y;

        // find the initial velocity in y direction
        /// /发现在y方向上的初始速度//
        float ft;
        ft = -2.0f * gravity * (maxYPos - from.y);
        if (ft < 0) ft = 0f;
        newVel.y = Mathf.Sqrt(ft);
        // find the total time by adding up the parts of the trajectory
        // time to reach the max
        //发现的总时间加起来的轨迹的各部分//
        //时间达到最大//

        ft = -2.0f * (maxYPos - from.y) / gravity;
        if (ft < 0)
            ft = 0f;

        float timeToMax = Mathf.Sqrt(ft);
        // time to return to y-target
        //时间返回到y轴的目标//

        ft = -2.0f * (maxYPos - to.y) / gravity;
        if (ft < 0)
            ft = 0f;

        float timeToTargetY = Mathf.Sqrt(ft);
        // add them up to find the total flight time
        //把它们加起来找到的总飞行时间//
        float totalFlightTime;

        totalFlightTime = timeToMax + timeToTargetY;

        // find the magnitude of the initial velocity in the xz direction
        /// /查找的初始速度的大小在xz方向//
        float horizontalVelocityMagnitude = range / totalFlightTime;
        // use the unit direction to find the x and z components of initial velocity
        //使用该单元的方向寻找初始速度的x和z分量//
        newVel.x = horizontalVelocityMagnitude * unitDirection.x;
        newVel.z = horizontalVelocityMagnitude * unitDirection.z;
        return newVel;
    }

    /// <summary> 计算抛物线物体在下一帧的位置 </summary>
    /// <param name="position">初始位置</param>
    /// <param name="velocity">移动速度</param>
    /// <param name="gravity">重力加速度</param>
    /// <param name="time">飞行时间</param>
    /// <returns></returns>
    public static Vector3 GetParabolaNextPosition(Vector3 position, Vector3 velocity, float gravity, float time)
    {
        velocity.y += gravity * time;
        return position + velocity * time;
    }

}

Missile.cs

using UnityEngine;

/// <summary>
/// 抛物线导弹
/// <para>计算弹道和转向</para>
/// <para>ZhangYu 2019-02-27</para>
/// </summary>
public class Missile : MonoBehaviour
{

    public Transform target;        // 目标
    public float hight = 16f;       // 抛物线高度
    public float gravity = -9.8f;   // 重力加速度
    private Vector3 position;       // 我的位置
    private Vector3 dest;           // 目标位置
    private Vector3 velocity;       // 运动速度
    private float time = 0;         // 运动时间

    private void Start()
    {
        dest = target.position;
        position = transform.position;
        velocity = PhysicsUtil.GetParabolaInitVelocity(position, dest, gravity, hight, 0);
        transform.LookAt(PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, Time.deltaTime));
        
    }

    private void Update()
    {
        // 计算位移
        float deltaTime = Time.deltaTime;
        position = PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, deltaTime);
        transform.position = position;
        time += deltaTime;
        velocity.y += gravity * deltaTime;

        // 计算转向
        transform.LookAt(PhysicsUtil.GetParabolaNextPosition(position, velocity, gravity, deltaTime));

        // 简单模拟一下碰撞检测
        if (position.y <= dest.y)
        {
            if (Vector3.Distance(transform.position,target.position)>= 2) return;
            GetComponent<Rigidbody>().useGravity = true;
            GetComponent<Rigidbody>().velocity = velocity;
            enabled = false;
        };
    }

}

四、资源分享

CSDN下载链接

在我的资源中搜索 PhysicsMissile

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

鸿蒙开发4.0-ArkTS与H5的交互

ArkTS侧与H5的交互 首先在开发H5页面&#xff08;输入框和金额选择部分&#xff09;前需要实现JSBridge桥接打通两侧的交互。开发者可以在ArkTS侧定义一个JSBridge类&#xff0c;在类中封装call方法以及initJsBridge方法。 准备异步执行脚本&#xff0c;在脚本中声明一个JSBri…

工具系列:PyCaret介绍_Fugue 集成_Spark、Dask分布式训练

工具系列&#xff1a;PyCaret介绍_Fugue 集成_Spark、Dask分布式训练 Fugue 是一个低代码的统一接口&#xff0c;用于不同的计算框架&#xff0c;如 Spark、Dask。PyCaret 使用 Fugue 来支持分布式计算场景。 目录 1、分布式计算示例&#xff1a; (1)分类 (2)回归 (3)时间…

7.5组合总和②(LC40-M)

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

MATLAB - 读取双摆杆上的 IMU 数据

系列文章目录 前言 本示例展示了如何从安装在双摆杆上的两个 IMU 传感器生成惯性测量单元 (IMU) 读数。双摆使用 Simscape Multibody™ 进行建模。有关使用 Simscape Multibody™ 构建简易摆的分步示例&#xff0c;请参阅简易摆建模&#xff08;Simscape Multibody&#xff09…

深度学习(七):bert理解之输入形式

传统的预训练方法存在一些问题&#xff0c;如单向语言模型的局限性和无法处理双向上下文的限制。为了解决这些问题&#xff0c;一种新的预训练方法随即被提出&#xff0c;即BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;。通过在大规模…

python通过JS逆向采集艺恩电影数据, 并制作可视化

嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 如果有什么疑惑/资料需要的可以点击文章末尾名片领取源码 环境使用: 版 本&#xff1a; python 3.10 编辑器&#xff1a;pycharm 2022.3.2 nodejs 模块使用: requests -> pip install requests execjs -> pip install…

python实现bp神经网络对csv文件进行数据预测

参考资源&#xff1a; sklearn库 bp神经网络[从原理到代码一篇搞定]&#xff08;2&#xff09;_sklearn 神经网络-CSDN博客 十分钟上手sklearn&#xff1a;安装&#xff0c;获取数据&#xff0c;数据预处理 - 知乎 (zhihu.com) 一个实例讲解如何使用BP神经网络(附代码) - 知…

基于STM32单片机智能手环老人防跌倒报警系统GSM短信上报毕业设计7

STM32单片机老人防跌倒报警系统GSM短信上报加速度7 演示视频&#xff08;复制到浏览器打开&#xff09;&#xff1a; 基于STM32单片机的智能手环老人防跌倒报警系统设计GSM短信上报ADXL345重力加速度检测设计DIY开发板套件7 修改接收短信手机号码视频&#xff1a; ★★★如何修…

Pycharm解释器的配置: System Intgerpreter 、Pipenv Environment、Virtualenv Environment

文章目录 前提1. 环境准备2. 了解虚拟环境 一、进入Interpreter设置页二、添加Interpreter1. 方式一2. 方式二 三、 System Interpreter四、 Pipenv Environment前提条件&#xff1a;详细步骤1&#xff09; 选择pipenv2&#xff09; 设置Base Interpreter3&#xff09; 设置Pip…

必学的maven的起步

Maven的简介 maven是什么 Maven的本质是一个项目管理工具将项目开发和管理过程抽象成一个项目对象模型&#xff08;POM&#xff09;POM&#xff1a;项目对象模型 Maven的作用&#xff1a; 项目构建&#xff1a;提供标准的、跨平台的自动化项目构建方式依赖管理&#xff1a;方…

mingw下编译opencv4.5.2

初衷&#xff1a; 加载之前的模型没问题&#xff0c;但最近加载另一个模型时出现报错&#xff1a; OpenCV: terminate handler is called! The last OpenCV error is: OpenCV(4.1.0) Error: Assertion failed (nodesMapIt ! nodesMap.end()) in sortByExecutionOrder, file G…

R软件包ConsensusCluster进行共识聚类(Consensus Clustering)

从下面论文看到这个方法&#xff1a; Wang, Xin, et al. "Deep learning using bulk RNA-seq data expands cell landscape identification in tumor microenvironment." Oncoimmunology 11.1 (2022): 2043662. 这篇论文基于 AI 方法对 bulk RNA-seq 数据识别肿瘤微环…

qt项目-《图像标注软件》源码阅读笔记-Shape类绘图及其子类

目录 1. Shape 概览 2. Shape 基类 2.1 字段 2.2 方法 2.3 嵌套类型 3. Shape2D 2d形状纯虚基类 3.1 字段 3.2 方法 4. Shape3D 3d形状纯虚基类 5. Shape2D子类 5.1 Rectangle 矩形类 1. Shape 概览 功能&#xff1a;Shape类及其子类负责形状的绘制及形状的存储。…

【数据结构入门精讲 | 第十三篇】考研408、公司面试树专项练习(二)

在上一篇中我们进行了树的判断题、选择题、填空题专项练习&#xff0c;在这一篇中我们将进行编程题的相关练习。 目录 编程题R7-1 目录树R7-1 是否同一棵二叉搜索树R7-2 二叉搜索树的结构R7-3 平衡二叉树的根R7-1 完全二叉搜索树R7-1 修理牧场R7-2 嘴强王者R7-3 房屋分拆R7-4 动…

Qt/QML编程学习之心得:在QML中调用fileDialog(十六)

Qt中有一些内置的对话框dialog,比如 在QWidget工程中使用比较容易,比如 #include <QFileDialog>fileName = QFileDialog::getOpenFileName(this, tr("Open Image"), "/home/jana", tr("Image Files (*.png *.jpg *.bmp)")); 那么在QM…

【LearnOpenGL基础入门——5】着色器

目录 一.简介 二.GLSL 三.数据类型 四.输入与输出 五.Uniform 六.更多属性 一.简介 着色器(Shader)是运行在GPU上的小程序。这些小程序为图形渲染管线的某个特定部分而运行。从基本意义上来说&#xff0c;着色器只是一种把输入转化为输出的程序。着色器也是一种非常独立…

最新技术整理3款开源免费直播推流工具,实现实时视频推流、视频拉流,目标端可以是服务器、云平台、移动设备等(附源码)

最新技术整理3款开源免费直播推流工具&#xff0c;实现实时视频推流、视频拉流&#xff0c;目标端可以是服务器、云平台、移动设备等&#xff08;附源码&#xff09;。 什么是推流&#xff1f; 视频推流是指将实时的视频数据从一个源端发送到一个或多个目标端的过程。推流的源…

基于javaWeb的高校后勤报修系统的设计与实现论文

基于JavaWeb的高校后勤报修系统的设计与实现 摘 要 当下&#xff0c;正处于信息化的时代&#xff0c;许多行业顺应时代的变化&#xff0c;结合使用计算机技术向数字化、信息化建设迈进。以前学校对于后勤报修信息的管理和控制&#xff0c;采用人工登记的方式保存相关数据&…

python脚本 ssh工具 ssh上传文档 选择文档并上传到ssh服务器

此文分享一个python脚本,用于快速的定位、选择文档,并将其上传到指定的ssh服务器。 效果演示 🔥完整演示效果 👇第一步,显然,我们需要选择功能 👇第二步,我们需要定位并选择需要上传的文档 👇第三步,确认我们需要上传文档的ssh服务器 👇第四步,定位、选择…

mybatis的一级缓存使用以及禁用

目录 验证代码如下 mappper 代码 xml 中代码 实际执行代码 执行结果 DefaultSqlSession CachingExecutor BaseExecutor PerpetualCache 总结 禁用一级缓存 mapper 对应的 xml 的 select 查询设置 flushCache 属性为 true MappedStatement 的内部类 Builder 向外部变…