PonePal_unity游戏制作

           这里介绍一下关于PonePalGame,一个2d乒乓球游戏的制作方法

这里,我将讲解一下一个很简单的小游戏,PonePalGame,一个乒乓球小游戏的制作方法,这个游戏的制作方法是学习自siki老师的,如果大家想要看更多好的视频教程和游戏制作方法,可以去微信关注一下老师,这里我的话,更多的是做一个学习笔记,当然,也希望能帮忙推广一下老师。那么下面,就讲解一下游戏的制作方法,游戏exe文件和素材下载链接

http://download.csdn.net/download/qq_36574586/9896779

一.  新建项目

1.    首先我们新建一个叫做PonePal的一个项目,设置成为2d项目

2.    因为是2d游戏,所以场景会和3d有所不同,首先我们把布局调整成tall布局,并且将project的布局改成One column Layout,方便开发

3.    然后新建几个文件夹,分别保存游戏的预制体,音效,场景,脚本,贴图,这样我们项目开发的第一步,新建项目,也就算完成了。

二.  背景的添加

1.    我们要将BG的素材导入到sprites,并且将其拖拽到视图层

2.    这里注意的是因为我们发布游戏的平台屏幕宽度可能不一样,因此我们最好将摄像机和背景保持一定的间距,这里将摄像机大小保持成五就行了

3.    当然我们也可以背后背景的颜色修改和bg一样,点开camera里的Background,然后用取色器取到BG的颜色,这样可以保证略微超出屏幕后不是很影响美观

4.    这里我们为了防止经常操作游戏界面时候对于BG的误操作,可以在右上角的layer里给它添加一个标签,然后点开上方的layers进行锁住可以防止误操作

5.    我们还可以在Inspectors里修改BGsorting layer,这是决定了素材展示的层级,在这里我们添加一个background并且将它放在default层的上方,决定了最底层就是BG

 

 

三.  Player预制体的设置

在这里我们将控制player,也就是挡板的移动

1.    我们将sprite里的player图片拖拽到Hierarchy

2.    我们给player添加两个组件,Boxcollider2dRigiidbody2d两个组件

3.    BoxCollider2D组件绿色的碰撞框缩放到和player一致

4.    Rigidbody2D组件Gravcity Scale设置为0表示没有重力,并且在Constraints里勾选xz表示player只在y轴移动

5.    player下添加脚本来控制它的移动,代码如下

publicclassPlayerController :MonoBehaviour {

   //这里是控制上下键变量的声明

   publicKeyCode upkey;

   publicKeyCode downkey;

   publicfloat speed = 10;//设置移动速度

   privateRigidbody2D rigidbody2D;

   // Use this for initialization

   void Start () {

       //start方法里获取到刚体组件

       rigidbody2D = GetComponent<Rigidbody2D>();

       

   }

   

   // Update is called once per frame

   void Update () {

       if (Input.GetKey(upkey))

       {

           //这里是通过刚体组件velocity控制二维向量在(x,y)轴的移动,这里的移动是每帧调用的

           rigidbody2D.velocity =newVector2(0, speed);

 

       }elseif (Input.GetKey(downkey))

       {

           rigidbody2D.velocity =newVector2(0, -speed);

       }

       else

       {

           rigidbody2D.velocity =newVector2(0, 0);

       }

 

   }

}

6.  回到编辑器里,将脚本里的upkeydownkey设置为ws

7.    这样,运行项目,就可以在场景内控制player的移动了

四.  控制墙体的生成

为了防止player跑出屏幕边界,这里我们会设置四个透明墙来控制player的活动范围

1首先,我们生成一个空物体命名为GameMannager,来管理游戏物体,并且将其reset使其位置归0

2.GameMannager下生成四个游戏物体,分别命名为leftWall,rightWal,upWall,downWall

3.分别给它们添加一个BoxCollider2D的组件

4.然后我们在GameMannager下生成一个叫做GameMannager脚本来控制透明墙的位置和大小

5.代码如下

这里我们先定义四个墙体的私有变量,然后声明一个方法resestWall通过transform.find组件在方法里获取这四个变量,再调用camer.main.ScreenWorldPoint这个方法获取摄像机下四个墙体的位置坐标,这里就可以设置四个墙体的位置通过transform,position来设置它们的坐标,再用.size方法设置大小,这样,就可以实现4个墙体在该位置的摆放

publicclassGameMannager :MonoBehaviour {

 

   privateBoxCollider2D rightWall;

   privateBoxCollider2D leftWall;

   privateBoxCollider2D upWall;

   privateBoxCollider2D downWall;

 

 

   // Use this for initialization

   void Start () {

       resetwall();

   }

   

   // Update is called once per frame

   void Update () {

       

   }

 

   publicvoid resetwall()

   {

       //在这个方法里,我们将通过代码来控制墙体的位置

       rightWall = transform.Find("rightWall").GetComponent<BoxCollider2D>();

       leftWall = transform.Find("leftWall").GetComponent<BoxCollider2D>();

       upWall = transform.Find("upWall").GetComponent<BoxCollider2D>();

       downWall = transform.Find("downWall").GetComponent<BoxCollider2D>();

 

       //在这里,我们要设置墙体位置在摄像机的视野四条边,因此设置上方墙坐标为(1/2x,y)

       //Vector3 wallPosition = Camera.main.ScreenToWorldPoint(newVector2(Screen.width / 2, Screen.height))+new Vector3(0,0.5f,0);

       //upWall.transform.position = wallPosition;

       //float width = Camera.main.ScreenToWorldPoint(newVector2(Screen.width, Screen.height)).x * 2;

       //upWall.size = new Vector2(width, 1);

 

      

 

       Vector3 tempPosition=Camera.main.ScreenToWorldPoint(newVector2(Screen.width,Screen.height));

       upWall.transform.position =newVector3(0, tempPosition.y +0.5f, 0);

       upWall.size =newVector2(tempPosition.x * 2, 1);

 

       

       downWall.transform.position =newVector3(0, -tempPosition.y- 0.5f, 0);

       downWall.size =newVector2(tempPosition.x * 2,1);

 

     

       rightWall.transform.position =newVector3(tempPosition.x+0.5f,0,0);

       rightWall.size =newVector2(1,tempPosition.y*2);

 

       

       leftWall.transform.position =newVector3(-tempPosition.x-0.5f,0, 0);

       leftWall.size =newVector2(1,tempPosition.y*2);

 

 

   }

 

 

}

五.player位置的控制

这里我们设计的是一个对战游戏,所以我们需要两个游戏物体,而为了能保持它们左右对称并且在不同平台都自适应,我们应该进行如下操作

1.    player ctrl+d复制两个命名为player1player2

2.    在脚本gameMannager进行如下操作

3.    这样我们就成功设置了两个物体坐标并且成功对屏幕自适应

1)声明两个变量用来获取

 publicTransform player1;

publicTransform player2;

2)定义这样一个方法,通过照相机获取世界坐标,设置两个物体都在屏幕的100像素间距,这里这么设置是因为如果直接x,y变量,那么z轴坐标因为和camera保持一致而变成-10,因此我们要手动设置z轴坐标

publicvoid restPlayer()

   {

 

       Vector3 player1position =Camera.main.ScreenToWorldPoint(newVector3(100,Screen.height/2,0));

       player1position.z = 0;

       player1.position = player1position;

       Vector3 player2position=Camera.main.ScreenToWorldPoint(newVector3(Screen.width-100,Screen.height/2,0));

       player2position.z = 0;

       player2.position = player2position;

六。生成小球并且控制小球的弹跳

 

 

 

这里我们将讲述怎么添加一个小球,让它可以来回弹跳

1.  首先,我们将player1player2做成一个预制体,并且在脚本里改变他们的控制方法,这里我是将player的控制改成up arrowdownarrow

2.  将素材中的小球拖动到视图,给它添加一个circleCollider2D的碰撞器并且将大小调整和小球一样

3.  创建一个materials的文件夹并且生成一个叫做physical2d的材质,材质有两个属性,摩擦力和弹跳,这里把摩擦力设置成0,弹跳设置成1 

4.  将材质添加给小球,给小球添加刚体组件,锁定让它不在z轴旋转,Mass设置成0.2表示质量方便弹跳,gravicity scale设置成0取消它的重力

5.  player1player2一个tag标签player表示我们碰撞的是什么物体

6.  然后我们编写一个脚本控制小球的弹跳,代码如下

代码解释:1.我们先定义一个刚体和碰撞器的随机变量方便调用

         2.我们定义一个随机数控制小球往哪边走

       3.rigidbody2D组件控制给小球的力,这里我们给100x轴的力

      4.然后为了保证碰撞到不同的位置速度不同我们给出一个OnCollisionEnter的方法

 通过获取player的速度,然后附加给小球,这样就控制了小球的移动不会一直平行移动,并且当两边不移动时,速度逐渐变0,这里为了保证速度不会无限累加,我们每次将速度设置为一半.

7.这样我们就可以控制小球在两个板子中间正常弹跳了

 

 publicclassBall :MonoBehaviour {

 

   privateRigidbody2D rigidbody2d;

   privateCircleCollider2D circleCollider2d;

  

 

 

   void Start () {

       rigidbody2d = GetComponent<Rigidbody2D>();

       circleCollider2d = GetComponent<CircleCollider2D>();

       

       int number =Random.Range(0, 2);

       if (number == 1)

       {

           rigidbody2d.AddForce(newVector2(100, 0));

 

 

       }

       else

       {

           rigidbody2d.AddForce(newVector2(-100, 0));

 

       }

   }

   

   void Update () {

       

   }

   void OnCollisionEnter2D(Collision2D col)

   {

       //通过这个方法来改变碰撞后的速度

       if (col.collider.tag =="player")

       {

           Vector2 velocity = rigidbody2d.velocity;

           velocity.y = velocity.y / 2 +col.rigidbody.velocity.y/2;

           rigidbody2d.velocity = velocity;

 

       }

 

 

 

 

   }

}

七.控制分数的UI

在这一节,我们将讲述如何控制两边得分情况

1.    我们右键生成UI_Text两个,命名为score1score2,f分别把他们放在画布顶部并且锚点设置为顶部,字体为白色,字体大小的话设置成自己喜欢的就可以。

2.    然后代码按照如下操作

3.    z这样我们就实现了UI控制分数生成

首先,我们将GameMannager改成单例模式,用awake方法初始化,这样我们就可以在别的方法里调用这个脚本里的方法

4.     privatestaticGameMannager _instance;

5.      publicstaticGameMannager Instance

6.      {

7.   

8.          get

9.          {

10.            return _instance;

11.        }

12.     }

 void Awake()

   {

       _instance =this;

       

 

13.     }

14. 然后我们定义一个方法叫做ChangeScore,这里获取的是小球传过来的碰到墙体的参数,当然在这之前我们需要定义下面这些变量,然后在changeScore方法里判断小球传过来的参数,来对分数进行加减,再对获得的数值转换成字符串赋值给text组件

15. 

Using unityEngine.UI

   privateint score1;

   privateint score2;

   publicText score1text;

   publicText score2text;

  publicvoid ChangeScore(string name)

   {

       if (name =="leftWall")

       {

           score1++;

       }

       elseif (name =="rightWall")

       {

           score2++;

       }

       score1text.text = score1.ToString();

       score2text.text = score2.ToString();

 

16.     }

当然,我们在ball脚本下写一个方法判断小球碰到的是左边的墙还是右边的墙,然后传递参数给GameMannager中的方法

17.void OnCollisionEnter2D(Collision2D col)

18.    {

19.        //通过这个方法来改变碰撞后的速度

20.        if (col.collider.tag == "player")

21.        {

22.            Vector2 velocity = rigidbody2d.velocity;

23.            velocity.y = velocity.y / 2 +col.rigidbody.velocity.y/2;

24.            rigidbody2d.velocity = velocity;

25. 

26.        }

27.        if (col.gameObject.name == "rightWall" || col.gameObject.name == "leftWall")

28.        {

29.            //当我们将GameMannager改成单例模式后,我们就可以再ball里访问它的方法

30.            GameMannager.Instance.ChangeScore(col.gameObject.name);

31. 

32.            

33.        }

34.    }

35. }

.控制音效的添加

1.我们将素材里的audio拖进我们的audio文件夹中

2.我们通过控制和player的碰撞和墙体的碰撞实现音乐的播放,首先我们给player1,2rightwall,leftwall都添加上audioSource组件,并且给他们添加对应的音效clickhit,并且将playOnAwake取消掉

3.然后给他们添加以下代码

这两者同理都是通过audio组件的调用和内置play方法进行播放的,audio,pitch则是控制声音播放速度,然后背景音乐则直接在GameMannager中添加audioSorce组件并且将音乐文件拖拽即可,当然记得勾选上循环和playOnAwake,这样音乐的添加也就算完成了

 publicAudioSource audio;

 

voidOnCollisionEnter2D()

   {

       audio.pitch =Random.Range(0.8f, 1.2f);

       audio.Play();

 

 

 

}

publicAudioSource audio;

 void OnCollisionEnter2D (){

 

       audio.Play();

 

 

   }

.关于重置按钮的制作

当我们想要重新开始一局游戏时候,可以按下重置按钮进行重置分数和球的位置,为了这样,我们有如下操作

1.  button的素材导入sprite

2.  引入UI组件button

3.  将三个图片分别附加给Imagebutton组件中的HighLight组件和Pressed组件

4.  button位置放置好,可以通过按住alt进行等比例缩放

5.  按照如下代码进行控制

6.  然后在button组件上添加GameMannager游戏组件,并且选择Reset方法,这样点击后就可以重置了

首先是GameMannager下写一个Reset方法

7.  publicvoid Reset()

8.      {

9.          score1 = 0;

10.        score2 = 0;

11.        score1text.text = score1.ToString();

12.        score2text.text = score2.ToString();

13.        GameObject.Find("Ball").SendMessage("Reset");

14. 

15.     }

然后在ball脚本

publicvoid Reset()

   {

       transform.position = Vector3.zero;

       GoBall();

 

}

void GoBall()

   {

       int number =Random.Range(0, 2);

       if (number == 1)

       {

           rigidbody2d.AddForce(newVector2(100, 0));

 

 

       }

       else

       {

           rigidbody2d.AddForce(newVector2(-100, 0));

 

       }

 

 

   }

void Start () {

       rigidbody2d = GetComponent<Rigidbody2D>();

       GoBall();

 }

 

.发布版本

啊,这里直接点击build and setting即可发布自己想要发布的平台,这里你可以创建,然后更改设置,这里不赘述了,记得把场景拖过去,build后就可以看到你的游戏了,这里我也发布了游戏文件和相关资源,大家可以搜索乒乓球游戏进行下载

猜你喜欢

转载自blog.csdn.net/qq_36574586/article/details/75039660
今日推荐