Unity破窗游戏制作(简易版)
Unity破窗游戏制作(简易版)
参考:“对不起,我选择摸鱼”—《扫雷》小游戏开发实战,算法、源代码,基于Unity3D开发 - 掘金 (juejin.cn)
到“制作默认方块(4)”均为相同操作
2-1、新建项目
(1)项目开发,从新建项目开始,我使用的Unity版本是Unity 2019.4.7f1,模板就选择2D,项目名称随意,别中文就行:

(2)创建目录,在Project视图,右击选择Create→Folder,新建几个文件夹:

(3)目录如下图所示:

- Prefabs:预制体资源文件夹
- Scenes:场景资源文件夹
- Scripts:脚本资源文件夹
- Sprites:图片资源文件夹
2-2、导入资源
接下来将需要的资源导入:

全部右键另存为图片,然后导入到Project视图的Sprites文件夹内:
选中所有图片,在Inspector视图中,设置Pixels Per Unit为16:

之所以设置为16,是因为16X16这个单位在游戏世界中是一个比较适合的值。
2-3、设置摄像机属性
在Hierarchy视图中,选中Main Cameras对象,然后在Inspector视图中找到Camera组件,设置属性:

注意:Clear Flags设置为Skybox,Background按照图中设置,然后Size设置为20。
2-4、制作默认方块
(1)将Project视图的Sprites目录中的default对象拖入Hierarchy视图中:

(2)选中default对象,在Inspector视图中,选择Add Componet→Physics 2D→Box Collider 2D,添加碰撞器组件:

注意:勾选Is Trigger
(3)选中default对象,拖回到Projcet视图的Prefabs文件夹内,做成一个预制体,我们将在后面的代码中去实例化生成它:

(4)Hierarchy视图中的default对象就可以删除了。
(5)新建脚本CreateBg.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateBg : MonoBehaviour
{
public GameObject block;//默认方块
void Start()
{
//创建默认方块
CreateBlock();
}
private void CreateBlock()
{
//创建方块父物体
GameObject blockParent = new GameObject("blockParent");
//创建10行10列的默认方块
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
{
//Instantiate参数为:预制体 位置 旋转 父物体
Instantiate(block, new Vector2(i, j), Quaternion.identity, blockParent.transform);
}
}
}
}
将脚本托给Main Camera对象,然后将预制体拖入Block卡槽中:

基本界面就做好了。
2-5、制作窗户类型
(1)新建一个脚本Element.cs,然后在Project视图的Prefabs文件夹中选中default对象,点击Add Componet→Element添加脚本:
.....
public bool Lock;//判断是否是锁住
public bool Perfect;//判断是否是完好
public bool Broken;
public Sprite LockTexture;
public Sprite PerfectTexture;
public Sprite BrokenTexture;
void Start()
{
//随机锁住
Lock = Random.value < 0.1;
Perfect = !Lock;
// 在Grid注册
int x = (int)transform.position.x;
int y = (int)transform.position.y;
Grids.elements[x, y] = this;
if (Lock) Grids.elements[x, y].loadTexture(0);
}
public void loadTexture(int adjacentCount)
{
if (adjacentCount==0)
GetComponent<SpriteRenderer>().sprite = LockTexture;
else if(adjacentCount==1)
GetComponent<SpriteRenderer>().sprite = PerfectTexture;
else GetComponent<SpriteRenderer>().sprite = BrokenTexture;
}
.....
(2)选中default预制体,将对应的资源拖入Element.cs脚本的属性卡槽中:


(3)新建一个Grid.cs脚本,将脚本也添加到预制体default身上,Grid脚本将处理更加复杂的游戏逻辑:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Grids : MonoBehaviour
{
public static int w=4; // 网格的长
public static int h=6; // 网格的高
public static Element[,] elements = new Element[w, h];
public static bool isPerfect(int x,int y)
{
....
}
public static bool isBroken(int x, int y)
{
....
}
public static void brokeWin(int x,int y)
{
....
}
public static bool isWin()
{
....
}
public static bool GameOver()
{
....
}
}
2-6、破坏窗户
Grids.cs:
public static bool isPerfect(int x,int y)
{
if (x >= 0 && y >= 0 && x < w && y < h)
return elements[x, y].Perfect;
return false;
}
public static bool isBroken(int x, int y)
{
if (x >= 0 && y >= 0 && x < w && y < h)
return elements[x, y].Broken;
return false;
}
public static void brokeWin(int x,int y)
{
if (isPerfect(x , y)) { elements[x, y].loadTexture(2);elements[x, y].Broken = true; elements[x, y].Perfect = false; }
else if (isBroken(x, y)) { elements[x, y].loadTexture(1); elements[x, y].Broken = false; elements[x, y].Perfect = true; }
}
Elements.cs:
void OnMouseUpAsButton()
{
if (!Lock) //锁住的窗无法互动
{
//反转5格内的非锁住窗户
int x = (int)transform.position.x;
int y = (int)transform.position.y;
Grids.brokeWin(x , y);
Grids.brokeWin(x-1, y);
Grids.brokeWin(x+ 1, y);
Grids.brokeWin(x, y-1);
Grids.brokeWin(x , y+1);
//判断是否胜利
if (Grids.isWin())
{
Debug.Log("Game Win");
}
if (Grids.GameOver())
{
Debug.Log("Game Over");
}
}
}
2-7、判断是否已经破坏所有窗户
接下来,需要判断玩家破坏所有窗户,
接着修改Grid类的代码,添加函数isWin:
public static bool isWin()
{
foreach (Element elem in elements)
if (elem.Perfect)
return false;
return true;
}
public static bool GameOver()
{
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
if (elements[i, j].Perfect && (i - 1 < 0 || !elements[i - 1, j].Perfect) && (i + 1 >= w || !elements[i + 1, j].Perfect) && (j - 1 < 0 || !elements[i, j - 1].Perfect) && (j + 1 >= h || !elements[i, j + 1].Perfect))
return true;
}
}
return false;
}
在这里游戏失败的原因可以有很多:
- 本就无解
- 超过了限制步数
- 超过时间
这些都可以自己写
然后获胜或失败的UI可以自己加
2-8、总结
游戏的大体框架就开发完成了,当然,你也可以添加一些元素让游戏更加有趣:
- 分成更多难度,比如简单、中等、困难
- 切换更加漂亮的UI
- 输赢界面以及重新开始
- 添加音效
2-9、源码
Grids:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Grids : MonoBehaviour
{
public static int w=4; // 网格的长
public static int h=6; // 网格的高
public static Element[,] elements = new Element[w, h];
public static bool isPerfect(int x,int y)
{
if (x >= 0 && y >= 0 && x < w && y < h)
return elements[x, y].Perfect;
return false;
}
public static bool isBroken(int x, int y)
{
if (x >= 0 && y >= 0 && x < w && y < h)
return elements[x, y].Broken;
return false;
}
public static void brokeWin(int x,int y)
{
if (isPerfect(x , y)) { elements[x, y].loadTexture(2);elements[x, y].Broken = true; elements[x, y].Perfect = false; }
else if (isBroken(x, y)) { elements[x, y].loadTexture(1); elements[x, y].Broken = false; elements[x, y].Perfect = true; }
}
public static bool isWin()
{
foreach (Element elem in elements)
if (elem.Perfect)
return false;
return true;
}
public static bool GameOver()
{
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
if (elements[i, j].Perfect && (i - 1 < 0 || !elements[i - 1, j].Perfect) && (i + 1 >= w || !elements[i + 1, j].Perfect) && (j - 1 < 0 || !elements[i, j - 1].Perfect) && (j + 1 >= h || !elements[i, j + 1].Perfect))
return true;
}
}
return false;
}
}
Element:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Element : MonoBehaviour
{
public bool Lock;//判断是否是锁住
public bool Perfect;//判断是否是完好
public bool Broken;
public Sprite LockTexture;
public Sprite PerfectTexture;
public Sprite BrokenTexture;
void Start()
{
//随机锁住
Lock = Random.value < 0.1;
Perfect = !Lock;
int x = (int)transform.position.x;
int y = (int)transform.position.y;
Grids.elements[x, y] = this;
if (Lock) Grids.elements[x, y].loadTexture(0);
}
public void loadTexture(int adjacentCount)
{
if (adjacentCount==0)
GetComponent<SpriteRenderer>().sprite = LockTexture;
else if(adjacentCount==1)
GetComponent<SpriteRenderer>().sprite = PerfectTexture;
else GetComponent<SpriteRenderer>().sprite = BrokenTexture;
}
// 判断是否被点击
public bool isCovered()
{
//判断当前纹理的名称是不是默认值
return GetComponent<SpriteRenderer>().sprite.texture.name == "default";
}
// 鼠标点击
void OnMouseUpAsButton()
{
if (!Lock)
{
//破坏周围的窗户
int x = (int)transform.position.x;
int y = (int)transform.position.y;
Grids.brokeWin(x , y);
Grids.brokeWin(x-1, y);
Grids.brokeWin(x+ 1, y);
Grids.brokeWin(x, y-1);
Grids.brokeWin(x , y+1);
//判断是否胜利
if (Grids.isWin())
{
Debug.Log("Game Win");
}
if (Grids.GameOver())
{
Debug.Log("Game Over");
}
}
}
}
CreateBg:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CreateBg : MonoBehaviour
{
public GameObject block;//默认方块
void Start()
{
//创建默认方块
CreateBlock();
}
public void CreateBlock()
{
//创建方块父物体
GameObject blockParent = new GameObject("blockParent");
//创建10行10列的默认方块
for (int i = 0; i <Grids.w; i++)
{
for (int j = 0; j < Grids.h; j++)
{
//Instantiate参数为:预制体 位置 旋转 父物体
Instantiate(block, new Vector2(i, j), Quaternion.identity, blockParent.transform);
}
}
}
}
2-10、效果

Unity破窗游戏制作(简易版)的更多相关文章
- Unity 进度条3D制作(3D版)
昨天我们一起学习了2D进度跳的制作,那么趁着我们脑海中还残存昨日的记忆,今天继续学习另一种方法: 实现思路:当鼠标悬浮Start按钮->实例化物体并显示进度->100/100->进入 ...
- 简易2D横版RPG游戏制作
Unity学习笔记1 简易2D横版RPG游戏制作 http://m.blog.csdn.net/article/details?id=24601905
- html5 canvas简易版捕鱼达人游戏源码
插件描述:html5利用canvas写的一个js版本的捕鱼,有积分统计,鱼可以全方位移动,炮会跟着鼠标移动,第一次打开需要鼠标移出背景图,再移入的时候就可以控制炮的转动,因为是用的mouseover触 ...
- unity入门—五分钟制作一个理论上的游戏
unity入门 前言:这可不是标题党,虽然都是基础的操作,不过含括了基本的流程,比起脑海中的五花八门的画面,入门还是这个现实一点. 这里插两句,unity国外官网下载会推荐你看一个简短的视频,国内官网 ...
- 自定义View4-塔防小游戏第一篇:一个防御塔+多个野怪(简易版)*
塔防小游戏 第一篇:一个防御塔+多个野怪(简易版) 1.canvas画防御塔,妖怪大道,妖怪行走路线 2.防御塔攻击范围是按照妖怪与防御塔中心距离计算的,大于防御塔半径则不攻击,小于则攻击 ...
- 利用Unity3D制作简易2D计算器
利用Unity3D制作简易2D计算器 标签(空格分隔): uiniy3D 1. 操作流程 在unity3DD中创建一个新项目 注意选择是2D的(因为默认3D) 在Assets框右键新建C#脚本 在新建 ...
- MVC 验证码实现( 简易版)
现在网站上越来越多的验证码,使用场景也是越来越多,登陆.注册.上传.下载...等等地方,都有可能大量使用到验证码,那么制作验证码到底有多简单呢?我们一起来看下最简易版的验证码实现过程- 验证码的基本步 ...
- C+命令行+方向键=简易版扫雷
前言: 想起来做这个是因为那时候某天知道了原来黑框框里面的光标是可以控制的,而且又经常听人说起这个,就锻炼一下好了. 之前就完成了那1.0的版本,现在想放上来分享却发现有蛮多问题的,而且最重要的是没什 ...
- 游戏制作之路:一个对我来说可实现的High-end的Mac/iOS游戏制作大概计划
对于学习一些东西,我比较习惯任务驱动式的学习,也就是说,要事先订好一个目标,要做什么东西,达到什么效果,然后根据自己了解的知识作一个可以实现这个目标的计划. 现在要学的是游戏制作,而且是High-en ...
随机推荐
- ceph 005 赋权补充 rbd块映射
我的ceph版本 [root@serverc ~]# ceph -v ceph version 16.2.0-117.el8cp (0e34bb74700060ebfaa22d99b7d2cdc037 ...
- 基于EasyExcel实现的分页数据下载封装
功能概述 主要实现的功能: 1.分页查询,避免一次性查询全部数据加载到内存引起频繁FULL GC甚至OOM 2.当数据量超过单个工作簿最大行数(1048575)时,自动将数据写入新的工作簿 3.支持百 ...
- 微服务性能分析|Pyroscope 在 Rainbond 上的实践分享
随着微服务体系在生产环境落地,也会伴随着一些问题出现,比如流量过大造成某个微服务应用程序的性能瓶颈.CPU利用率高.或内存泄漏等问题.要找到问题的根本原因,我们通常都会通过日志.进程再结合代码去判断根 ...
- 深入理解Redis 数据结构—字典
字典,又称为符号表.关联数组或映射,是一种用于保存键值对的抽象数据结构.在字典中,一个键可以和一个值进行关联,这些关联的键和值称为键值对.键值对中键是唯一的,我们可以根据键key通过映射查找或者更新对 ...
- UVA1306 The K-League(最大流)
题面 有 n n n 支队伍进行比赛,每支队伍需要打的比赛数目相同. 每场比赛恰好一支队伍胜,另一支败. 给出每支队伍目前胜的场数 w i w_i wi 和败的场数(没用),以及每两个队伍还剩下的比 ...
- HTML创建访问加密代码
在</head>前面加入即可 普通方式 此方法屏蔽F12查看源码但是屏蔽不了Ctrl+U查看源码 解决方式加密html即可注意!解密比较繁琐切记要记住自己设置的密码 <SCRIPT ...
- React报错之Rendered more hooks than during the previous render
正文从这开始~ 总览 当我们有条件地调用一个钩子或在所有钩子运行之前提前返回时,会产生"Rendered more hooks than during the previous render ...
- KingbaseES的表空间
表空间的概念 KingbaseES中的表空间允许在文件系统中定义用来存放表示数据库对象的文件的位置.实际上表空间就是给表指定一个存储目录. 表空间的作用 通过使用表空间,管理员可以控制一个Kingba ...
- Windows客户端DNS工作原理
通常大家对Windows客户端DNS的配置存在多个误区. 误区一,配置1个内网DNS,1个外网DNS.解析内网的时候用内网DNS,解析外网的时候用外网. 电脑怎么知道哪个是内网?哪个是外网?我们内部的 ...
- Linux使用密钥登录SSH
输入命令和上传密钥时需要注意当前目录.账号和读写权限 生成密钥 使用服务器生成(方法一,推荐) 1.1生成密钥 #ssh-keygen(这里pwd为当前账号的home目录) 1.2下载密钥 .id_r ...