Unity3D游戏开发之跑酷游戏项目详解

更多精彩请到http://www.gopedu.com/

今天的博客的主题就是《Unity3D游戏开发之跑酷游戏项目讲解》。

从我们自身来考虑这件事情,当你选择做自己热爱的事情的时候,你的内心一定是充满激情和勇气的,你愿意看到自己的努力,你愿意看到自己的付出,我们成长是为了促进自我对认知的不断完善,所以我们应该以一种虔诚、谦恭的态度来对待我们的生命,我们或许无法选择出身,但我们可以选择向自己喜欢的生活去努力。或许我和这些人真的不是一个世界的人吧,很多事情在今天都给出了结局,对于这种人我已经没有再尝试与之交流的想法了,或许大学四年平平淡淡,留给我的只有自己才能体会的孤独吧。好了,不说我的事情了,我们正式开始今天的内容吧!

一、游戏策划

游戏采用2D界面,角色从左到右奔跑,在路段中随机生成障碍物和金币,玩家需要使用跳跃功能躲开障碍物,在游戏中玩家收集的金币数目越多,奔跑的距离越长,玩家的得分就越高。我们最终实现的界面效果如图所示,首先我们来讲一下游戏的原理,我们这里这里采用的方法是路段固定,移动摄像机的方法。换句话说,当角色开始移动后,摄像机和场景跟随角色缓缓向右移动。当角色跑完每一个路段距离的2/3时,计算下一路段的位置,并在该位置生成一个新的路段,这样在游戏场景中可以产生无限远的路段,当某一路段离开摄像机视野时,立即将其销毁。于此同时,我们在每一个路段上随机产生障碍物和金币,然后对角色做碰撞检测即可。

二、角色控制

角色控制这里,我们只关注角色的状态,即角色是处于奔跑状态还是死亡状态。通过这一状态,我们针对角色采取不同的处理方式。如果角色处于奔跑状态,则更新角色位置、摄像机位置、背景位置,否则角色将在被障碍物撞到以后倒地死亡。我们来一起看下面的脚本:

[csharp] view
plain
copyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Player : MonoBehaviour {
  4. //定义角色移动速度
  5. public float mMoveSpeed=2.5F;
  6. //摄像机
  7. private Transform mCamera;
  8. //背景图片
  9. private Transform mBackground;
  10. //角色是否在奔跑
  11. private bool isRuning=true;
  12. //场景中路段总数目
  13. private int mCount=1;
  14. //路段预设
  15. public GameObject CubeWay;
  16. //死亡动画播放次数
  17. private int DeathCount=0;
  18. //收集的金币数目
  19. private int mCoinCount=0;
  20. public int CoinCount {
  21. get {
  22. return mCoinCount;
  23. }
  24. }
  25. //当前奔跑距离
  26. private int mLength=0;
  27. public int Length {
  28. get {
  29. return mLength;
  30. }
  31. }
  32. //当前得分
  33. private int mGrade=0;
  34. public int Grade {
  35. get {
  36. return mGrade;
  37. }
  38. }
  39. void Start ()
  40. {
  41. //获取相机
  42. mCamera=Camera.main.transform;
  43. //获取背景
  44. mBackground=GameObject.Find("Background").transform;
  45. }
  46. void Update ()
  47. {
  48. //如果角色处于奔跑状态则移动角色、相机和场景
  49. if(isRuning)
  50. {
  51. Move();
  52. CreateCubeWay();
  53. Jump();
  54. UpdateData();
  55. }else
  56. {
  57. Death();
  58. }
  59. }
  60. /// <summary>
  61. /// 更新玩家的游戏数据
  62. /// </summary>
  63. private void UpdateData()
  64. {
  65. //计算奔跑距离
  66. mLength=(int)((transform.position.x+25)*25);
  67. //计算玩家得分
  68. mGrade=(int)(mLength*0.8+mCoinCount*0.2);
  69. }
  70. ///角色死亡
  71. private void Death()
  72. {
  73. //为避免死亡动画在每一帧都更新,使用DeathCount限制其执行
  74. if(DeathCount<=1)
  75. {
  76. //播放死亡动画
  77. transform.animation.Play("Lose");
  78. //次数+1
  79. DeathCount+=1;
  80. //保存当前记录
  81. //PlayerPrefs.SetInt("这里填入一个唯一的值",Grade);
  82. }
  83. }
  84. private void Jump()
  85. {
  86. //这里不能使用刚体结构,所以使用手动方法实现跳跃
  87. if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
  88. {
  89. while(transform.position.y<=1)
  90. {
  91. float y=transform.position.y+0.02F;
  92. transform.position=new Vector3(transform.position.x,y,transform.position.z);
  93. transform.animation.Play("Jump");
  94. }
  95. StartCoroutine("Wait");
  96. }
  97. }
  98. IEnumerator Wait()
  99. {
  100. yield return new WaitForSeconds(0.8F);
  101. //角色落地继续奔跑
  102. while(transform.position.y>0.125F)
  103. {
  104. float y=transform.position.y-0.02F;
  105. transform.position=new Vector3(transform.position.x,y,transform.position.z);
  106. transform.animation.Play("Run");
  107. }
  108. }
  109. //移动角色、相机和场景
  110. private void Move()
  111. {
  112. //让角色从左到右开始奔跑
  113. transform.Translate(Vector3.forward * mMoveSpeed * Time.deltaTime);
  114. //移动摄像机
  115. mCamera.Translate(Vector3.right * mMoveSpeed * Time.deltaTime);
  116. //移动背景
  117. mBackground.Translate(Vector3.left * mMoveSpeed * Time.deltaTime);
  118. }
  119. //创建新的路段
  120. private void CreateCubeWay()
  121. {
  122. //当角色跑完一个路段的的2/3时,创建新的路段
  123. //用角色跑过的总距离计算前面n-1个路段的距离即为在第n个路段上跑过的距离
  124. if(transform.position.x+30-(mCount-1)*50 >=50*2/3)
  125. {
  126. //克隆路段
  127. //这里从第一个路段的位置开始计算新路段的距离
  128. GameObject mObject=(GameObject)Instantiate(CubeWay,new Vector3(-5F+mCount * 50F,0F,-2F),Quaternion.identity);
  129. mObject.transform.localScale=new Vector3(50F,0.25F,1F);
  130. //路段数加1
  131. mCount+=1;
  132. }
  133. }
  134. void OnTriggerEnter(Collider mCollider)
  135. {
  136. //如果碰到的是金币,则金币消失,金币数目加1;
  137. if(mCollider.gameObject.tag=="Coin")
  138. {
  139. Destroy(mCollider.gameObject);
  140. mCoinCount+=1;
  141. }
  142. //如果碰到的是障碍物,则游戏结束
  143. else if(mCollider.gameObject.tag=="Rock")
  144. {
  145. isRuning=false;
  146. }
  147. }
  148. }

在这里我们需要关注下面的内容:

1、Update()方法及Move()、Jump()、CreateCubeWay()、Death()方法,因为这是角色在奔跑过程中的核心控制方法。

2、CreateCubeWay()方法的作用是在玩家跑完每一个路段的2/3时,在指定的位置生成新的路段。假设当前场景中共有n个路段,玩家在每一个路段上奔跑的距离=用玩家从起点到当前位置的长度-前面n-1个路段的距离。通过这种方法我们可以判断玩家在每一个路段上的相对位置。在确定了这个位置后,我们将其与路段长度的2/3比较,如果大于或者等于这个距离,则生成新的路段,且第n+1个路段的位置等于第一个路段的位置+n个路段的总长度。由此,我们就实现了在指定的位置生成新的路段,使场景中源源不断的生成新的路段。

3、玩家收集金币和障碍物的碰撞检测都是在OnTrigger方法中实现的,我们使用了一个bool类型的标识变量isRuning来表示角色的状态,此状态直接影响Update()方法的执行,大家可以从代码中自己去寻找。

4、这里角色的跳跃是通过脚本模拟出来的,因为这里使用刚体似乎不能实现博主想实现的那种效果,大家可以参考Jump()方法。

三、场景布设

这里我们2D平面作为游戏的背景,使用NGUI来显示界面文字内容。在Unity3D场景中使用NGUI需要相机和Anchor设置为同一层级,并设置相机的景深,这样两个相机系统都能工作了。路段CubeWay是一个预设体Cube,负责在CubeWay上生成金币和障碍物,该对象关联在Player脚本上。玩家角色是一个3D的人物模型,最终场景布设效果如图所示:

四、预设定义

在这个游戏中需要重用的对象有路段CubeWay、金币Coin、障碍物Rock,我们分别来看他们的脚本:

[csharp] view
plain
copyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class CubeWay : MonoBehaviour {
  4. //在道路上显示的金币、障碍物
  5. public GameObject[] mObjects;
  6. void Start ()
  7. {
  8. //在每段路段上随机产生20到50个物品
  9. int mCount=Random.Range(20,50);
  10. for(int i=0;i<mCount;i++)
  11. {
  12. Instantiate(mObjects[0],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),1F,-2F),
  13. Quaternion.Euler(new Vector3(90F,180F,0F)));
  14. }
  15. //在每段路段上随机产生5到10个障碍物
  16. mCount=Random.Range(5,10);
  17. for(int i=0;i<mCount;i++)
  18. {
  19. Instantiate(mObjects[1],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),0.5F,-2F),
  20. Quaternion.Euler(new Vector3(90F,180F,0F)));
  21. }
  22. }
  23. //当离开摄像机视野时立即销毁
  24. void OnBecameInvisible()
  25. {
  26. Destroy(this.gameObject);
  27. }
  28. }

[csharp] view
plain
copyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Coin : MonoBehaviour {
  4. //这里是一个控制金币旋转的脚本
  5. void Update ()
  6. {
  7. transform.Rotate(Vector3.forward * 50F * Time.deltaTime);
  8. }
  9. //当离开摄像机视野时立即销毁
  10. void OnBecameInvisible()
  11. {
  12. Destroy(this.gameObject);
  13. }
  14. }

[csharp] view
plain
copyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class Rock : MonoBehaviour {
  4. //当离开摄像机视野时立即销毁
  5. void OnBecameInvisible()
  6. {
  7. Destroy(this.gameObject);
  8. }
  9. }

其中CubeWay就是一个Cube、Coin是一个圆柱体,为了让金币看起来好看点,我们让金币在空中旋转起来、Rock就是一个平面贴图。这里Rock、Coin将绑定到CubeWay的mObjects。

五、游戏管理

最后是界面的数据更新啦,脚本定义如下:

[csharp] view
plain
copyprint?

  1. using UnityEngine;
  2. using System.Collections;
  3. public class GameManager : MonoBehaviour {
  4. //游戏界面根节点
  5. private Transform GameUI;
  6. //玩家
  7. private Transform mPlayer;
  8. //界面金币数及距离
  9. private Transform mCoins;
  10. private Transform mLength;
  11. void Start ()
  12. {
  13. GameUI=GameObject.Find("2DUI").transform;
  14. mPlayer=GameObject.Find("People").transform;
  15. mCoins=GameUI.FindChild("Anchor/Panel/Coins").transform;
  16. mLength=GameUI.FindChild("Anchor/Panel/Length").transform;
  17. }
  18. void Update ()
  19. {
  20. mCoins.GetComponent<UILabel>().text="金币:" + mPlayer.GetComponent<Player>().CoinCount;
  21. mLength.GetComponent<UILabel>().text="距离:" + mPlayer.GetComponent<Player>().Length;
  22. }
  23. }

好了,到现在整个游戏已经讲解完了,相信大家已经迫不及待地想看看最终的效果了,好,我们一起来看看吧:

希望今天的内容大家能够喜欢,希望大家继续支持和关注我的博客,如果我们对今天的例子稍作修改,就可以实现3D版的跑酷,经典的《神庙逃亡》游戏就是基于Unity3D游戏引擎开发的。

时间: 2024-12-22 08:22:57

Unity3D游戏开发之跑酷游戏项目详解的相关文章

[Unity3D]Unity3D游戏开发之跑酷游戏项目解说

大家好,我是秦元培.我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客. 大家晚上好.我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei.终于到了更新博客的时间.从昨天下午開始,博主開始设计一个跑酷的游戏,到晚上睡觉前这个游戏已经基本完毕. 博主今天早上七点钟就起来了,到早上十点钟终于把整个游戏写完了. 所以,今天的博客的主题就是<Unity3D游戏开发之跑酷游戏项目解说>. 从博主自身来考虑这

Unity3D游戏开发之粒子系统实现详解

 今天为大家分享的是Unity3D中的粒子系统,粒子系统通常用来表现烟雾.云等高级效果,是一个十分注重制作技巧的部分,今天我们将以一个气泡的演示实例来一起学习如何在Unity3D中使用粒子系统.首先我们创建一个Unity3D项目,然后我们导入官方提供的粒子系统资源包,如下图: 接下来,我们创建一个粒子对象,如图所示: 接下来我们在属性面板中完成对粒子系统的设置,我们通过一张图来介绍这个属性面板: 接下来,我们单击Renderer,以设置该模块的Material属性,我们将官方提供的SoapB

Cocos2d-x手机游戏开发与项目实践详解_随书代码

Cocos2d-x手机游戏开发与项目实战详解_随书代码 作者:沈大海  由于原作者共享的资源为UTF-8字符编码,下载后解压在win下显示乱码或还出现文件不全问题,现完整整理,解决所有乱码问题,供大家下载. 下载地址:http://download.csdn.net/detail/oyangyufu/7665049 Cocos2d-x手机游戏开发与项目实践详解_随书代码

[Unity3D]Unity3D游戏开发之继续探索NGUI

大家好,我是秦元培.欢迎大家关注我的博客.我的博客地址是blog.csdn.net/qinyuanpei. 博主近期開始研究NGUI了,但是说实话,博主感觉NGUI的东西似乎有些分散,由于网上大部分的资料都仅仅是简单地解说怎样使用NGUI,并没有从实质性的原理出发来解说NGUI的内涵,这就和我们学习.NET仅仅会拖控件是一样的.并不能把握事物内在的东西.所以,博主推荐大家从官方提供的样例入手研究NGUI.博主这几天基本上都在看NGUI的演示样例程序,自我感觉内容比較杂吧.在今天的文章中,博主将讲

Unity3D游戏开发之详解 Animation类和Animator类

Unity3D游戏开发之详解 Animation类和Animator类 Animation类 animation组件用于播放动画.可以指定动画剪辑到动画组件并从脚本控制动画播放.在Unity的动画系统基于权重并且支持动画融合,叠加动画,动画混合,标签和完全控制动画播放的各个方面. 如果想播放一个简单的动画,可以使用Animation.Play:如果想在动画之间交叉淡入,可以使用Animation.CrossFade:如果想改变动画模式(循环,一次,乒乓),可以改变动画导入设置里面的动画帧的Wra

【Unity3D游戏开发】—— 太空大战打飞机游戏详解

大家好我是Kaven,今天给大家带来的是一个Unity3D的打飞机的小项目.俗话说"眼看千变,不如手过一边",学了差不多两星期Unity3D了,是时候找个小项目练练手了.于是就翻出了cocos2d-x的一个例子,模仿着写了一个飞机大战的游戏,虽然有一些功能没有实现,但总体上是完成了.闲话少说,下面开始吧. 由于这个用的是Unity3d自带的原生的2D插件native 2d,所以创建项目时左下角选择2d. 这个小游戏我分了三个场景,菜单场景,游戏场景,结束场景.由于菜单场景与结束场景都比

零基础unity3d游戏开发系列目录

零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(一) 零基础Unity3D游戏开发系列 第一章:游戏开发与游戏引擎(二) 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)界面... 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目I 零基础unity3d游戏开发系列 第二章:unity3d概览(一)创建与打开项目II 零基础Unity3D游戏开发系列 第二章:Unity3D概览(一)创建与打开项目III 零基础Unity3D游戏开发

Unity3D游戏开发之使用disunity提取Unity3D游戏资源

各位朋友,大家好,我是秦元培.今天博主想和分享的是使用disunity提取Unity3D游戏素材.这个工具呢,博主在Unity3D游戏开发之反编译AssetBundle提取游戏资源这篇文章中其实已经提到过了,不过因为有些朋友对如何使用这个工具依然存在问题,所以博主决定特地写一篇文章来讲解如何使用disunity来提取Unity3D游戏中的素材. 准备工作 disunity:负责对Unity3D的数据文件进行解包 Unity3D:负责将导出的数据文件显示出来 Bleander或者3DsMax:负责

[Unity3D]Unity3D游戏开发之异步记载场景并实现进度条读取效果

大家好,我是秦元培.欢迎大家关注我的博客,我的博客地址是:blog.csdn.net/qinyuanpei.终于在各种无语的论文作业中解脱了,所以立即抓紧时间来这里更新博客.博主本来计划在Unity3D游戏开发之从<魂斗罗>游戏说起(上)--目标追踪这篇文章后再写一篇<Unity3D游戏开发之从<魂斗罗>游戏说起(下)>,只是眼下博主的项目进度有些缓慢,所以想等项目稳定下来以后再和大家分享. 作为大家等待博主更新博客的回报,我们今天来说一说Unity3D中的游戏场景异步