how-to-make-a-video-game-in-unity-game-over-e08
Course: 【油管100w+】 Unity 入门视频
🎮 视频标题|How to make a Video Game in Unity — GAME OVER (E08)
👤 主讲人|Brackeys
📅 系列定位|Unity 初学者系列 Episode 08
🏷 关键词|GameManager | Restart | SceneManager | Invoke | 布尔状态 | Game Over | Delay
🏛 课程目标
为游戏添加一个“游戏结束与重启系统”,
当玩家撞上障碍或掉出地图时,游戏延迟几秒后自动重启。
🧭 核心思路
1️⃣ 用一个新的脚本 GameManager 负责管理游戏状态。
2️⃣ 当玩家死亡(碰撞或坠落)时调用 EndGame()。
3️⃣ 延迟几秒后通过 SceneManager.LoadScene() 重新加载当前关卡。
📦 创建 GameManager 系统
1️⃣ Hierarchy → 右键 → Create Empty → 命名为 GameManager
2️⃣ Reset Transform(保持干净)
3️⃣ 点击 “Add Component” → 新建脚本 → 命名为 GameManager
🧠 GameManager.cs 初版
using UnityEngine;
public class GameManager : MonoBehaviour
{
public void EndGame()
{
Debug.Log("Game Over");
}
}📘 public 关键字允许在其他脚本中访问该函数。
先用
Debug.Log()打印信息验证是否触发。
📚 在 PlayerCollision 中调用 GameManager
目前碰撞逻辑在 PlayerCollision.cs 中:
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false;
// TODO: 调用 GameManager.EndGame()
}直接引用会导致预制体引用丢失问题。
👉 解决方案:动态查找对象。
FindObjectOfType<GameManager>().EndGame();Unity 会在场景中搜索第一个挂有 GameManager 脚本的对象并调用方法。
虽然效率略低,但简单安全。
🧩 引用变量丢失原因
当 Player 被制作成 Prefab 并重新拖回场景时,
Inspector 中的手动引用会丢失。
通过 FindObjectOfType<> 可避免这种情况,无需手动拖引用。
⚠️ 注意:性能低于直接引用,仅在需要动态实例化对象时使用。
📦 让玩家掉落时也触发游戏结束
在 PlayerMovement.cs 中添加以下代码:
void FixedUpdate()
{
if (rb.position.y < -1f)
{
FindObjectOfType<GameManager>().EndGame();
}
}- 检查 Y 坐标是否低于阈值(-1 表示掉出地图)
- 掉落时自动调用 Game Over
📘 Unity 中 FixedUpdate() 是物理计算帧函数,
因此适合检测基于 Rigidbody 的坐标变化。
🧪 防止重复调用多次 EndGame()
如果玩家连续掉落或多次触发碰撞,会出现多次重启。
→ 使用布尔变量限制只执行一次。
bool gameHasEnded = false;
public void EndGame()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("Game Over");
Restart();
}
}✅ 确保只执行一次。
🧩 “状态锁”机制是游戏逻辑中常见的防抖方法。
📚 实现关卡重启逻辑
在 GameManager.cs 末尾添加:
using UnityEngine.SceneManagement;
public float restartDelay = 1f;
void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}SceneManager.GetActiveScene().name:返回当前活动场景名称。SceneManager.LoadScene():重新加载该场景实现“重开游戏”。
🧠 添加延迟重启效果
直接调用重启太快,看起来突兀。
Unity 提供 Invoke() 延迟执行函数:
public void EndGame()
{
if (!gameHasEnded)
{
gameHasEnded = true;
Debug.Log("Game Over");
Invoke("Restart", restartDelay);
}
}🎯 Invoke(“方法名”, 延迟时间) 可让游戏在几秒后执行操作。
这里的
restartDelay默认为 1 秒,可在 Inspector 调整。
✅ 完整 GameManager.cs
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour
{
bool gameHasEnded = false;
public float restartDelay = 1f;
public void EndGame()
{
if (!gameHasEnded)
{
gameHasEnded = true;
Debug.Log("Game Over");
Invoke("Restart", restartDelay);
}
}
void Restart()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}📘 逻辑流程:
1️⃣ 检测游戏结束
2️⃣ 锁定状态(防止重复)
3️⃣ 延迟重启
4️⃣ 重新加载当前关卡
📦 小问题:重新加载后光照变灰
原因:Lighting → “Auto Generate” 选项。
当场景在编辑器中重新加载时,Unity 没时间重建光照。
✅ 解决方法:
- 打开 Window → Rendering → Lighting Settings
- 取消勾选
Auto Generate - 点击 “Generate Lighting” 手动构建。
生产环境推荐关闭 Auto,提高加载一致性。
📚 Build Settings 检查
若重启时报错:
“Scene not in build settings”
解决:
- File → Build Settings → “Add Open Scenes”
- 确保当前关卡在构建列表中。
- 多关卡项目可按 Build Index 管理场景切换。
✅ 本集成果总结
| 模块 | 功能 |
|---|---|
| GameManager | 管理全局游戏状态 |
| EndGame() | 控制游戏结束触发 |
| Invoke() | 延迟调用重启 |
| SceneManager | 加载当前或下个场景 |
| 布尔锁 | 防止多次执行逻辑 |
| Lighting 调整 | 修复自动光照闪烁 |
🪄 延伸练习
1️⃣ 添加 GameOverUI → 在游戏结束时显示文字而非立即重启。
2️⃣ 将重启绑定到按钮点击事件 (OnClick → GameManager.Restart())。
3️⃣ 结合分数系统(E07),在 Game Over 界面显示最终得分。
4️⃣ 添加动画淡出效果或背景音乐停止逻辑。
📚 下一集预告:Final Polish & Build
Episode 09 将进入游戏收尾阶段,
添加主菜单、结束画面与打包导出流程。
你将学习:
- UI Button 点击事件
- 多场景切换
- 游戏最终打包设置