[Unity3D]Unity3D游戏开发之跑酷游戏项目解说
大家好,我是秦元培。我參加了CSDN2014博客之星的评选,欢迎大家为我投票,同一时候希望在新的一年里大家能继续支持我的博客。
大家晚上好。我是秦元培,欢迎大家关注我的博客,我的博客地址是blog.csdn.net/qinyuanpei。终于到了更新博客的时间。从昨天下午開始,博主開始设计一个跑酷的游戏,到晚上睡觉前这个游戏已经基本完毕。
博主今天早上七点钟就起来了,到早上十点钟终于把整个游戏写完了。
所以,今天的博客的主题就是《Unity3D游戏开发之跑酷游戏项目解说》。
从博主自身来考虑这件事情。当你选择做自己热爱的事情的时候。你的内心一定是充满激情和勇气的。你愿意看到自己的努力。你愿意看到自己的付出,我们成长是为了促进自我对认知的不断完好,所以我们应该以一种虔诚、谦恭的态度来对待我们的生命。我们也许无法选择出身,但我们能够选择向自己喜欢的生活去努力。
也许我和这些人真的不是一个世界的人吧。非常多事情在今天都给出了结局,对于这样的人我已经没有再尝试与之交流的想法了,也许大学四年平平淡淡,留给我的仅仅有自己才干体会的孤独吧。
好了。不说我的事情了,我们正式開始今天的内容吧!
一、游戏策划
游戏採用2D界面,角色从左到右奔跑。在路段中随机生成障碍物和金币,玩家须要使用跳跃功能躲开障碍物。在游戏中玩家收集的金币数目越多,奔跑的距离越长,玩家的得分就越高。
我们终于实现的界面效果如图所看到的,首先我们来讲一下游戏的原理,我们这里这里採用的方法是路段固定,移动摄像机的方法。换句话说,当角色開始移动后,摄像机和场景尾随角色缓缓向右移动。
当角色跑完每个路段距离的2/3时。计算下一路段的位置,并在该位置生成一个新的路段,这样在游戏场景中能够产生无限远的路段,当某一路段离开摄像机视野时,马上将其销毁。于此同一时候,我们在每个路段上随机产生障碍物和金币。然后对角色做碰撞检測就可以。
二、角色控制
角色控制这里,我们仅仅关注角色的状态,即角色是处于奔跑状态还是死亡状态。通过这一状态,我们针对角色採取不同的处理方式。假设角色处于奔跑状态,则更新角色位置、摄像机位置、背景位置,否则角色将在被障碍物撞到以后倒地死亡。
我们来一起看以下的脚本:
using UnityEngine;
using System.Collections; public class Player : MonoBehaviour { //定义角色移动速度
public float mMoveSpeed=2.5F; //摄像机
private Transform mCamera;
//背景图片
private Transform mBackground; //角色是否在奔跑
private bool isRuning=true;
//场景中路段总数目
private int mCount=1; //路段预设
public GameObject CubeWay; //死亡动画播放次数
private int DeathCount=0; //收集的金币数目
private int mCoinCount=0;
public int CoinCount {
get {
return mCoinCount;
}
} //当前奔跑距离
private int mLength=0;
public int Length {
get {
return mLength;
}
} //当前得分
private int mGrade=0;
public int Grade {
get {
return mGrade;
}
} void Start ()
{
//获取相机
mCamera=Camera.main.transform;
//获取背景
mBackground=GameObject.Find("Background").transform;
} void Update ()
{
//假设角色处于奔跑状态则移动角色、相机和场景
if(isRuning)
{
Move();
CreateCubeWay();
Jump();
UpdateData();
}else
{
Death();
}
} /// <summary>
/// 更新玩家的游戏数据
/// </summary>
private void UpdateData()
{
//计算奔跑距离
mLength=(int)((transform.position.x+25)*25);
//计算玩家得分
mGrade=(int)(mLength*0.8+mCoinCount*0.2);
} ///角色死亡
private void Death()
{
//为避免死亡动画在每一帧都更新,使用DeathCount限制其运行
if(DeathCount<=1)
{
//播放死亡动画
transform.animation.Play("Lose");
//次数+1
DeathCount+=1;
//保存当前记录
//PlayerPrefs.SetInt("这里填入一个唯一的值",Grade);
}
} private void Jump()
{
//这里不能使用刚体结构,所以使用手动方法实现跳跃
if(Input.GetKeyDown(KeyCode.Space) || Input.GetMouseButton(0))
{
while(transform.position.y<=1)
{
float y=transform.position.y+0.02F;
transform.position=new Vector3(transform.position.x,y,transform.position.z);
transform.animation.Play("Jump");
}
StartCoroutine("Wait");
}
} IEnumerator Wait()
{
yield return new WaitForSeconds(0.8F);
//角色落地继续奔跑
while(transform.position.y>0.125F)
{
float y=transform.position.y-0.02F;
transform.position=new Vector3(transform.position.x,y,transform.position.z);
transform.animation.Play("Run");
}
} //移动角色、相机和场景
private void Move()
{
//让角色从左到右開始奔跑
transform.Translate(Vector3.forward * mMoveSpeed * Time.deltaTime);
//移动摄像机
mCamera.Translate(Vector3.right * mMoveSpeed * Time.deltaTime);
//移动背景
mBackground.Translate(Vector3.left * mMoveSpeed * Time.deltaTime);
} //创建新的路段
private void CreateCubeWay()
{
//当角色跑完一个路段的的2/3时,创建新的路段
//用角色跑过的总距离计算前面n-1个路段的距离即为在第n个路段上跑过的距离
if(transform.position.x+30-(mCount-1)*50 >=50*2/3)
{
//克隆路段
//这里从第一个路段的位置開始计算新路段的距离
GameObject mObject=(GameObject)Instantiate(CubeWay,new Vector3(-5F+mCount * 50F,0F,-2F),Quaternion.identity);
mObject.transform.localScale=new Vector3(50F,0.25F,1F);
//路段数加1
mCount+=1;
}
} void OnTriggerEnter(Collider mCollider)
{
//假设碰到的是金币,则金币消失,金币数目加1;
if(mCollider.gameObject.tag=="Coin")
{
Destroy(mCollider.gameObject);
mCoinCount+=1;
}
//假设碰到的是障碍物,则游戏结束
else if(mCollider.gameObject.tag=="Rock")
{
isRuning=false;
}
}
}
在这里我们须要关注以下的内容:
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,我们分别来看他们的脚本:
using UnityEngine;
using System.Collections; public class CubeWay : MonoBehaviour { //在道路上显示的金币、障碍物
public GameObject[] mObjects; void Start ()
{ //在每段路段上随机产生20到50个物品
int mCount=Random.Range(20,50);
for(int i=0;i<mCount;i++)
{
Instantiate(mObjects[0],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),1F,-2F),
Quaternion.Euler(new Vector3(90F,180F,0F)));
}
//在每段路段上随机产生5到10个障碍物
mCount=Random.Range(5,10);
for(int i=0;i<mCount;i++)
{
Instantiate(mObjects[1],new Vector3(Random.Range(this.transform.position.x-25,this.transform.position.x+25),0.5F,-2F),
Quaternion.Euler(new Vector3(90F,180F,0F)));
}
} //当离开摄像机视野时马上销毁
void OnBecameInvisible()
{
Destroy(this.gameObject);
} }
using UnityEngine;
using System.Collections; public class Coin : MonoBehaviour { //这里是一个控制金币旋转的脚本 void Update ()
{
transform.Rotate(Vector3.forward * 50F * Time.deltaTime);
} //当离开摄像机视野时马上销毁
void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}
using UnityEngine;
using System.Collections; public class Rock : MonoBehaviour { //当离开摄像机视野时马上销毁
void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}
当中CubeWay就是一个Cube、Coin是一个圆柱体,为了让金币看起来好看点,我们让金币在空中旋转起来、Rock就是一个平面贴图。
这里Rock、Coin将绑定到CubeWay的mObjects。
五、游戏管理
最后是界面的数据更新啦,脚本定义例如以下:
using UnityEngine;
using System.Collections; public class GameManager : MonoBehaviour { //游戏界面根节点
private Transform GameUI;
//玩家
private Transform mPlayer;
//界面金币数及距离
private Transform mCoins;
private Transform mLength; void Start ()
{
GameUI=GameObject.Find("2DUI").transform;
mPlayer=GameObject.Find("People").transform;
mCoins=GameUI.FindChild("Anchor/Panel/Coins").transform;
mLength=GameUI.FindChild("Anchor/Panel/Length").transform;
} void Update ()
{
mCoins.GetComponent<UILabel>().text="金币:" + mPlayer.GetComponent<Player>().CoinCount;
mLength.GetComponent<UILabel>().text="距离:" + mPlayer.GetComponent<Player>().Length;
}
}
好了,到如今整个游戏已经解说完了,相信大家已经迫不及待地想看看终于的效果了。好。我们一起来看看吧:
希望今天的内容大家能够喜欢,希望大家继续支持和关注我的博客,假设我们对今天的样例稍作改动,就能够实现3D版的跑酷,经典的《神庙逃亡》游戏就是基于Unity3D游戏引擎开发的。
每日箴言:要有美好的希望,并全力以赴去追求;要有远大的梦想,并全力以赴去实现。
喜欢我的博客请记住我的名字:秦元培,我的博客地址是blog.csdn.net/qinyuanpei
转载请注明出处,本文作者:秦元培,本文出处:http://blog.csdn.net/qinyuanpei/article/details/25510579
[Unity3D]Unity3D游戏开发之跑酷游戏项目解说的更多相关文章
- 关于《Unity3D/2D游戏开发从0到1》书籍再版说明
关于<Unity3D/2D游戏开发从0到1>第一版本在2015年7月1日全国发行,累计得到不少国内高校教师.培训机构的好评.但是由于Unity官方对于技术不断的升级与版本的快速迭代,基于U ...
- 《Unity3D/2D游戏开发从0到1(第二版本)》 书稿完结总结
前几天,个人著作<Unity3D/2D游戏开发从0到1(第二版)>经过七八个月的技术准备以及近3个月的日夜编写,在十一长假后终于完稿.今天抽出一点时间来,给广大热心小伙伴们汇报一下书籍概况 ...
- 《Unity3D/2D游戏开发从0到1》正式出版发行
<Unity3D/2D游戏开发从0到1>正式出版发行 去年个人编写的Unity书籍正式在2015年7月正式发行,现在补充介绍一下个人著作.书籍信息: 书籍的名称: <Uni ...
- Unity3D手机游戏开发
<Unity3D手机游戏开发> 基本信息 作者: 金玺曾 出版社:清华大学出版社 ISBN:9787302325550 上架时间:2013-8-7 出版日期:2013 年8月 开本:16开 ...
- Unity3D 入门 游戏开发 Unity3D portal game development
Unity3D 入门 游戏开发 Unity3D portal game development 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq.com ...
- Unity3D独立游戏开发日记(二):摆放建筑物
在沙盒游戏里,能自由建造是很重要的特点,比如说风靡全球的<我的世界>,用一个个方块就能搭建出规模宏大的世界.甚至有偏激的人说,没有自由建造,就不是一个真正的沙盒游戏.的确,沙盒游戏的魅力有 ...
- Unity3D独立游戏开发日记(一):动态生成树木
目前写的独立游戏是一个沙盒类型的游戏.游戏DEMO视频如下: 提到沙盒类型的游戏,就有人给出了这样的定义: 游戏世界离现实世界越近,自由度.随机度越高才叫沙盒游戏.所谓自由度,就是你在游戏里想干啥就干 ...
- Unity3D小游戏开发之两个我踩过的坑
最近在开发一个植物大战僵尸小游戏,今天写了一早上的代码,踩了两个坑,这两个坑的位置分别位于触发器和数据转换,写这篇博文以此来让其他程序员不要再去踩这两个坑. 1.我在做简易僵尸模型的时候,这个僵尸模型 ...
- Photon + Unity3D 在线游戏开发 学习笔记(两)
本文和大家 和大家说说 Photon 解压后的目录结构 这里面最基本的我们 以后开发要用到的目录 就是 deploy目录,这个目录里 放的是要挂载的 server 当然我们的 server端也要放在 ...
随机推荐
- 转:Ogre源代码浅析——脚本及其解析(一)
Ogre的许多外部资源数据都有着相应的脚本格式,现例举如下: Material(材质):Ogre使用的是“大材质”的概念.狭义的“材质”概念往往是与“贴图”等概念区分开的,比如在Lambert光照模型 ...
- how to Use the Tampermonkey API from the Chrome console
1.Create the following script: // ==UserScript== // @name Exports some GM functions // @namespace Wh ...
- (原)linux下caffe模型转tensorflow模型
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/7419352.html 参考网址: https://github.com/ethereon/caffe- ...
- rox + openbox + fbpanel + conky打造又快又稳的桌面
从开始用 Gentoo 以来,就没有打算用 gnome . KDE 这些巨无霸级别的 DE ,最后选择了相对来来说比较轻量级的 Xfce4 ,不过最近更是变本加厉,连 Xfce4 都觉得太大.于是,下 ...
- mysql--SQL编程(关于mysql中的日期,实例,判断生日是否为闰年) 学习笔记2.1
关于日期处理的实例: 从mysql给出的 example 这个是官方源码下载以及导入,http://dev.mysql.com/doc/employee/en/employees-installati ...
- [转]2016年linux运维人员必会开源运维工具体系
linux运维人员必会开源运维工具体系 说明:不同的技术人员,不同的阶段确定知识边界非常重要,否则,就像马拉车,不知道终点在哪,累死也达不到目标.例如拿8K要学多少,拿15K要学多少.一个新手也许只想 ...
- FireFox 浏览器插件/扩展开发学习
2014-11-08 内容存档在evernote,笔记名"FireFox 浏览器插件/扩展开发学习"
- 树莓派进阶之路 (003) - Raspberry Pi(树莓派)国内软件源
树莓派自带的软件源是 deb http://mirrordirector.raspbian.org/raspbian/ wheezy main contrib non-free rpi 由于网站在国外 ...
- 终极 Shell
在开始今天的 MacTalk 之前,先问两个问题吧: 1.相对于其他系统,Mac 的主要优势是什么?2.你们平时用哪种 Shell?…… 第一个童靴可以坐下了,Mac 的最大优势是 GUI 和命令行的 ...
- 对于“Newtonsoft.Json”已拥有为“NETStander.Library”定义的依赖项,解决办法
问题描述: 在使用visual studio中的NuGet包管理下载程序时,有时会出现-对于“Newtonsoft.Json”已拥有为“NETStander.Library”定义的依赖项,这样的错误. ...