zoukankan      html  css  js  c++  java
  • [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

      源代码下载

       

      


    
  • 相关阅读:
    Moya 浅析
    Swift: Alamofire -> http请求 & ObjectMapper -> 解析JSON
    ReactiveCocoa 用法实例
    RACSignal的Subscription深入
    idea 不能编译生成class文件
    idea 右下角不显示git分支
    SSO单点登录的研究
    JVM内存模型简介
    Spring事务处理
    RabbitMQ
  • 原文地址:https://www.cnblogs.com/jhcelue/p/6727079.html
Copyright © 2011-2022 走看看