Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

时间:2023-02-07 16:38:12

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

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

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

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

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

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

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

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

         下面开始编写脚本:

 

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上,我们运行一下:

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

Unity3D游戏开发之使用Unity3D开发2D游戏 (一)

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

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

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

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

         4、小地图的实现

          5、场景地图范围控制

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