这里介绍一下关于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里修改BG的sorting layer,这是决定了素材展示的层级,在这里我们添加一个background并且将它放在default层的上方,决定了最底层就是BG
三. Player预制体的设置
在这里我们将控制player,也就是挡板的移动
1. 我们将sprite里的player图片拖拽到Hierarchy下
2. 我们给player添加两个组件,Boxcollider2d和Rigiidbody2d两个组件
3. 将BoxCollider2D组件绿色的碰撞框缩放到和player一致
4. 将Rigidbody2D组件Gravcity Scale设置为0表示没有重力,并且在Constraints里勾选x和z表示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. 回到编辑器里,将脚本里的upkey和downkey设置为w和s
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复制两个命名为player1和player2
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. 首先,我们将player1和player2做成一个预制体,并且在脚本里改变他们的控制方法,这里我是将player的控制改成up arrow和downarrow
2. 将素材中的小球拖动到视图,给它添加一个circleCollider2D的碰撞器并且将大小调整和小球一样
3. 创建一个materials的文件夹并且生成一个叫做physical2d的材质,材质有两个属性,摩擦力和弹跳,这里把摩擦力设置成0,弹跳设置成1
4. 将材质添加给小球,给小球添加刚体组件,锁定让它不在z轴旋转,Mass设置成0.2表示质量方便弹跳,gravicity scale设置成0取消它的重力
5. 给player1和player2一个tag标签player表示我们碰撞的是什么物体
6. 然后我们编写一个脚本控制小球的弹跳,代码如下
代码解释:1.我们先定义一个刚体和碰撞器的随机变量方便调用
2.我们定义一个随机数控制小球往哪边走
3.rigidbody2D组件控制给小球的力,这里我们给100牛x轴的力
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两个,命名为score1和score2,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,2和rightwall,leftwall都添加上audioSource组件,并且给他们添加对应的音效click和hit,并且将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. 将三个图片分别附加给Image和button组件中的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后就可以看到你的游戏了,这里我也发布了游戏文件和相关资源,大家可以搜索乒乓球游戏进行下载