Unity实用案例之——“吃鸡”手雷弹道模拟

最近吃鸡游戏火啊,至今也吃了好几晚的鸡了,无奈手雷就是丢不准,从窗户丢雷丢几个弹出几个,各种误伤自己人……而别人家的手雷:
这里写图片描述
一般的游戏里手雷都是盲投,不过一般游戏也不会对弹道有这么精确的要求,尽管往敌人家里丢就好了,能不能炸到人全靠缘分。那么,如果把雷精确的从窗户丢进去呢,不不不,是如何在Unity里实现手雷的轨迹,从而预判手雷落点呢,今天我们就来讨论这个问题!

一、轨迹绘制

众所周知,手雷的弹道其实是一个抛物线,扔手雷的过程,其实就是给一个物体以一定的初速度的自由落体运动,在运动过程中没有碰倒任何物体前只受重力和空气阻力。这里我们不考虑空气阻力,那么快速来写一下轨迹方程

velocity += Vector3.down * Gravity * Time;
position += velocity * Time;

其中velocity是矢量,表示当前运动速度,变量类型为为Vector3;Gravity表示重力大小,乘以(0, -1, 0),表示重力矢量;最终得到当前手雷运动的位置Position。

OK,到这一步很简单,那么接下来的问题是:如何将这个抛物线绘制出来?
这里我们选择用网格绘制。要绘制抛物线,我们需要先对轨迹进行预模拟,记录抛物线上的点,然后将这些点连成线,再将线连面。首先,预模拟一次抛物线,并记录一定时间间隔(Interval)的点的位置:

int PointsCount = 100;
List<Vector3> Points = new List<Vector3>();for (int i = 0; i < PointsCount; i++)
{Points.Add(pos);velocity += Vector3.down * Gravity * Interval;pos += velocity * Interval;
}

然后另写一个类,用我们记录的点生成Mesh:

using System.Collections.Generic;
using UnityEngine;public class MeshData
{public Vector3 Up = Vector3.up;private Vector3[] vertices;private int[] triangles;private Vector2[] uvs;private int vertexIndex;private int triangleIndex;private float Width;private List<Vector3> Line;public MeshData(List<Vector3> line, float width){Line = line;Width = width;vertices = new Vector3[Line.Count * 2];uvs = new Vector2[Line.Count * 2];triangles = new int[(Line.Count - 1) * 6];vertexIndex = triangleIndex = 0;int length = Line.Count;for (int i = 0; i < length; i++) {vertices[vertexIndex] = Line[i] + Up * Width;vertices[vertexIndex + length] = Line[i] - Up * Width;uvs[vertexIndex] = new Vector2(i / (float)length, 0);uvs[vertexIndex + length] = new Vector2(i / (float)length, 1);if (i < length - 1) {AddTriangle(vertexIndex, vertexIndex + length + 1, vertexIndex + length);AddTriangle(vertexIndex + length + 1, vertexIndex, vertexIndex + 1);}vertexIndex++;}}public Mesh CreateMesh(){Mesh mesh = new Mesh();mesh.vertices = vertices;mesh.triangles = triangles;mesh.uv = uvs;
//      mesh.RecalculateNormals();return mesh;}void AddTriangle(int a, int b, int c){triangles[triangleIndex] = a;triangles[triangleIndex + 1] = b;triangles[triangleIndex + 2] = c;triangleIndex += 3;}
}

这里点的顺序是按行来的,用AddTriangle()方法来记录三角形绘制顺序,抛物线连线会按宽度(Width)来复制一份出来,这两条线形成的面就是最终的Mesh,面的朝向可以通过修改Up来做调整,最后的法线计算可以按需求来打开注释,我这里表示不需要,去掉不必要的计算。
有了Mesh,赶快把Mesh赋值给一个MeshFilter来看看效果吧:

MeshData data = new MeshData(Points, Width);
TrackRender.mesh = data.CreateMesh();

这里写图片描述
可以看到,It looks pretty good!这里,我希望可以更清楚的对比当前网格的密度和效果,添加了一小段代码对其进行编辑器扩展:

void OnSceneGUI(){Handles.color = Color.green;for (int i = 0, length = track.Points.Count; i < length; i++){Handles.SphereHandleCap(0, track.Points[i], Quaternion.identity, 1, EventType.Repaint);}}

小球表示间隔,效果如下:
这里写图片描述

二、落点位置

现在轨迹有了,那么接下来的问题是,轨迹不可能无限延长吧,那么终点在哪,改如何获取?
这里我用一个笨办法,用射线检测来做(当然也是因为我没有想到其他更好的办法,orz),两点之间做射线,如果有碰到碰撞层(提前设好碰撞层级),就代表到了轨迹的终点。好了,有了思路,代码极其简单:

        Vector3 endPos = Vector3.zero;RaycastHit hitInfo;for (int i = 0; i < PointsCount; i++){Points.Add(pos);if (i != 0 && i%RayCastSimplify == 0){Vector3 dirVec = pos - Points[i - RayCastSimplify];if (Physics.SphereCast(Points[i - RayCastSimplify], RaycastRadius, dirVec.normalized, out hitInfo, dirVec.magnitude, mask.value)){endPos = hitInfo.point;break;}}velocity += Vector3.down * Gravity * Interval;pos += velocity * Interval;}

每次记录位置时,两点之间做射线检测,如果有碰撞,则返回,并记录终点位置endPos。最后给一张合适的贴图,并在endPos再放一个合适的圈表示落点即可(我比较懒,只给了一张圆),最终效果:
这里写图片描述

OK,到这里,我们的手雷弹道功能基本完成啦!可以看到,由于落点和地面贴的太近,落点会出现闪烁情况,当然,这里只提供基本思路,剩下的完善与优化就交在你的手里了。今天就到这里,如果你有更好的解决方案,欢迎交流讨论!

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

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

相关文章

Unity3D——射击游戏(多地图,多人物,枪支切换,驾车,扔手雷等功能,堪比小型和平精英)

演示1: 演示2: 演示3: 演示4&#xff1a; 源代码和运行程序 链接&#xff1a;https://pan.baidu.com/s/1QZ9UGWPAHO1zRgW5qNCjcw?pwd4m31 提取码&#xff1a;4m31 本款游戏是一个多场景&#xff0c;多角色&#xff0c;多枪支可选的枪战游戏&#xff0c;类似于市面上的小型…

C# textBox1.Text=““与textBox1.Clear()的区别

一、区别 textbox.Text "" 和 textbox.Clear() 都可以用于清空文本框的内容&#xff0c;但它们之间有一些细微的区别。 textbox.Text "": 这种方式会将文本框的 Text 属性直接设置为空字符串。这样会立即清除文本框的内容&#xff0c;并将文本框显示为空…

几个nlp的小任务(生成任务(摘要生成))

几个nlp的小任务生成任务——摘要生成 安装库选择模型加载数据集展示数据集数据预处理 tokenizer注意特殊的 token处理组成预处理函数调用map,对数据集进行预处理微调模型,设置参数设置数据收集器,将处理好的数据喂给模型封装测评方法将参数传给 trainer,开始训练安装库 选…

Vue3(开发h5适配)

在开发移动端的时候需要适配各种机型&#xff0c;有大的&#xff0c;有小的&#xff0c;我们需要一套代码&#xff0c;在不同的分辨率适应各种机型。 因此我们需要设置meta标签 <meta name"viewport" content"widthdevice-width, initial-scale1.0">…

JDK介绍

JDK,JRE和JVM之间的关系 JVM是运行环境&#xff0c;JRE是含运行环境和相关的类库&#xff0c;跟node环境是一个意思 JDK目录介绍 目录名称说明bin该路径下存放了JDK的各种工具命令。javac和java就放在这个目录。conf该路径下存放了JDK的相关配置文件include该路径下存放了一些…

【算法训练-链表】合并两个有序链表、合并K个有序链表

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;首先&#xff0c;链表对应的数据结构在这篇Blog中&#xff1a;【基本数据结构 一】线性数据结构&#xff1a;链表&#xff0c;基于对基础知识的理解来进行题目解答。…

alias命令手册

alias&#xff1a;查看和定义别名 功能描述 alias命令用来设置指令的别名。使用alias时&#xff0c;用户可以使用单引号 ‘ ‘ 将原来的命令引起来&#xff0c;防止特殊字符导致错误。 alias命令的作用只局限于该次登入的操作。若要每次登入都能够使用这些命令别名&#xff0c;…

Ubuntu学习之alias命令

Ubuntu学习之alias命令 1.1 alias功能介绍 当我们经常需要在命令窗键入复杂冗长的命令时&#xff0c;alias就派上用场啦。alias允许用户为命令创建简单的名称或缩写&#xff0c;哪怕这个缩写只有一个字符。即为指令设置别名。 1.2 alias语法 语法&#xff1a;alias [name”va…

linux alias命令路径,Linux alias命令

本文概述 Linux的” alias”命令将shell中的一个字符串替换为另一个字符串。这是一个shell内置命令。它将复杂的命令转换为更简单的命令, 换句话说, 通过将其替换为更简单的命令来创建快捷方式。 在命令行中使用”alias”会创建一个临时的”alias”。临时alias仅在退出外壳程序…

git alias

git alias 其实之前就用过一些 alias&#xff0c;比如说 git reflog show 就是 git log -g --abbrev-commit --prettyoneline 的 alias&#xff0c;一般 alias 可以存储到 git 的 config 文件&#xff0c;repo 等级的在 .git 下&#xff0c;global 的一般在 ~/.gitconfig 或者…

【ubuntu】alias命令

目录 1 alias的作用 2 语法 &#xff08;1&#xff09;简单命令 &#xff08;2&#xff09;多条命令 3 alias永久化 &#xff08;1&#xff09;启动vim编辑器 &#xff08;2&#xff09;进入编辑模式 &#xff08;3&#xff09;退出 &#xff08;4&#xff09;source使…

Elasticsearch:Index alias

现在让我们来谈谈 Elasticsearch 最简单和最有用的功能之一&#xff1a;别名 &#xff08;alias)。为了区分这里 alias 和文章 “Elasticsearch : alias 数据类型”&#xff0c;这里的别名&#xff08;alias&#xff09;指的是 index 的别名。 别名正是他们听起来的样子; 它们是…

Linux alias 的用法

Linux alias 的用法 作者: Sway 1. 啥是alias alias的英文意思是别名. 通俗来说 alias 的概念是让方便你写一段非常非常小的小程序 如 : sway:~$ alias alias lsls --colorauto这里的意思是当你输入 ls 的时候就等同输入 ls --colorauto 但是当我们切换用户的时候 alias …

Nginx中alias与root的区别

目录&#xff1a; 一、区别二、举例说明1三、举例说明2 一、区别 Nginx指定文件路径有两种方式root和alias&#xff0c;这两者的用法区别在于对URI的处理方法不同。 二、举例说明1 alias&#xff1a; location /i/{ alias /usr/local/nginx/html/admin/&#xff1b;} #若…

详解nginx的root与alias

文章目录 1. 结论2. 详解root2.1 基本用法2.2 location的最左匹配原则2.3 index2.4 nginx location解析url工作流程2.5 末尾/ 3. 详解alias3.1 基本用法 4. 特殊情况4.1 alias指定文件4.2 root指定文件 nginx版本: 1.18.0 1. 结论 location命中后 如果是root&#xff0c;会把…

Linux命令之alias

在Linux中&#xff0c;alias命令的功能是设置命令的别名&#xff0c;用以简写命令&#xff0c;提高操作效率。根据参数的不同&#xff0c;该命令可查看已设定的别名&#xff0c;或为命令设置新的别名。对于用户自定义别名&#xff0c;仅当前登录期内有效&#xff1b;也可修改配…

Linux之alias命令

回复【1001】获取 linux常用命令速查手册 Linux alias命令用来设置指令的别名&#xff0c;对一些较长的命令进行简化。使用alias时&#xff0c;必须使用单引号将原来的命令包含&#xff0c;防止特殊字符导致错误。 命令格式 alias [-p] [name[value] ...] 命令功能 简化较长…

别名机制alias详解——一个让你少敲键盘的偷懒方式

别名机制alias——让你少敲键盘的偷懒方式 目录 别名机制alias——让你少敲键盘的偷懒方式样例环境1.从一个例子开始&#xff1a;2.别名机制alias&#xff1a;2.1 什么是alias&#xff1a;2.2 alias怎么用&#xff1a;2.3 alias的注意事项&#xff1a; 参考文献&#xff1a; 样…

Linux基础——别名(alias)

一、啥是别名? 别名&#xff08;alias&#xff09;是某个命令或者某一组命令的代称&#xff0c;和我们的小名或者外号一样&#xff0c;比如一些少数民族或者复姓的同学名字可能比较长&#xff0c;那我们一般不会每次都喊全名&#xff0c;而是用一个能特指他的另外一个名字称呼…