【VR开发篇】Unity3D 使用物理公式实现抛物线传送功能

  • 发布时间:2021/03/22
  • 作者:七夜丶

文章目录

  • 【VR开发篇】Unity3D 使用物理公式实现抛物线传送功能
  • 前言
  • 一、前期准备
    • 1、引擎及语言
    • 2、用到的物理公式
  • 二、核心代码
    • 1.传送射线代码
    • 2.实际表现
  • 三、总结

前言

  • 在刚接触VR开发的时候,涉及到移动时经常会用到传送,如果用平移的方式移动,可能大部分人连隔夜饭都会吐出来,所以刚开始做VR项目一般程序猿都会选择接入插件的方式开发。
  • 但一般插件的功能繁多,各种挂载,各种选择或填入参数,很麻烦,而且大多数的额外功能都用不上,最主要的就是不可用,一旦出现Bug,很难排查问题所在。
  • 常用到的VR插件有:VRTK、SteamVR Plugin等,一般用起来很鸡肋,所以就自己搞了一套支持HTCvive硬件的驱动模块插件,已经完美支持了四个项目,目前在稳定运行中,此篇文章只介绍传送模块的功能实现,VR驱动模块等后续发布。

一、前期准备

1、引擎及语言

  • 引擎:Unity3D 2019.4.13f1c1
  • 语言:C#
  • 编辑器:VisualStudio2019
  • 项目工程链接:
  • 链接:Unity2018.4.13f1示例工程百度网盘链接[提取码:qq92]

2、用到的物理公式

平抛或斜抛运动可分解为:


> 符号含义

x − 水 平 方 向 上 移 动 的 距 离 \ x -水平方向上移动的距离  x−水平方向上移动的距离
y − 竖 直 方 向 上 移 动 的 距 离 \ y -竖直方向上移动的距离  y−竖直方向上移动的距离
v 0 − 初 速 度 \ v_0 -初速度  v0​−初速度
θ − 发 射 方 向 与 水 平 面 的 夹 角 角 度 \ θ -发射方向与水平面的夹角角度  θ−发射方向与水平面的夹角角度
t − 时 间 \ t -时间  t−时间

> 水平方向的匀速直线运动

  • 匀速直线运动公式:
    x = v 0 c o s ( θ ) t \ x = v_0cos(θ)t  x=v0​cos(θ)t

> 竖直方向的变速(加速/减速)直线运动
VR项目中手柄发射的传送射线,分三种情况:

  • 1、斜上抛抛物线;

    • 竖直方向上的速度以-g的加速度逐渐变小,直至为0,然后向下以大小为g的加速度做自由落体运动。
  • 2、斜下抛抛物线;

    • 竖直方向上的速度以-g的加速度逐渐变小,直至为0,然后向下以大小为g的加速度做自由落体运动。
  • 3、平抛抛物线;

    • 以大小为g的加速度做自由落体运动。
  • 变速(减速)直线运动公式:
    y = v 0 s i n ( θ ) t − 1 2 g t 2 \ y = v_0sin(θ)t - {1 \over 2}gt^2  y=v0​sin(θ)t−21​gt2
  • 变速(加速)直线运动公式:
    y = v 0 s i n ( θ ) t + 1 2 g t 2 \ y = v_0sin(θ)t + {1 \over 2}gt^2  y=v0​sin(θ)t+21​gt2
  • 自由落体运动公式:
    y = 1 2 g t 2 \ y = {1 \over 2}gt^2  y=21​gt2

二、核心代码

1.传送射线代码

using UnityEngine;public class Test : MonoBehaviour
{/// <summary> 是否显示Debug辅助线 </summary>public bool _bIsShowDebugRay = false;/// <summary> 传送射线宿主 </summary>public Transform m_tsfTleportRayHost = null;/// <summary> 射线渲染组件 </summary>public LineRenderer m_lrTeleportRayShowLine = null;/// <summary> 射线精度(不可小于2) </summary>public int m_tPrecision = 10;/// <summary> 抛物线初速度 </summary>public float m_fVelocity = 1.0f;/// <summary> 模拟地球标准重力加速度 </summary>public float m_fG = -9.8f;/// <summary> 射线初始发射高度 </summary>private float m_fShootHeight = 2f;/// <summary> 累计时间 </summary>private float m_fAccumulateTime = 0.0f;/// <summary> 射线打到地面的最大时长 </summary>private float m_fHitLandMaxTime = 0.0f;/// <summary> 时间步长 </summary>private float m_fTimeStep = 0.0f;/// <summary> 夹角 </summary>private float m_fTheta = 0.0f;/// <summary> 符号 </summary>private int m_tSymble = 1;/// <summary> 线段使用个数 </summary>private int _tSegmentCount = 0;/// <summary> 计算得到的抛物线坐标 </summary>private Vector3 m_v3CalculatePos = Vector3.zero;/// <summary> 上一个检测点坐标 </summary>private Vector3 m_v3LastCheckPos = Vector3.zero;/// <summary> 当前检测点坐标 </summary>private Vector3 m_v3CurCheckPos = Vector3.zero;/// <summary> 检测点方向向量 </summary>private Vector3 m_v3CheckVector = Vector3.zero;/// <summary> 检测点位置坐标数组 </summary>private Vector3[] m_v3BrokenNodePos;/// <summary> 射线检测数据 </summary>private RaycastHit m_raycastHit;void Update(){if (null == m_tsfTleportRayHost){return;}// 精度修正m_tPrecision = Mathf.Clamp(m_tPrecision,2,100);// 初始赋值m_fShootHeight = Mathf.Abs(m_tsfTleportRayHost.position.y);m_fHitLandMaxTime = m_fVelocity * Mathf.Sin(m_fTheta) * 2 / Mathf.Abs(m_fG) + Mathf.Sqrt(m_fShootHeight * 2/ Mathf.Abs(m_fG));m_fTimeStep = m_fHitLandMaxTime / (m_tPrecision - 1);m_fTheta = Vector3.Angle(m_tsfTleportRayHost.forward, Vector3.ProjectOnPlane(m_tsfTleportRayHost.forward, Vector3.up)) * Mathf.Deg2Rad;m_tSymble = (m_tsfTleportRayHost.position + m_tsfTleportRayHost.forward).y > m_tsfTleportRayHost.position.y ? 1 : -1;m_fAccumulateTime = 0;// 自动扩容if (null == m_v3BrokenNodePos || m_v3BrokenNodePos.Length != m_tPrecision){m_v3BrokenNodePos = new Vector3[m_tPrecision];}// 计算抛物线轨迹for (int i = 0; i < m_tPrecision; i++){if (0 == i){m_v3LastCheckPos = m_tsfTleportRayHost.position - m_tsfTleportRayHost.forward;}// 时间T时,平抛距离的计算点坐标m_v3CalculatePos.z = m_fVelocity * Mathf.Cos(m_fTheta) * m_fAccumulateTime;// 时间T时,竖直上抛距离的计算点坐标m_v3CalculatePos.y = m_fVelocity * Mathf.Sin(m_fTheta) * m_fAccumulateTime * m_tSymble + 0.5f * m_fG * m_fAccumulateTime * m_fAccumulateTime;// 计算当前检测点坐标m_v3CurCheckPos = m_tsfTleportRayHost.position + Quaternion.AngleAxis(m_tsfTleportRayHost.eulerAngles.y, Vector3.up) * m_v3CalculatePos;// 计算当前检测向量m_v3CheckVector = m_v3CurCheckPos - m_v3LastCheckPos;_tSegmentCount = i + 1;// 检测其他相交物体if (Physics.Raycast(m_v3LastCheckPos, m_v3CheckVector,out m_raycastHit, m_v3CheckVector.magnitude)){// 打到物体后,最后一段线段使用HitPoint - LastCheckPosm_v3CheckVector = m_raycastHit.point - m_v3LastCheckPos;m_v3BrokenNodePos[i] = m_raycastHit.point;// 辅助线TestDebugLine(m_v3LastCheckPos, m_v3CheckVector, Color.green, m_v3CheckVector.magnitude);break;}else{m_v3BrokenNodePos[i] = m_v3CurCheckPos;// 辅助线TestDebugLine(m_v3LastCheckPos, m_v3CheckVector, Color.green, m_v3CheckVector.magnitude);}m_v3LastCheckPos = m_v3CurCheckPos;m_fAccumulateTime += m_fTimeStep;}// 渲染抛物线m_lrTeleportRayShowLine.positionCount = _tSegmentCount;m_lrTeleportRayShowLine.SetPositions(m_v3BrokenNodePos);}/// <summary> 测试用的Debug线 </summary>private void TestDebugLine(Vector3 _v3Origion, Vector3 _v3Target, Color _color, float _fLength){if (!_bIsShowDebugRay){return;}
#if UNITY_EDITORDebug.DrawRay(_v3Origion, _v3Target, _color, _fLength);
#endif}
}

2.实际表现




三、总结

  • 以上为VR传送射线的算法,不需要任何其他插件和组件,传送射线的美化和项目接入需要根据不同项目做处理,在此不做过多赘述;
  • 如果有更好的实现方式和表现方式,请多多指点和学习交流~
  • 如果在VR项目开发或者游戏开发中遇到问题,欢迎随时留言交流~会在看到留言的第一时间回复!

【VR开发篇】Unity3D 使用物理公式实现抛物线传送功能相关推荐

  1. Unity3d 基于物理渲染Physically-Based Rendering之最终篇

    前情提要: 讲求基本算法 Unity3d 基于物理渲染Physically-Based Rendering之specular BRDF plus篇 Unity3d 基于物理渲染Physically-B ...

  2. Unity3D 升级2020版VR开发的一些问题

    Unity3D升级2020版VR开发可能遇到的一些问题 1.Unity3D 2020版VR已经整合到XR中并统一以插件包形式提供 在Unity2020版本以前,打开VR功能是在Player Setti ...

  3. VR丨有哪些靠谱的VR开发工具之引擎篇

    转载:http://www.uisdc.com/vr-tools-design-engine @C7210 :靠谱的工具都有哪些?在不同的学习阶段又该怎样进行合理的选择?本文将聚焦于这两个问题向你介绍 ...

  4. 初识UE4 VR开发一

    初识UE4 VR开发一 开篇 开始开发前的准备 编程基础 C++类 C++ 类定义 C++类的实例化 开篇 我是一个2020年毕业软件专业的毕业生,快要毕业了,已经厌倦了用java去创建一个工程,编写 ...

  5. 视频教程-C# For Unity系列之基础篇-Unity3D

    C# For Unity系列之基础篇 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过程.软件架构设计理 ...

  6. unity5.3 VR开发

    转载来自 http://toutiao.com/i6226112237539426818/ 请注重原创 不知道怎么开发VR游戏?Unity5.3官方VR教程重磅登场 2015-12-09 10:55 ...

  7. 视频教程-C# For Unity系列之中级篇-Unity3D

    C# For Unity系列之中级篇 二十多年的软件开发与教学经验IT技术布道者,资深软件工程师.具备深厚编程语言经验,在国内上市企业做项目经理.研发经理,熟悉企业大型软件运作管理过程.软件架构设计理 ...

  8. VR开发从何入手的实战分享

    摘要: 6月25日,由CSDN主办的"[VR技术开放日]VR开发从何入手"在北京辽宁大厦隆重举行,会议邀请到小米互娱VR技术专家房燕良.焰火工坊CTO王明杨.资深VR开发工程师王秋 ...

  9. VR开发中性能问题—OculusWaitForGPU

    http://blog.csdn.net/cartzhang/article/details/50788894 VR开发中性能问题-OculusWaitForGPU 本文章由cartzhang编写,转 ...

最新文章

  1. C++零碎知识点(一)
  2. ajax在项目中怎么使用,我如何添加项目在sql中使用jQuery(ajax)通过web服务
  3. 城市中的像素灯塔-前海数据中心,深圳
  4. python调用c的配置文件_python调用c
  5. Open vswitch 之Qos rate-limiting 原理
  6. php不用框架怎么写,php框架不用写sql语句就能调用数据库里表的字段是怎么实现的...
  7. nyoj244 16进制的简单运算
  8. Visual Studio 2013 中使用断点
  9. 如何掌握mysql的查询语句_如何分析mysql的查询语句
  10. MIMO-OTFS in High-Doppler Fading Channels:Signal Detection and Channel Estimation(5)
  11. Android数据结构与算法(一):基础简介
  12. android viewholder静态,使用内部viewHolder时声明为static的原因
  13. html语言ppt,htmlppt课件
  14. 寻优算法(1)-------遗传算法(GA)附Matlab代码(copy可用)
  15. CIO:人工智能将改变企业IT
  16. Android Studio中模拟器如何输入中文、将模拟器语言设置为中文
  17. B树和B+树的查找方式及原因
  18. 东京工业大学计算机毕业生去向,打开心扉 收获东京工业大学计算机专业offer
  19. daimadaima
  20. android app代码审计,常规漏洞/缺陷整理(持续更新)

热门文章

  1. 完全平方数和问题(创新工厂涂鸦移动面试题)
  2. 法拉第效应维尔德常数_法拉第旋光效应实验讲义.doc
  3. 计算机名师工作室活动个人总结,名师工作室个人年度工作计划范文(通用3篇)...
  4. 轩辕剑天之痕java论坛_仿《天之痕》小游戏
  5. 轩辕剑-天之痕java_轩辕剑天之痕,芦家渡的宝藏当年有多少玩家得到过?
  6. 从五星酒店到大众浴室——死多头的困境
  7. 大学图书馆计算机房,图书馆计算机房与整体方案设计.doc
  8. 关于树叶的活动设计_有关树叶活动方案
  9. 把身上的名牌的衣服脱掉,换件廉价的去地铁口站着,你什么都不是!
  10. 女朋友教务系统抢课老抢不上怎么办,写个代码解决这个问题