Unity开发2d游戏全套教程
官方手册:https://docs.unity.cn/cn/2023.2/Manual/class-EdgeCollider2D.html
项目素材地址(Github),欢迎star:
https://github.com/ziyifast/ziyifast-code_instruction/tree/main/unity-demo/SnakeRun
- 本期只演示最基本的操作,大家可以在这个基础上进行修改,比如添加背景或者添加音乐
环境准备:下载Unity
- 下载Unity
进入官网,选择对应操作系统、对应版本下载即可
我这里是mac,直接下载最新长期支持版的mac即可:
也可以直接下载Unity Hub,从Unity Hub中安装

下载好后,根据自己后续游戏开发的必要,下载对应的扩展包,但需要勾选WebGL Build Support,因为我们后续会将游戏打包为Web发布到网站上。
- 下载.net环境
游戏开发语言使用C#,所以需要准备.net环境。
创建项目
我们开发的是2D游戏,这里选择2D游戏模板

实战开发
场景搭建+实现小蛇跳跃
1. assets中导入角色与背景图片
2. 创建Snake物品,create empty

3. 给这个Snake物品添加一个sprite renderer,将小蛇图片拖入其中,按住shit键可以等比例缩放小蛇
相当于我们这里用这个小蛇图片进行渲染
4. 调整渲染图颜色及物体大小

5. 点击播放,查看效果

效果:
6. 给Snake这个物品添加Rigidbody 2D重力,让其实现自然坠落

7. 添加C#脚本代码,实现Snake跳跃操作

csharp
using UnityEngine;
public class SnakeController : MonoBehaviour
{
//每次跳动的高度
public float jumpForce = 5f;
private Rigidbody2D rb;
public GameObject gameOverPanel;
private bool isGameOver = false;
public float upperLimit = 1000000000f; // Set this to the top of your screen
public float lowerLimit = -1000000000f; // Set this to the bottom of your screen
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (isGameOver) return;
if (Input.GetKeyDown(KeyCode.Space))
{
Jump();
}
}
private void Jump()
{
rb.linearVelocity = Vector2.up * jumpForce;
}
}
运行游戏查看效果

创建障碍物+实现物体碰撞
1. 创建空物品Barrier,在下面分别创建topBarrier、bottomBarrier
分别给topBarrier、bottomBarrier添加Sprite Renderer,并调整物品页面布局

点击运行游戏,查看效果:
2. 添加C#脚本,让障碍物实现向左移动(从视觉上实现小蛇向右移动)

csharp
using UnityEngine;
public class BarrierController : MonoBehaviour
{
public float speed = 2f;
public float lifetime = 10f;
private void Start()
{
//实现超出范围后,销毁多余的障碍物
Destroy(gameObject, lifetime);
}
private void Update()
{
MoveLeft();
}
private void MoveLeft()
{
//向左移动障碍物
// Debug.Log("move left....");
transform.Translate(Vector2.left * speed * Time.deltaTime);
}
}

效果:
3. 给小蛇、障碍物都添加collider,实现碰撞效果
障碍物、小蛇添加:Box collider 2D
- 因为障碍物、小蛇类似正方体,所以添加box collider更合理。当然大家也可以根据自己角色进行调整
给障碍物添加collider:
小蛇同理

效果:
4. 解决碰撞后,翻滚问题
目前小蛇和障碍物碰撞后,小蛇会翻滚

解决:调整小蛇的rigidbody 2d属性,冻结Z方向
效果

脚本实现障碍物自动随机生成
目前游戏场景中的障碍物是我们自己手动拖进去的,如果要添加多个障碍物肯定不能由我们手动去操作。这里我们可以通过C#代码实现自动生成。
1. 在Assets目录下新建Prefab文件夹,用于存储我们的复制品
2. 将Barrier拖到Prefab文件夹中,这样Barrier就成了复制品,然后我们就可以删除场景里的Barrier了
如果我们想要Pipe,直接到Asset目录下的Prefab文件夹下拖动Pipe即可,想要多个就拖动多个。优化:后续会采用代码来实现自动生成

3. 新建BarrierSpawner物品,并添加BarrierSpawner脚本实现自动生成障碍物

csharp
using UnityEngine;
public class BarrierSpawner : MonoBehaviour
{
public GameObject barrierPrefab;
public float spawnDelay = 2f;
public float minSpawnHeight = -2f;
public float maxSpawnHeight = 2f;
private void Start()
{
//重复调用函数,实现物品复制重复创建
InvokeRepeating("SpawnBarrier", 0f, spawnDelay);
}
private void SpawnBarrier()
{
float randomHeight = Random.Range(minSpawnHeight, maxSpawnHeight);
Vector2 spawnPosition = new Vector2(transform.position.x, randomHeight);
Instantiate(barrierPrefab, spawnPosition, Quaternion.identity);
}
}
效果

实现加分机制
当小蛇通过一个障碍物时,我们应该实现加分,实现思路:
在上下两个障碍物之间添加trigger,当小蛇通过后,触发trigger,执行加分函数
1. Barrier下添加scoreCheck,scoreCheck添加box collider 2d,并勾选Is Trigger

2. 添加ScoreManager物品,同时添加ScoreManager代码
ScoreManager.cs:
csharp
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour
{
public static int score = 0;
public Text scoreText;
private void Update()
{
// Update the text field with the current score
//scoreText.text = score.ToString();
}
// public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
// {
// SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
// score = 0;
// }
}
SnakeController.cs代码中添加分数逻辑:
3. 新增Canvas物品,添加分数面板展示分数

4. 添加Text展示分数

5. 调整页面分数字体大小、颜色等

6. ScoreManager.cs添加分数展示逻辑,并将Score Text文字展示框拖动到ScoreManager物品下
csharp
private void Update()
{
// Update the text field with the current score
scoreText.text = score.ToString();
}

效果

实现游戏结束逻辑
1. Canvas下添加Panel,并调整页面展示位置与大小

2. GameOverPanel下添加Text与Button,提示游戏结束与重新开始按钮
UI - Legacy - Text
UI - Legacy - Button
效果:
3. 隐藏游戏结束页面,当触发碰撞💥条件时,游戏才结束

SnakeController.cs中新增游戏结束逻辑:
csharp
//当snake与Barrier相撞时,游戏结束
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Barrier"))
{
// Game over
GameOver();
}
}
private void GameOver()
{
isGameOver = true; // Add this line
// Freeze the Snake's motion
rb.linearVelocity = Vector2.zero;
if (gameOverPanel != null)
{
//展示游戏结束页面
gameOverPanel.SetActive(true);
}
}
SnakeController.cs全部代码:
csharp
using UnityEngine;
public class SnakeController : MonoBehaviour
{
//每次跳动的高度
public float jumpForce = 5f;
private Rigidbody2D rb;
public GameObject gameOverPanel;
private bool isGameOver = false;
public float upperLimit = 1000000000f; // Set this to the top of your screen
public float lowerLimit = -1000000000f; // Set this to the bottom of your screen
//public AudioSource jumpSFX;
private void Start()
{
rb = GetComponent<Rigidbody2D>();
}
private void Update()
{
if (isGameOver) return;
// Check if Snake is out of bounds【小蛇超出页面也触发游戏结束】
// if (transform.position.y > 50f || transform.position.y < -50f)
// {
// //Debug.Log(transform.position.y);
// GameOver();
// }
if (Input.GetKeyDown(KeyCode.Space))
{
Jump();
}
}
private void Jump()
{
rb.linearVelocity = Vector2.up * jumpForce;
//jumpSFX.Play();
}
//与Trigger部分碰撞时,触发分数加操作
private void OnTriggerEnter2D(Collider2D collision)
{
// if (isGameOver) return; // Add this line
//Debug.Log("Score: " + ScoreManager.score);
ScoreManager.score++;
}
//当snake与Barrier相撞时,游戏结束
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.CompareTag("Barrier"))
{
// Game over
GameOver();
}
}
private void GameOver()
{
isGameOver = true; // Add this line
// Freeze the Snake's motion
rb.linearVelocity = Vector2.zero;
if (gameOverPanel != null)
{
//展示游戏结束页面
gameOverPanel.SetActive(true);
}
}
}
4. SnakeController中添加游戏结束Panel

5. 为障碍物添加Barrier标签
因为c#代码中是通过Barrier Tag来判断

给topBarrier、bottomBarrier分别添加tag:
效果
实现重玩逻辑
给游戏结束页面的[重新开始]按钮绑定事件,点击时,触发游戏重新开始
1. ScoreManager.cs新增重玩逻辑代码:
csharp
//游戏重新开始,分数清零,重新加载游戏场景
public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
score = 0;
}
ScoreManager.cs全部代码:
csharp
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
public class ScoreManager : MonoBehaviour
{
public static int score = 0;
public Text scoreText;
private void Update()
{
// Update the text field with the current score
scoreText.text = "Score:" + score.ToString();
}
//游戏重新开始,分数清零,重新加载游戏场景
public void OnRestartButtonClick() // Connect this function to your button's onClick event in the inspector
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
score = 0;
}
}
2. GameOverPanel下的Button绑定重新开始逻辑

效果

游戏打包
1. File - Build Profile

2. 选择打包参数
因为我们这里是打包发布到web服务器上,所以这里直接选择web,然后点击切换平台

3. 修改压缩参数,改为gzip或不压缩
因为Brotli 在http上不支持压缩,改成G-zip或不压缩
4. 点击Build打包游戏,然后选择打包后文件存放位置

游戏上线(itch.io)
itch.io可以算是全球最大的独立游戏平台。它和steam一样,你可以把你的游戏上架到itch上,可以是免费的,也可以让大家捐赠,也可以让大家付费购买。
-
注册账号之后,创建项目:
-
填写游戏基本信息
-
填写完后选择save,保存为draft(第一次只能保存为草稿)
-
保存完后,点击项目,改为public,表明游戏公开,然后就可以把体验链接发给其他人体验了
本地运行游玩
打包后的游戏,有两个文件夹(Build、TemplateData),一个文件(index.html)

python
# 本地运行项目:可以通过python直接起http服务,也可以下载nginx或Tomcat等
# 9999指定运行端口
# --directory 指定unity打包后的路径
python3 -m http.server 9999 --directory /Users/ziyi/Desktop/ZiyiSnakeRun

浏览器访问localhost:9999
效果:
全部代码地址(资源文件地址)
Github(欢迎star~):https://github.com/ziyifast/ziyifast-code_instruction/tree/main/unity-demo/SnakeRun