目录
前言
这篇文章完成一个简单的经典游戏“2048”unity 小游戏,有游戏视频。程序按注释的代码框架,严格分为三部分,并满足三部分之间的约束关系。
一、Unity的游戏循环和mvc结构
Unity 的游戏循环
Unity 的游戏循环是指每帧更新和渲染的流程。这个循环通常由以下几个主要部分组成:
- 初始化(Initialization): 游戏开始时,进行必要的初始化设置,比如加载资源、创建游戏对象等。
- 输入处理(Input Handling): 在每一帧中,检查用户输入(如键盘、鼠标、触控等)。
- 更新(Update): 调用所有活动对象的更新方法,这通常在每一帧中执行。这个方法用于处理游戏逻辑、物理计算和其他状态更新。
- 渲染(Rendering): 将场景中的对象渲染到屏幕上,显示最新的状态。
- 结束(End): 当游戏结束时,执行清理和资源释放。
MVC 结构
MVC(模型-视图-控制器)是一种软件架构模式,常用于分离应用程序的逻辑层、数据层和表现层。其组成部分如下:
- 模型(Model): 代表应用程序的数据和业务逻辑。模型处理数据的存储、处理和业务规则,而不关心如何显示这些数据。
- 视图(View): 负责呈现模型的数据,显示给用户。视图通常不处理任何业务逻辑,只负责如何将数据展现出来。
- 控制器(Controller): 充当模型和视图之间的桥梁。控制器接收用户的输入,调用模型的方法来更新数据,并更新视图以反映最新的数据状态。
在 Unity 中的结合
虽然 Unity 的主要结构是基于组件的设计(如 MonoBehaviour),但也可以结合 MVC 模式进行组织:
- 模型可以使用脚本来管理游戏状态(例如玩家分数、游戏进度等)。
- 视图可以是 UI 元素和游戏对象,负责展示模型的数据。
- 控制器可以是处理输入和游戏逻辑的脚本,负责管理模型和视图之间的交互。
二、让Unity运行代码的基础流程
1. 创建一个 Unity 项目
- 打开 Unity Hub,点击“New Project”来创建一个新的 2D 或 3D 项目。
- 选择合适的模板(可以使用 2D 模板,因为这是一个棋盘类的小游戏)。
- 命名项目并选择保存位置,然后点击“Create”来创建项目。
2. 创建必要的文件和对象
-
创建一个空对象:
- 在 Unity 场景中,右键
Hierarchy
面板,选择Create Empty
来创建一个空对象。 - 将这个对象重命名为
GameController
,用于挂载脚本。
- 在 Unity 场景中,右键
-
创建 Scripts 文件夹并添加脚本:
- 在
Project
面板中,右键点击空白区域,选择Create > C# Script
,将新建的脚本命名为ChessGame
。 - 双击
ChessGame.cs
脚本文件,打开 Visual Studio 或其他代码编辑器,编写逻辑(代码我放在后文了)。
- 在
-
将脚本附加到对象上:
- 在
Hierarchy
面板中,选择GameController
对象,然后将ChessGame
脚本从Project
面板中拖到Inspector
面板中的GameController
对象上,或者点击Add Component
按钮并搜索ChessGame
来附加脚本。
- 在
3. 运行游戏测试
-
点击
Play
按钮:- 在 Unity 编辑器顶部中间的工具栏中,点击
Play
按钮来运行游戏。
- 在 Unity 编辑器顶部中间的工具栏中,点击
-
检查
Console
面板:- 如果游戏无法正常运行,查看
Console
面板中是否有错误或警告信息。
- 如果游戏无法正常运行,查看
三、ChessGame.cs
脚本
unity小游戏2048: 不必多言 (gitee.com)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NumberGame : MonoBehaviour
{
// Entities and their states / Model
private static int[,] board = new int[4, 4];
private static int score;
// System Handlers
void Start()
{
Init();
}
// View to render entities / models
void OnGUI()
{
// 绘制重启按钮
if (GUI.Button(new Rect(310, 340, 100, 30), "Restart"))
{
Debug.Log("Restart button pressed!"); // 调试信息
Init(); // 确保调用 Init 方法
}
// 画分数框
GUI.Box(new Rect(210, 25, 300, 50), "Score: " + score);
// 画棋盘
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
float buttonX = 210 + j * 70 + 10;
float buttonY = 80 + i * 70;
GUI.Button(new Rect(buttonX, buttonY, 70, 70), board[i, j] != 0 ? board[i, j].ToString() : "");
}
}
}
// Components /controls
void Init()
{
Debug.Log("Init method called.");
board = new int[4, 4];
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
board[i, j] = 0;
score = 0;
AddNewNumber();
AddNewNumber();
}
void AddNewNumber()
{
List<Vector2> emptyCells = new List<Vector2>();
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++)
if (board[i, j] == 0) emptyCells.Add(new Vector2(i, j));
if (emptyCells.Count > 0)
{
Vector2 cell = emptyCells[Random.Range(0, emptyCells.Count)];
board[(int)cell.x, (int)cell.y] = Random.Range(1, 3) * 2;
}
else
{
if (IsGameOver())
{
Debug.Log("Game Over!");
}
}
}
bool IsGameOver()
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
if (board[i, j] == 0) return false;
if (i < 3 && board[i, j] == board[i + 1, j]) return false;
if (j < 3 && board[i, j] == board[i, j + 1]) return false;
}
}
return true; // 没有可移动的方块,游戏结束
}
// Add methods for sliding and merging numbers here
void Update()
{
if (Input.GetKeyDown(KeyCode.UpArrow)) SlideUp();
if (Input.GetKeyDown(KeyCode.DownArrow)) SlideDown();
if (Input.GetKeyDown(KeyCode.LeftArrow)) SlideLeft();
if (Input.GetKeyDown(KeyCode.RightArrow)) SlideRight();
}
void SlideUp()
{
for (int j = 0; j < 4; j++)
{
List<int> column = new List<int>();
for (int i = 0; i < 4; i++)
{
if (board[i, j] != 0) column.Add(board[i, j]);
}
Merge(column);
for (int i = 0; i < 4; i++)
{
board[i, j] = i < column.Count ? column[i] : 0;
}
}
AddNewNumber();
}
void SlideDown()
{
for (int j = 0; j < 4; j++)
{
List<int> column = new List<int>();
for (int i = 3; i >= 0; i--)
{
if (board[i, j] != 0) column.Add(board[i, j]);
}
Merge(column);
for (int i = 0; i < 4; i++)
{
board[3 - i, j] = i < column.Count ? column[i] : 0;
}
}
AddNewNumber();
}
void SlideLeft()
{
for (int i = 0; i < 4; i++)
{
List<int> row = new List<int>();
for (int j = 0; j < 4; j++)
{
if (board[i, j] != 0) row.Add(board[i, j]);
}
Merge(row);
for (int j = 0; j < 4; j++)
{
board[i, j] = j < row.Count ? row[j] : 0;
}
}
AddNewNumber();
}
void SlideRight()
{
for (int i = 0; i < 4; i++)
{
List<int> row = new List<int>();
for (int j = 3; j >= 0; j--)
{
if (board[i, j] != 0) row.Add(board[i, j]);
}
Merge(row);
for (int j = 0; j < 4; j++)
{
board[i, 3 - j] = j < row.Count ? row[j] : 0;
}
}
AddNewNumber();
}
void Merge(List<int> line)
{
for (int i = 0; i < line.Count - 1; i++)
{
if (line[i] == line[i + 1])
{
line[i] *= 2;
score += line[i];
line.RemoveAt(i + 1);
}
}
}
}
四、演示视频
总结
这篇文章说明了如何用unity实现一个简单的游戏,并介绍了游戏循环和mvc结构以及即使模式GUI,然后示例2048的实现。