《黄金矿工小游戏》是一款敏捷,经典小游戏。怀揣梦想的黄金矿工为了寻找更多金子开始了他的挖金之旅。
使用钩子放入地下,开拓你的智慧寻找宝物,达到目标金额过关吧!
本游戏开发工具选择Unity3D(2020.3.30f),开发语言选择C#
在2D游戏的制作中,我们考虑更多的是游戏的长宽页面,深度无法直接看出,首先需要调整摄像机模式,选择Main Camera 在Inspector中的Projection选为Orthographic。
注:没有近大远小的特点。
摄像机的渲染顺序由近到远,我们使用UI结合精灵的方式来制作游戏,将游戏分为三层:
背景层——游戏层——UI层
背景层和UI层使用UI搭建,游戏层使用精灵渲染器搭建。
Canvas有三种渲染方式
Overlay方式:Screen Space-Overlay(屏幕控件-覆盖模式)的画布会填满整个屏幕空间,并将画布下面的所有的UI元素置于屏幕的最上层,或者说画布的画面永远“覆盖”其他普通的3D画面,如果屏幕尺寸被改变,画布将自动改变尺寸来匹配屏
Camera方式;在该模式下,画布会被放置到摄影机前方。在这种渲染模式下,画布看起来 绘制在一个与摄影机固定距离的平面上。所有的UI元素都由该摄影机渲染,因此摄影机的设置会影响到UI画面。
WorldSpace方式:即世界控件模式。在此模式下,画布被视为与场景中其他普通游戏对象性质相同的类似于一张面片(Plane)的游戏物体。画布的尺寸可以通过RectTransform设置,所有的UI元素可能位于普通3D物体的前面或者后面显示。
我们制作背景层的时候选择Camera方式。
Render Camera 选择Main Camera
Camera 与Plane 之间选择一个合适距离即可
为BGCarnvas添加一个Image 选择 填充整个页面
Source Image 选择添加我们提前收集到的素材
完成效果如下:
UI层我们同样先新建一个Canvas,UI控件我们一般置于最上层,因此摄像机的一般的渲染方式选择Overlay,但是咱们本次UI内容比较简单,Time,Gold,Target三个文本,为了便于显示操作,我们使用Camera方式,将和摄像机的距离调整小于背景层与摄像机距离即可。
创建UItex,为time,gold,target创建UI文本。
首先创建GameManage图层作为游戏管理层,游戏层离摄像机的距离设置在UI层及背景层的中间。
在GameManage层中添加一个空物体名称为Icons方便我们管理游戏场景中的物体,在Icons下创建多个Sprite Rendere,导入我们的素材。在Unity的机制中,当我们选择了大于2个物体的时候,会优先考虑做成帧动画。因此可以创建出闪耀的物体。此时我们创建big_Gold、middle_Gold、small_Gold、diamond、mouse、rock作为我们的素材此时勾选好Animator(动画)将我们做好的动画状态机导入,可以用Crtl+d复制并在场景中移动到合适的位置。
在Gamemanage层中再创建一个sprite Renderer,命名为Rope,导入我们的绳子素材,移动到合适的位置。为Rope添加子物体作为抓钩。
不难发现,绳子的左右摆动可以通过改变Transform中的Rotation Z的值实现,绳子的缩放可以通过改变Transform中Scale Y 的值来实现。我们需要绳子的长度能够在斜对角的方向延展到最长。
绳子的状态应该有三种,摇摆,延长,收缩。
初始开始的时候绳子处于摇摆的状态,当鼠标点击屏幕后实现绳子的延长,在绳子达到最大距离后,绳子的状态变为收缩。
旋转我们可以用欧拉角或者四元数来做,
本次选择四元数:
Unity里提供了非常多的方式来创建一个四元数。例如:
Quaternion.AngleAxis(float angle, Vector3 axis)
它可以返回一个绕轴线axis旋转angle角度的四元数变换。我们可以一个Vector3和它进行左乘,就将得到旋转后的Vector3。在Unity里只需要用一个“ * ”操作符就可以进行四元数对向量的变换操作
绳子的延长可以用Lenth来记录随着时间增加。
注意:同时抓钩作为绳子的子物体应该同时变为1/Lenth。
首先确定我们抓取物体的部位是绳子的子物体抓钩,为抓钩添加Rigidbody刚体组件,再添加一个Circle Colider 2D。
再为Rope创建一个C#脚本作用为抓取.检测如果Colider2D有碰撞,直接变为自己的子物体。并调用根节点中的GameManage脚本中的收缩函数。
为每一组的物体添加标签。
在返回的过程中首先需要仅用Colider2D避免再次触发碰撞检测。
首先需要在GameManage层的C#脚本中获取Unity Engine UI,设置grade,times。
timetext此处需要转换为int类型。添加switch语句判断根据抓取物体的不同,增加不同的分数。
在这里分数的增加需要首先判断抓钩是否抓到物体,如果抓到了子物体调用Getchaild()来增加对应的分数。
当分数增加后,抓钩需要销毁物体,调用Destroy函数。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public enum State//状态
{
Rock,//摇摆
Stretch,//拉伸
Shorten//缩短
}
public class GameManage : MonoBehaviour {
private State state;
private Vector3 dir;
private Transform rope;
private Transform ropeCord;
private float length;
private int grade;
private float times;
public Text timeText;
public Text gradeText;
public State GetState
{
set { state = value; }
get { return state ; }
}
void Start () {
state = State.Rock;
dir = Vector3.back;
rope = transform.GetChild(0);
ropeCord = rope.GetChild(0);
length = 1;
times = 60;
grade = 0;
}
void Update () {
if (times <= 0) { times = 0; UnityEditor.EditorApplication.isPlaying = false; return; }
if (state == State.Rock)
{
Rock();
if (Input.GetMouseButtonDown(0)) state = State.Stretch;
}
else if (state == State.Stretch)
{
Stretch();
}
else if (state == State.Shorten)
{
Shorten();
}
times -= Time.deltaTime;
timeText.text = ((int)times).ToString();
gradeText.text = grade.ToString();
}
private void Rock()
{
if (rope.localRotation.z <= -0.5f)//0.5f为60度
dir = Vector3.forward;//逆时针
else if (rope.localRotation.z >= 0.5f)
dir = Vector3.back;//顺时针
rope.Rotate(dir * 60 * Time.deltaTime);
}
private void Stretch()
{
if (length >= 7.5f) { state = State.Shorten; return; }
length += Time.deltaTime*5;
rope.localScale = new Vector3(rope.localScale.x, length, rope.localScale.z);
ropeCord.localScale = new Vector3(ropeCord.localScale.x, 1 / length, ropeCord.localScale.z);
}
private void Shorten()
{
if (length <= 1)
{
length = 1;
state = State.Rock;
if (0 != ropeCord.childCount)
{
grade += GetGrade(ropeCord.GetChild(0).tag);
Destroy(ropeCord.GetChild(0).gameObject);
}
ropeCord.GetComponent().enabled = true;
return;
}
length -= Time.deltaTime*5;
rope.localScale = new Vector3(rope.localScale.x, length, rope.localScale.z);
ropeCord.localScale = new Vector3(ropeCord.localScale.x, 1 / length, ropeCord.localScale.z);
}
private int GetGrade(string tag)//每次得到的分数
{
int num = 0;
switch (tag)
{
case "Rock":
num = 10;
break;
case "SmallGold":
num = 50;
break;
case "Gold":
num = 100;
break;
case "BigGold":
num = 200;
break;
case "Mouse":
num = -1000;
break;
case "Diamond":
num = 500;
break;
}
return num;
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CheckObjects : MonoBehaviour {
public void OnTriggerEnter2D(Collider2D other)
{
other.transform.parent = transform;
transform.root.GetComponent().GetState = State.Shorten;
for (int i = 0; i < transform.childCount; i++)
{
transform.GetChild(i).GetComponent().enabled = false;
}
transform.GetComponent().enabled = false;
}
}