首页 > Unity3D频道 > 【Unity3D研究院之游戏开发】 > Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六)
2013
02-19

Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六)

         按照正常情况游戏中角色在上坡爬坡的时候速度应该减慢,可是角色控制器组件没有帮我们做这个判断,刚好最近工作中需要做这个功能,我就用勾股定理的法则来解决这个问题。如下图所示,当角色在爬坡的时候,角色控制器默认行走的距离就是 “C” 。但是如果行走的距离是“C” 你会发现上坡的速度太快了。这里我们需要计算”b”,让角色在上坡时候一次移动的距离是”b”这样移动就很正常了。

         按照勾股定理的法则, c二次方 = a二次方 + b二次方。已知 c  和 a 我们求的b的距离即可。

Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六) - 雨松MOMO程序研究院 - 1

 

第一步:主角目前所在地形的3D坐标,以及主角面朝方向行走“一段距离”后的3D坐标。 “一段距离” 我这里使用他的行走速度也就是1秒行走的长度。

第二步:把部分代码添加入角色控制器组件。

默认角色控制器行走是走路,简单改一下让他跑步。找到UpdateSmoothedMovementDirection ()方法,加入“|isMoving” 这个判断条件。

 然后找到Update()方法,(C#和js都可以编译通过下面这段代码)

直接运行游戏,你会发现当你在爬坡的时候主角的移动速度会减少,下坡与平地的时候移动速度正常。

另外还有一个地方需要注意下。 使用角色控制器时如果你的坡度角度过于大,你会发现你的主角无法继续爬坡。如下图所示,默认坡度角度为45。如果你需要爬坡更高的角度,直接修改Slope Limit数值即可。

Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六) - 雨松MOMO程序研究院 - 2

 

当然代码中我们也可以控制角色是否可以继续爬坡,根据上述代码两点Y坐标的插值也可以判断。

接着,如果你的项目中没有使用地形元素,而是用美术建模形成的地形话,那么就需要通过射线来取得“地形”上的两个点。如下图所示。

白色射线:得到主角面朝方向一步以后的地形坐标。

蓝色线段:主角移动的起点和终点的线段。

红色射线:处理摄像机(与本章无关)

 

Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六) - 雨松MOMO程序研究院 - 3

 

 在地形之上,我们使用下面这个方法得到地形的高度。

如果项目中的地形是美术做的话,需要用射线的方式来计算。代码比较简单我就不用注释了, 就是上图中的那个白色射线,从天上射向地面。参数是模型面前下一步的将要行走的坐标,然后通过射线换算成实际Y轴高度。

 剩下的地方就和上面的代码差不多了。如果你的项目中没有使用角色控制器,用别的方式来实现移动效果,也可以使用这样的方法,总是就是勾股定理了。

最后是本文的内容的下载地址,这样看起来原理就清晰很多。欢迎留言给我,大家互相学习与进步,哇咔咔。

http://vdisk.weibo.com/s/r1xrb

最后编辑:
作者:雨松MOMO
专注移动互联网,Unity3D游戏开发
捐 赠写博客不易,如果您想请我喝一杯星巴克的话?就进来看吧!

Unity3D研究院之处理角色控制器实现上坡爬坡减速(四十六)》有 45 条评论

  1. 山石 说:

    加了角色控制器之后。两个角色不能互相穿插了,怎么办?

  2. ... 说:

    为什么下坡速度会慢?上坡正常的,用的Character Controller,Update里有添加垂直向下的“重力”。好奇怪,斜坡,楼梯都是这样子,下坡就慢。

  3. 小徐 说:

    momo,你好,我觉得这个上坡减速有点问题,运行的时候也会报错,因为第三人称模型,Z轴永远指向的前方,不会因为坡度而发生变化,那么求出来的下一秒运动的位置实际上是基于底边运行了一秒,也就是求得的c的值实际是b的长度,并不是在斜边上运行一秒的距离,如果坡度固定的话,就应该不会报错,如果坡度不固定,随着坡度越来越高,求根的时候c*2-b*2会小于0所以报了错,如果模型的Z轴会发生改变 我想直接用勾股定理应该是没问题的,所以我觉得如果用第三人称应该通过随角度的变化即时改变速度的大小,求出实际斜边的速度

  4. 雨松你好!前段时间买了你的书,感觉对初学者很有帮助。现在研究到细致一些,在角色控制器上遇到问题,在此求教:如何使角色控制器能够精确地检测碰撞边缘?比如角色站在悬崖边,向前轻微移动时预期角色掉下悬崖,但控制器的collisionFlags底边检测一直存在,导致角色一半地面,一半悬空,效果很不好。同样问题表现在陡坡时,如果陡坡斜度接近垂直,按道理角色应该直接滑落,但角色仍然一半地面,一半悬空(非关重力问题),不知你有没有碰到类似问题?求教思路,不胜感激!

  5. xz 说:

    MOMO 你好,我遇到了点问题,我在弄个坦克大战,模型是在网上找的,每个坦克都加了rigidbody后坦克都可以落到地面,但是每个坦克之间却可以互相穿过,这是为什么?

  6. xz 说:

    MOMO 你好,我遇到了点问题,我在弄个坦克大战,模型是在网上找的,每个坦克都加了rigidbody后坦克都可以落到地面,但是每个坦克之间却可以互相穿过,这是为什么?

  7. Arkks 说:

    MO哥泥嚎!学生我有个问题。我在内置地形上自定义了一个角色,用CollisionFlags.CollidedBelow判断是否着地,若是,则可操控,反之不行。问题来了,在下坡时isGrounded状态不连续,以致操作断断续续。我参考了官方的bootcamp,看不懂(= =)。ps:重力用pos.y-=G*Time.deltaTime实现,与isGrounded无关

  8. 西凡纳斯 说:

    momo你好,我之前问题可能说的不清楚。 所以在贴吧发了个帖子 有图有真相,有空希望你帮我看看。谢谢。http://tieba.baidu.com/p/2207264639

    • 雨松MOMO 说:

      我知道为什么你没能掉下来了。。 因为角色控制器是没有重力系统的,你需要用代码来实现重力。 源码里面有这一段。。verticalSpeed -= gravity * Time.deltaTime * 10; 计算了重力,然后得到移动的向量。 Vector3 movement = moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity; movement *= Time.deltaTime;最后 CharacterController controller = GetComponent(); collisionFlags = controller.Move(movement);就会感应重力。。

    • 雨松MOMO 说:

      我知道为什么你没能掉下来了。。 因为角色控制器是没有重力系统的,你需要用代码来实现重力。 源码里面有这一段。。verticalSpeed -= gravity * Time.deltaTime * 10;计算了重力,然后得到移动的向量。Vector3 movement = moveDirection * moveSpeed new Vector3 (0, verticalSpeed, 0) inAirVelocity;movement *= Time.deltaTime;最后CharacterController controller = GetComponent();collisionFlags = controller.Move(movement);就会感应重力。。

  9. 西凡纳斯 说:

    载入了一个 带动画的3d模型 想再地图上行走,但是遇到山体就穿进去了如果用了钢体 的重力的话 就会从地图上穿下去。请教一下 怎么让一个模型沿着制作的地图随意行走。动画调用会了 移动也会了 现在就是不知道 怎么沿着山体行走。

    • 雨松MOMO 说:

      你应该就山林那里增加一个collider。 然后选定一个碰撞的区域, 不用增加刚体给主角加刚体 或角色控制器(建议角色控制器) 就可以感应碰撞

      • 西凡纳斯 说:

        感谢momo回答 但还是不太懂啊 地图本身有一个地图collider 怎么再加呢我是想 实现 官方例子里的 爬坡 用了角色控制器 发现模型还是穿过了地图的山体部分。

        • 西凡纳斯 说:

          这次摊上大事了 momo 同学。我用角色控制器的move了想要的效果 可以爬坡了。但爬坡完毕后 角色的高度提高了下不来…. 又遇到下坡问题 怎么让它有重力效果呢

          • 雨松MOMO 说:

            这个就更简单了。。 代码中25行 if(b < 0) 就表示角色在下坡、通过下坡的时间还有重力就可以计算出来。 我觉得下坡没必要增加速度。。。 原始速度就可以,上坡要加,我们的项目下坡就没有加, 就上坡加了。。

          • 西凡纳斯 说:

            感谢回答 但我的问题是: 我的模型不下坡 直接成飞的了 我没用系统自带 是自己做了个模型 加入了角色控制组件。 现在只能上坡不能下坡。

          • 雨松MOMO 说:

            奇怪,我这里没出过你的问题, 非常稳定 呵呵。。

  10. 龙之瀚雨 说:

    雨松MOMO,你出版的书第85页的backAnim数组变量是什么含义呢,没有注释所以没看懂哇,呵呵?

  11. 好吧我登陆了╮(╯▽╰)╭再赞一个!

  12. 欧宇龙 说:

    momo 你真是个 大好人啊!!!momo 你真是个 大好人啊!!!

  13. 欧宇龙 说:

    喂 写一些 服务端的东西嘛 好不我想实现一个 多人在线打怪的简单DEMO 呵呵嘿嘿 老板要看 momo洗个文章 指点撒

  14. Mr.ider 说:

    MOMO哥请教一下,怎么在寻路的时候实现多端同步呢?比如点击了某个目标位置,然后多台终端显示的角色的位置信息、朝向等都是同步于服务器的,momo给个思路吧,谢谢。

  15. 欧宇龙 说:

    momo好懒啊你!! 上次发文到这次间隔了一个月…….

  16. 欧宇龙 说:

    a? b?=c?好吧 这你居然不知道怎么打!!!!!!!!!!!!!!!!!!

  17. 欧宇龙 说:

    a²+b²=c²好吧 这你居然不知道怎么打!!!!!!!!!!!!!!!!!!

  18. 雨松MOMO 说:

    自己沙发! 加油蛤蛤。。

留下一个回复

你的email不会被公开。