Unity3D游戏开发之仿仙剑奇侠传一2D游戏 (一)

今天要和大家分享的是基于Unity3D开发2D游戏,博主一直钟爱于国产武侠RPG,这个我在开始写Unity3D游戏开发系列文章的时候就已经说过了,所以我们今天要做的就是利用Unity3D来实现在2D游戏中人物的走动控制。下面就请大家跟随我的一起来见证Unity3D强大的魅力吧。首先我们创建一个项目,创建新场景,我们首先创建一个Plane并将其命名为MainMap,然后我们在项目中添加一个Resources文件夹,将事先准备好的地图文件Map0复制到这个目录下,然后我们将这个图片拖拽到MainMap上,我们将MainMap的旋转参数Rotatiion设置为90,180,0,使其与摄像机垂直,然后将摄像机的Projection投影属性设置为 orthographic正交模式,这时我们就能够在屏幕中看到经典的余杭镇场景了。如果我们需要对场景进行进一步的优化的话,可以通过调整摄像机的投影面积大小和距离来实现。参数设置可以参考这里:



接下来,我们再次创建一个Plane将其命名为Player,这就是我们今天要出场的角色李逍遥啦,和准备地图类似,我们将李逍遥的贴图直接拖拽到Player上。刚开始角色会比较大,和画面不协调,我们可以通过调整Scale参数来缩放我们的角色,调整到合适的范围。这里我们直接使用了一张完整的地图,在实际的游戏开发中,一个场景地图可能是由很多瓦片构成的,所谓瓦片,就是指被分割成若干个可以拼接起来的图片。我们知道,仙剑奇侠传作为一款经典的单机游戏,除了剧情以外,就是那些经典、动听的音乐啦,在Unity3D中实现音乐播放是很简单的事情,我们选定MainMap,为主场景添加一个AudioSource组件,并将背景音乐拖拽到AudioSource的AudioClip属性框中,选中Loop使其循环,接下来我们点击运行,运行效果如下图:


接下类,就是今天的重头戏啦,我们今天的主要任务是通过Unity3D的2D帧动画绘制来实现人物的动画和控制,所以接下来我们在项目目录下增加一个Script文件下,新建一个叫做Person的脚本,该脚本封装了我们对人物角色的控制和帧动画的绘制方法。首先我们来准备一组素材:





从名称的命名上,我们就可以看出这是角色在上下左右四个方向上的连续动画图片。下面,我们在Resources目录下创建下面的目录结构,并将上面的图片分别放在对应的文件夹下,我们在脚本中会引用下面的资源:


下面开始编写脚本:

using UnityEngine;
using System.Collections;

public class Person : MonoBehaviour {
	//定义角色对象
	private GameObject mHero;
	//定义人物向上动画数组
	private Object[] UpAnim;
	//定义人物向下动画数组
	private Object[] DownAnim;
	//定义人物向左动画数组
	private Object[] LeftAnim;
	//定义人物向右动画数组
	private Object[] RightAnim;
	//当前帧索引
	private int mFrameIndex;
	//当前时间
	private float mTotalTime;
	//定义每秒帧数为10
	private float mFPS=10;
	//定义当前人物动画
	private Object[] NowAnim;
	private Object[] LastAnim;
	//定义角色行动速度
	private float mSpeed=5;
	//角色当前状态
	private PersonState mState=PersonState.Stand;
	
	//定义角色状态枚举
	private enum PersonState
	{
	   Stand,
	   Walk
	}
	
	void OnGUI()
	{
	   GUI.Label(new Rect(10,10,180,40),"李逍遥位置:"+mHero.transform.position.ToString());
	}
	
	void Start () 
	{
	   //获取人物
	   mHero=GameObject.Find("Player");
	   //获取动画数组
	   UpAnim=Resources.LoadAll("UpAnim");
	   DownAnim=Resources.LoadAll("DownAnim");
	   LeftAnim=Resources.LoadAll("LeftAnim");
	   RightAnim=Resources.LoadAll("RightAnim");
	   //定义默认动画
	   NowAnim=UpAnim;
	   LastAnim=NowAnim;
	}
	
	void FixedUpdate()
	{
	   //向左
	   if(Input.GetKey(KeyCode.A))
	   {
	      SetAnimation(LeftAnim);
	      this.mState=PersonState.Walk;
	      mHero.transform.Translate(Vector3.right*Time.deltaTime*mSpeed);
	   }
	   //向右
	   if(Input.GetKey(KeyCode.D))
	   {
	      SetAnimation(RightAnim);
	      this.mState=PersonState.Walk;
	      mHero.transform.Translate(Vector3.right*Time.deltaTime*(-mSpeed));
	   }
	   //向上
	   if(Input.GetKey(KeyCode.W))
	   {
	      SetAnimation(UpAnim);
	      this.mState=PersonState.Walk;
	      mHero.transform.Translate(Vector3.forward*Time.deltaTime*(-mSpeed));
	   }
	   //向下
	   if(Input.GetKey(KeyCode.S))
	   {
	      SetAnimation(DownAnim);
	      this.mState=PersonState.Walk;
	      mHero.transform.Translate(Vector3.forward*Time.deltaTime*mSpeed);
	      Vector3 mHeroPos=mHero.transform.position;
	   }
	   DrawTexture(NowAnim);
	}
	
	void Update () 
	{
	   //松开键位时
	   if(Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D) 
	   || Input.GetKeyUp(KeyCode.S) || Input.GetKeyUp(KeyCode.W))
	   {
	      this.mState=PersonState.Stand;
	   }
	}
	
	void DrawTexture(Object[] mAnim)
	{
	   //如果角色当前状态为站立,则显示帧动画中的第一帧
	   if(mState==PersonState.Stand)
	   {
	     mHero.renderer.material.mainTexture=(Texture)mAnim[0];
	   }
	   //否则绘制帧动画
	   else
	   {
	      mTotalTime+=Time.deltaTime;
	      if(mTotalTime>=1.0/mFPS)
	      {
	         mFrameIndex++;
	         mTotalTime=0;
	         if(mFrameIndex>=mAnim.Length)
	         {
	           mFrameIndex=0;
	         }
	      }
	        mHero.renderer.material.mainTexture=(Texture)mAnim[mFrameIndex];
	   }
	}
	
	void SetAnimation(Object[] mAnim)
	{
	   NowAnim=mAnim;
	   if(!LastAnim.Equals(NowAnim))
	   {
	      this.mFrameIndex=0;
	      LastAnim=NowAnim;
	   }
	}
}

在上面的这部分脚本中,我们在Start()方法中加载了我们预先设定好的资源,然后在FixedUpdate()方法判断用户行为,并根据用户按下的键来确定要绘制的帧动画,我们假定每秒的帧数为10,则每帧显示的时间为0.1秒,如果从上一次刷新到现在的时间超过或者等于这个时间,则表示我们需要更新帧画面了。而当帧画面的索引和该帧动画数组内元素个数相等的时候,则意味着开始循环绘制这组帧动画。我们在上面定义了一个人物状态的枚举类型,这里只是简单的定义了两种类型,即Stand和Walk类型,当用户按下控制键时此类型的值为Walk,当用户松开控制键时此类型的值为Stand,和上一篇文章不同,这里调用的是FixedUpdate()方法,而不是Update()方法,原因是Update()f方法更新的时间我们无法控制,而FixedUpdate()方法的时间则可以通过Edit->Project Setting->time->Fixed Timestep来指定,具体的大家可以自己阅读代码,这里就不多说了,剩下的事情就是把脚本绑定到Player上,我们运行一下:



就目前这个解决方案而言,存在以下几个问题:

1、人物范围控制,换句话说就是如何保证人物不会从这些房屋、篱笆上直接穿过去

2、人物向下移动时,会钻到地底下

3、摄像机如何跟随人物实现平移

4、小地图的实现

5、场景地图范围控制

针对以上问题,伴随着博主学习Unity3D的深入,我们将在后面的文章中一一为大家解决,请大家关注我的博客,谢谢!


你可能感兴趣的:(Unity3D游戏开发之仿仙剑奇侠传一2D游戏 (一))