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

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

  • 一、介绍
  • 二、原理
  • 三、实现如下
    • 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

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

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

相关文章

word2003 open word2007+

Win 7 C:\Documents and Settings\Administrator\Application Data\Microsoft\Templates 还是不行&#xff0c;重装office2003吧&#xff0c;再安装转换插件&#xff0c;但是再高版本好像没转换工具

【Linux】进程管理

ps&#xff1a;报告当前进程快照。top&#xff1a;显示任务。kill&#xff1a;给一个进程发送信号。shutdown&#xff1a;关机或重启系统。 一个程序可以发动另一个程序被表述为一个父进程可以产生一个子进程&#xff0c;内核维护每个进程的信息&#xff0c;以此来保持事情有序…

【新版】软考 - 系统架构设计师(总结笔记)

个人总结学习笔记&#xff0c;仅供参考&#xff01;&#xff01;&#xff01;! →点击 笔者主页&#xff0c;欢迎关注哦&#xff08;互相学习&#xff0c;共同成长&#xff09; 笔记目录 &#x1f4e2;【系统架构设计系列】系统架构设计专业技能 计算机组成与结构操作系统信…

如何快速实现地源热泵远程监控

地源热泵远程监控解决方案 一、项目背景 山东省潍坊市盛世花园小区地源热泵项目是一个先进的供暖与制冷系统&#xff0c;旨在为整个小区提供高效且节能的温控服务。该系统主要由地下管道网络、地源热泵单元以及室内分配系统组成。 针对现有的地源热泵系统的管理和监控问题&a…

1162字符串逆序

一&#xff1a;题目 二.思路分析 1.如果不用递归&#xff0c;可以输入字符串后&#xff0c;再逆序输出&#xff0c;但是题目要求使用递归 2.使用递归&#xff1a; 2.1输入字符&#xff0c;直到输入的字符是‘&#xff01;’&#xff0c;停止输入&#xff0c;否则继续输入&…

Redis数据一致解决方案

文章目录 前言技术积累查询缓存业务流程更新缓存业务流程 更新缓存问题解决方案写在最后 前言 当前的应用服务很多都有着高并发的业务场景&#xff0c;对于高并发的解决方案一般会用到缓存来降低数据库压力&#xff0c;并且还能够提高系统性能减少请求耗时&#xff0c;比如我们…

AndroidStudio无法新建Java工程解决办法

我用的 AS 版本是 Android Studio Giraffe | 2022.3.1 Build #AI-223.8836.35.2231.10406996, built on June 29, 2023 以往新建工程都是 New project >> Empty Activity &#xff0c; 有个选择 Java 还是 Kotlin 语言的选项&#xff0c; 之后会默认生成一个 MainActi…

系列三、安装RocketMQ(单机版)

一、安装RocketMQ&#xff08;单机版&#xff09; 1.1、前置准备 通过前面系列一、MQ简介、系列二、RocketMQ简介的文章我们知道RocketMQ是用Java语言编写的&#xff0c;所以在安装RocketMQ之前&#xff0c;需要保证Linux中的JDK是已经安装好了的&#xff0c;要不然无法安装&a…

java流浪动物保护系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web 流浪动物保护系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysql…

3.java——继承及拓展(保姆级别教程,万字解析,匠心制作)

三.继承——节省了共有属性和方法的代码&#xff1a;语法 class Student extends Person 1.继承基础 1.继承首先是面向对象中非常强的一种机制&#xff0c;他首先可以复用代码&#xff08;name ,age&#xff09;&#xff0c;让我们的获得了Person全部功能和属性&#xff0c;只…

使用keytool查看Android APK签名

文章目录 一、找到JDK位置二、使用方法2.1 打开windows命令行工具2.2 查看签名 三、如何给APK做系统签名呢? 一、找到JDK位置 安卓AS之后&#xff0c;可选择继续安装JDK&#xff0c;如本文使用amazon版本默认位置&#xff1a;C:\Users\66176.jdks\corretto-1.8.0_342可通过自…

智能优化算法应用:基于北方苍鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于北方苍鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于北方苍鹰算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.北方苍鹰算法4.实验参数设定5.算法结果6.…

数据库之MySQL的介绍

操作系统&#xff1a; windows&#xff1a;win10、win11、win7、windows Server2016 Linux/Unix &#xff1a;红帽&#xff08;RedHat&#xff09;、Bebian、SUSE MacOS Linux系统&#xff1a;CantOS&#xff08;yum、dnf&#xff09;、Ubuntu&#xff08;apt、apt—get&am…

2024 年 22 款顶级免费数据恢复软件比较 [Windows 和 Mac]

适用于 Windows 和 Mac 用户的最佳数据恢复软件下载列表和比较&#xff0c;可快速恢复丢失的数据、已删除的文件、照片或格式化的分区数据&#xff1a; 数据恢复软件是一种从任何存储介质恢复丢失文件的应用程序。它可以恢复由于病毒攻击、硬盘故障或任何其他原因而意外删除或…

机器人创新实验室任务三参考文档

一、JAVA环境配置 需要在Linux里面下载并且安装java。 sudo apt-get install openjdk-17-jre-headless 打开终端并且运行指令&#xff0c;用apt下载安装java。官方用的好像是java11&#xff0c;我安装的是java17。 如果无法定位软件安装包&#xff0c;可以试试更新一下 sudo …

极智一周 | MoE、FlashAttention、PTQ、MI300禁令、H100利润空间、戴口罩检测 And so on

欢迎关注我的公众号 [极智视界]&#xff0c;获取我的更多技术分享 大家好&#xff0c;我是极智视界&#xff0c;带来本周的 [极智一周]&#xff0c;关键词&#xff1a;MoE、FlashAttention、PTQ、MI300禁令、H100利润空间、戴口罩检测 And so on。 邀您加入我的知识星球「极智…

1856_emacs_calc使用介绍与故事

Grey 全部学习内容汇总&#xff1a; GitHub - GreyZhang/g_org: my learning trip for org-mode 1856_emacs_calc使用介绍与故事 calc是emacs内置的一个计算器&#xff0c;可以提供多种计算表达方式并且可以支持org-mode中的表格功能。 主题由来介绍 我是因为想要了解org-…

c语言的练习---BCD解密

#继续源于c语言翁恺先生 一.分析 初看这道题的时候&#xff0c;可能很多人就想选择放弃&#xff0c;但这道题实在不是考察我们对于编码的能力&#xff1b;而是我们的数学能力。 就拿它的输入样例---18&#xff0c;来举例。 我们来看---在十进制中&#xff0c;是18D&#xf…

网络协议-BIO实战和NIO编程

网络通信编程基本常识 原生JDK网络编程-BIO 原生JDK网络编程-NIO Buffer 的读写 向 Buffer 中写数据 写数据到 Buffer有两种方式: 1. 读取 Channel写到 Buffer。 2.通过 Buffer 的 put0方法写到 Buffer 里。 从 Channel 写到 Buffer …

分布式锁常见问题及其解决方案

一、为什么要使用分布式锁&#xff1f; 因为在集群下&#xff0c;相当于多个JVM&#xff0c;就相当于多个锁&#xff0c;集群之间锁是没有关联的&#xff0c;会照成锁失效从而导致线程安全问题 分布式锁可以分别通过MySQL、Redis、Zookeeper来进行实现 二、redis分布式锁的实…