小游戏 SpeedDown 开发笔记(学习bilibili@[M"/>
基于Unity的2D小游戏 SpeedDown 开发笔记(学习bilibili@[M
基于Unity的2D小游戏 SpeedDown 开发笔记(学习bilibili@M_Studio的教学视频)
主要内容:在Sunnyland游戏的设计基础上,新增了物理组件Joint系列、DrawGizmos辅助设计工具、LineRenderer线渲染器组件的使用、随机生成prefabs、计时器等功能。
一、场景搭建
1、项目创建与素材导入
创建一个2 D项目,在Asset Store中搜索导入Pixel Adventure 1素材包(It’s Free)。
2、开发平台选择与屏幕分辨率调整
在File -> building setting 选择开发平台;
在Hierarchy窗口新建一个3 D项目->Quad,在Quad->Scale中更改x、y,更改背景的比例(参考值10:9),同时更改Main Camera的size(参考值为8),使得摄像机能够完整显示Quad,调整相机位置.z为负值,使得游戏画面能够正常显示
3、背景(QUAD)设置
在Assets文件夹中Create材质Material,命名为BackGround,将BackGround的Shader更改为Unlit->Texture(即仅仅作为一个图像)
更改素材BackGround文件图片中的Pixels Per Unit设置为素材本身的像素(此处为64),调整Wrap Mode为repeat,调整材质的Tiling,这样背景图片能够根据设置的铺设贴图行列数组成背景图,如图所示。通过改变offset(偏移)来实现视觉上的移动效果。
创建脚本实现背景的移动动画效果:
获得Material材质球,注意Quad中没有Material,GetComponent通过获得Renderer.material 来得到对象。
设置一个speed,在update方法基于speed参数,改变材质的Offset,代码如下所示。
public class Animationbg : MonoBehaviour
{Material material;Vector2 movement;public Vector2 speed;void Start(){material = GetComponent<Renderer>().material; //注意不是GetComponent<Material>}// Update is called once per framevoid Update(){movement += speed * Time.deltaTime; //*deltaTime等价于*0.02,使得图片变化更顺畅material.mainTextureOffset = movement;}
}
通过在unity中设置speed值,调整背景图横向、纵向移动速度。
4、SPIKES(尖刺)布置
Spikes素材的整理:找到素材Traps->Spikes->Idle,InputSettings -> Pixel Per Unit更改为16,Fliter mode设置为Point(对于像素资源来说,Point可以让贴图显示得更清楚,具体解释见Unity 纹理资源简介(5.3.7))
Create Empty,命名为TopSpikes,将贴图拖入项目,调整尖刺的方向和大小,Ctrl+D创建多个,铺满背景图上端。(Tips:选中Spike,按住V键,即可自动选择边界点,自动贴合,避免手动调整产生误差)
添加collider(碰撞体),让玩家产生碰撞效果,起到一个trigger作用,角色触碰触发死亡:
为Spikes添加组件Polygon Collider 2D(多边形碰撞体),打开Used By Composite(作为整合体的一部分);
添加组件Composite Collider 2D(合成碰撞体),在自动添加的rigidbody中,设置BodyType为Static(静态),固定rigidbody,再将Collider位置调整到一个合适的位置。
二、Platforms制作
1、基础平台BASICPLANTFORM制作
素材位置:Traps->Falling Plantforms。
Pixels Per Unit = 16,直接拖入Hierarchy中,命名为BasicPlantform。
添加动画效果:(新建文件夹Assets->Animation->Plantforms->BasicPlantform,养成整理各类型文件的好习惯)选中gameobject,在Animation窗口创建动画,选中所有BasicPlantforms动画素材,拖入Animation窗口当中,调整采样频率Samples = 10(2019版在Animation窗口右侧点击齿轮图标,选择show sample rate)。
为了使palyer可以在平台上站立,为平台添加Box Collider 2D,Edit 其大小。
2、旋转平台ROTATEPLANTFORM制作
素材位置:Traps->Plantforms。
Pixels Per Unit = 16,直接拖入Hierarchy中,命名为Rotate Plantform。
新组件:Joint系列组件
添加Hinge Joint 2D 组件(类似机械原理中的铰链),会自动添加rigid body 2D,修改Motor -> Maximum Motor Force(最大转矩) = 100(可根据需要调整)。
3、弹跳平台FANPLANTFORM制作
素材位置:Traps->Fan
Pixels Per Unit = 16,直接拖入Hierarchy中,命名为Fan Plantform。
动画逻辑:player踩在平台上,平台开始旋转,并将玩家弹起一定高度。这就需要有两个动画,一个idle状态(只有素材的第一帧),一个run状态(将素材全部拖进Animation)。
脚本实现:首先GetComponent< Animator >组件。利用OnCollisionEnter2D判断碰撞,需要判断碰撞的collision的tag == “Player”(需要在unity中添加Player的tag),直接Play动画名。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class FanPlantform : MonoBehaviour
{Animator animator;// Start is called before the first frame updatevoid Start(){animator = GetComponent<Animator>();}private void OnCollisionEnter2D(Collision2D collision){if (collision.gameObject.CompareTag("Player")){animator.Play("Fan_run");}}
}
4、摆动链球SPIKEDBALL制作
素材位置:Traps->Spiked Ball
Pixels Per Unit = 16,新建SpikedBall空项目,将Chain 和 Spike Ball拖入项目。
为实现球绕链顶点旋转,可以采用多种方法,比如复制多个Chain,利用Hinge joint组件创建铰链来实现;或者利用Distance Joint 2D组件来实现:
选择SpikedBall,添加Distance Joint 2D组件,为Chain添加Rigidbody,设置Body Type为Kinematic(或者为static),即将Chain固定在设定的位置上。选择SpikedBall,将Chain拖到Connected Rigidbody上。
为SpikedBall添加一个Circle Collider 2D ,调整圆的大小和位置,勾选isTrigger,作为一个碰撞体。
Line Renderer组件(线渲染器),绘制Ball和Chain之间的连线。修改材质为Default-Line,编写脚本获取Chain和Ball的两个点位置作为线的起点和终点。
为Spiked Ball添加脚本,通过SetPoint(int index,Vector3 position)方法,注意要一个index一个地添加。
设计结果如图所示:
5、平台的运动
Create new C#Scripts,named Plantform.
由于平台的Position都是3维的,所以Vector3 movement,写一个MovePlatform()方法,transform.position += movement * Time.deltaTime,在Start方法中movement.y = speed(先全局public speed,方便在Unity中调试);
平台销毁:需要创建一个EmptyObject,命名为TopLine,设置在想要销毁平台的位置,在脚本中调用它的TopLine.transform.position.y,当平台运动到平台.position.y > TopLine.transform.position.y时,Destry(平台)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Plantform : MonoBehaviour
{Vector3 movement;public float speed;GameObject topLine;void Start(){movement.y = speed;topLine = GameObject.Find("TopLine");}// Update is called once per framevoid Update(){MovePlantform();}void MovePlantform(){transform.position += movement * Time.deltaTime;if(transform.position.y >= topLine.transform.position.y){Destroy(gameObject);}}}
6、设置好平台之后,将其保存为Prefab,便于后面平台生成时调用与调试
三、Player制作
1、动画制作与切换
素材位置:Main Character -> Virtual Guy
Pixels Per Unit = 32,拖拽Idle第一帧动画到Hierarchy中,命名为Player
添加动画idle、run、fall、hit(dead),推荐采样频率为20-50。利用float speed,bool isOnGround,trigger hit来实现动画的切换。
添加Rigidbody,Constraints -> Freeze Rotation z,避免player绕z轴翻转
添加 Box Collider 2D,Edit box的大小和位置
添加脚本PlayerController,其中角色的移动、动画切换等与SunnyLand教程
中的操作基本一致。需要注意的是Fanplatform的设定,让角色触碰到fanplatform时弹起,通过对FanPlatform添加tag,利用**collision.gameObject.CompareTag()**方法来实现。
为所有平台添加Layer:Plantform
Tips:利用Gizmos(线框),让范围检测可视化,便于调试
Gizmos.DrawWireSphere(groundCheck.transform.position,checkRadius);
注意下图中的蓝色circle即为绘制的检测范围
2、角色死亡(或者HIT)-> GAME OVER
死亡判断:Player碰撞到tag为Spike的物体。
实现:在hit(dead)动画最后一帧添加Envent Dead()。
3、PLAYER设置完成后保存为Prefab
四、随机生成平台
在屏幕下方某处生成平台,同时作为角色死亡的判定位置。
创建Empty,reset并调整位置,添加BoxCollider2D,勾选isTrigger,调整box形状,将tag设置为Spikes,如图所示
创建随机生成平台脚本:用一个List来保存所有要生成的平台类型,设置生成平台的时间间隔spawnTime,以及生成平台的左右位置(左右各设置一个生成极值)。
生成平台的种类可以利用C#自带随机函数生成,即生成int index = Random.Range(0,List.Count)
玩家游戏性调整:调整Platform List中各种平台占比,控制游戏难度,可以以此制作难度与时间相关的游戏
不连续生成两个SpikedBall方法:设置全局变量spikeNum,如果生成了一个SpikedBall,spikeNum++,生成第二个时,spikeNum = 0,同时将index重置为**[0,3)之间的整数,注意,需要设置SpikedBall不在List**中的前三个位置。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Spawner : MonoBehaviour
{public List<GameObject> plantforms = new List<GameObject>();public float spawnTime;private float countTime;private Vector3 spawnPosition;int spikeNum = 0;// Update is called once per framevoid Update(){SpawnPlantform();}public void SpawnPlantform(){countTime += Time.deltaTime;spawnPosition = transform.position;spawnPosition.x = Random.Range(-3.5f, 3.5f);if(countTime >= spawnTime){CreatPlantform();countTime = 0; }}public void CreatPlantform(){int index = Random.Range(0, plantforms.Count);//Instantiate(plantforms[index], spawnPosition, Quaternion.identity);if (index == 4){spikeNum++;}if(spikeNum > 1){spikeNum = 0;//countTime = spawnTime;index = Random.Range(0, 3);//return;}GameObject newPlantform = Instantiate(plantforms[index], spawnPosition, Quaternion.identity);newPlantform.transform.SetParent(this.gameObject.transform);}
}
五、游戏管理 & UI
添加UI->Text,调整位置、字体等,用来计时(利用Time.timeSinceLevelLoad)。
添加游戏结束的Panel,包含Text(GameOver)和两个Button(PlayAgain,Quit)
创建脚本GameManage,挂到Empty GaemManage上。
PlayAgain方法利用SceneManger.LoadScene(SceneManager.GetActiveScene().name);实现。
Quit利用**Application.Quit()**方法。
角色死亡时暂停游戏(Time.timeScale = 0),显示panel。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;public class GameManage : MonoBehaviour
{static GameManage instance;public Text timeScore;public GameObject GameOverUI;private void Awake(){if(instance != null){Destroy(gameObject);}instance = this;}// Update is called once per framevoid Update(){timeScore.text = Time.timeSinceLevelLoad.ToString("00.0");}public void RestartGame(){SceneManager.LoadScene(SceneManager.GetActiveScene().name);Time.timeScale = 1f;}public void Quit(){Application.Quit();}public static void GameOver(bool dead){if (dead){instance.GameOverUI.SetActive(true);Time.timeScale = 0f;//Game pause;}}
}
附:游戏Demo:spikedball
spikedball
更多推荐
基于Unity的2D小游戏 SpeedDown 开发笔记(学习bilibili@[M
发布评论