Unity 2D游戏 模拟物理系统

1.为什么不用自带的物理系统

用unity进行2D游戏开发的时候一般都不会使用unity自带的2D物理系统,有几个因素:不可控(位置 旋转 )

2.静态的碰撞体

只带有碰撞体且没有刚体的物体属于静态碰撞体 如果需要让静态碰撞体移动 最好使用刚体使用物理方法 或者给对象加一个动力学刚体 不然也很消耗性能

3.移动

为了模拟真实的移动,你需要分别模拟 加速 匀速 减速  为了模拟这三种状态 你需要模拟加速度 和 摩擦力

1    //变速写法 2 inputHori = Input.GetAxis("Horizontal"); 3 float s = 0.8f * speedChangeFactor; 4 speedIncrement = 0; 5 frictionPower = 0; 6 7 //使用摇杆就清除所有除了遥感之外的横向反向速度 8 if (inputHori > 0.1f) 9 { 10 speedIncrement = s; 11 if (shootDir.x < 0) 12 { 13 shootx = 0; 14 shootSpeedX = 0; 15 } 16 if (reBoundDir.x < 0) 17 { 18 reBoundX = 0; 19 reboundSpeedX = 0; 20 } 21 22 } 23 else if (inputHori < -0.1f) 24 { 25 speedIncrement = -s; 26 if (shootDir.x > 0) 27 { 28 shootx = 0; 29 shootSpeedX = 0; 30 } 31 if (reBoundDir.x > 0) 32 { 33 reBoundX = 0; 34 reboundSpeedX = 0; 35 } 36 } 37 38 //摩擦力 39 if (moveSpeed > 0) { frictionPower = -Friction; } 40 else if (moveSpeed < 0) { frictionPower = Friction; } 41 42 moveSpeed += (speedIncrement + frictionPower) * Time.fixedDeltaTime; 43 44 //静止方法 (这是偷懒方法 正确写法是摩擦力不会让速度反转 暂时不知道怎么写) 45 if (Mathf.Abs(moveSpeed) < frictionPower * Time.fixedDeltaTime) 46 { moveSpeed = 0; } 47     //速度限制 48 if (Mathf.Abs(moveSpeed) > MoveSpeed) 49 { moveSpeed = (moveSpeed / Mathf.Abs(moveSpeed)) * MoveSpeed; } 50

这里的核心思路就是 利用摇杆的的变换来累计增量 而不是直接改位置 我们只对加速度进行控制 这里的 moveSpeed是一帧要移动的位置 当对加速度计算完毕后,再在Update最后一帧把所有的速度增量一起赋值给位置,因为在上一次模拟角色控制的时候在每一个需要移动的方法里都会对当前的位置进行改变,这样写虽然方便,但是主角的移动会有掉帧和卡顿的感觉,原因就是在一个Update里面多次修改主角的位置,

4.射线检测

unity里面的射线检测在使用的时候,有几个需要注意的盲点:一、3D的射线无法从碰撞体里面检测的物体,但是2D的射线可以,二、当主角一帧位移的距离大于射线长度的时候射线就会大概率检测不到。

射线检测是模拟物体是否碰到障碍,是否碰到物体的常用方法。为了解决盲点的第二个问题 ,就需要对所有的会对主角产生位移的方法,先算他们的加速度,在每一帧进行射线检测的提前将这一帧玩家要位移的距离计算出来,然后动态修改射线的长度。

注意当射线检测到的时候要注意将玩家的位置放置到合适的位置

1void HorDownRayCheck() 2 { 3 //提前计算位移量 posX是算好的这一帧的X方向的位移增量 4 lengthX = Mathf.Abs(posX); 5 lengthY = Mathf.Abs(posY); 6 if (lengthY < 0.4f) 7 { 8 lengthY = 0.4f; 9 } 10 11 if (lengthX < 0.4f) 12 { 13 lengthX = 0.4f; 14 } 15 16 if (posX > 0) 17 { 18 horiRaynub = 1; 19 } 20 else if (posX < 0) 21 { 22 horiRaynub = -1; 23 } 24 else 25 { 26 if (inputHori > 0) 27 { 28 horiRaynub = 1; 29 } 30 else if (inputHori < 0) 31 { 32 horiRaynub = -1; 33 } 34 } 35 36 RaycastHit2D horiHitOne = Physics2D.Raycast(horiRayOne.position, Vector3.right * horiRaynub, lengthX + 0.4f, 1 << 8); 37 if (horiHitOne) 38 { 39 if (horiHitOne.collider.CompareTag("VeritualGround")) 40 { 41 transform.position = new Vector2(horiHitOne.point.x - 0.34f * horiRaynub, transform.position.y); 42 isHorWallHere = true; 43 } 44 } 45 RaycastHit2D horiHitTwo = Physics2D.Raycast(horiRayTwo.position, Vector3.right * horiRaynub, lengthX + 0.4f, 1 << 8); 46 if (horiHitTwo) 47 { 48 if (horiHitTwo.collider.CompareTag("VeritualGround")) 49 { 50 transform.position = new Vector2(horiHitTwo.point.x - 0.34f * horiRaynub, transform.position.y); 51 isHorWallHere = true; 52 } 53 } 54 55 if (!horiHitOne && !horiHitTwo) 56 { 57 isHorWallHere = false; 58 } 59 60 RaycastHit2D downHitOne = Physics2D.Raycast(downRayOne.position, Vector3.down, lengthY, 1 << 8); 61 if (downHitOne) 62 { 63 if (downHitOne.collider.CompareTag("DownGround")) 64 { 65 transform.position = new Vector2(transform.position.x, downHitOne.point.y + 0.34f); 66 currentState = states.ground; 67 isDownWallHere = true; 68 jumpTimes = JumpTimes; 69 return; 70 } 71 } 72 RaycastHit2D downHitTwo = Physics2D.Raycast(downRayTwo.position, Vector3.down, lengthY, 1 << 8); 73 if (downHitTwo) 74 { 75 if (downHitTwo.collider.CompareTag("DownGround")) 76 { 77 transform.position = new Vector2(transform.position.x, downHitTwo.point.y + 0.34f); 78 currentState = states.ground; 79 isDownWallHere = true; 80 jumpTimes = JumpTimes; 81 return; 82 } 83 } 84 85 isDownWallHere = false; 86 } 87 88 void UpRayCheck() 89 { 90 if (posY < 0) return; 91 RaycastHit2D upHitOne = Physics2D.Raycast(upRayOne.position, Vector3.up, lengthX, 1 << 8); 92 if (upHitOne) 93 { 94 if (upHitOne.collider.CompareTag("UpGround")) 95 { 96 transform.position = new Vector2(transform.position.x, upHitOne.point.y - 0.34f); 97 gvec = -0.2f; 98 return; 99 } 100 } 101 RaycastHit2D upHitTwo = Physics2D.Raycast(upRayTwo.position, Vector3.up, lengthY, 1 << 8); 102 if (upHitTwo) 103 { 104 if (upHitTwo.collider.CompareTag("UpGround")) 105 { 106 transform.position = new Vector2(transform.position.x, upHitTwo.point.y - 0.34f); 107 //修改重力 让主角下坠 防止一直被上一行代码影响 这里有多种解决方法 目前这一种是配合模拟重力比较好用的 108 gvec = -0.2f; 109 return; 110 } 111 } 112 }

5.模拟重力

1void Gravity() 2 { 3 gvec += Physics2D.gravity.y * Time.fixedDeltaTime * Time.fixedDeltaTime * JumpSpeed; 4 }

将 gvec作为Y轴的增量给到付给位置就可以了 如果需要人物跳跃 只需要给gvec附一正值就可以了 jumpSeed是控制主角跳跃的速度 也同时是重力倍数

自己模拟物理移动是有趣并且很帮助理解物理的过程,重点就是模拟 当我们想要一种运动方式的时候 首先要了解它在真实世界运动的本质,不要尝试对位置直接修改一部到位。

下面这张gif是在上面代码的基础上模拟效果出来的一个三维弹球的效果 使用了球形射线 置位置 计算了入射角和反射角等

 

点赞
收藏

评论区

加载中...

相关推荐

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Unity小王子私藏的开发2D游戏的常用插件合集

Unity以开发3D游戏见长,早期版本的Unity在开发2D游戏时不慎方便,因此AssetStore出现了很多2D游戏开发引擎。现在Unity对2D游戏的支持越来越好,而这些开发2D游戏的Unity插件也得到了更多开发者的喜爱。1:RexEngine:Classic2DPlatformerEngine(https://www.os

Unity 4.x 2D游戏开发基础教程大学霸第一更

Unity4.x2D游戏开发基础教程大学霸第1章  Unity及其组成的介绍本书主要讲解的是,如何使用Unity开发2D游戏。但在开始讲解之前,最好先熟悉一下Unity这个工具。本章会首先介绍Unity的下载和安装,然后会介绍Unity界面的各组成部分,这些知

Unity 2D游戏开发快速入门第1章创建一个简单的2D游戏

Unity2D游戏开发快速入门第1章创建一个简单的2D游戏即使是现在,很多初学游戏开发的同学,在谈到Unity的时候,依然会认为Unity只能用于制作3D游戏的。实际上,Unity在2013年发布4.3版本的时候,就开始提供对制作2D游戏的支持了。例如,提供了一些专用于开发2D游戏的Unit