🎯 一、项目基础搭建与玩家核心(1-8 步)
这是项目的起点,主要目标是搭建场景和实现玩家的基本移动。
- 新建 3D 项目: 在 Unity Hub 中选择 "3D" 模板。
- 创建地面: 在 Hierarchy 中创建 3D Object -> Plane,并调整 Scale (10, 1, 10) 。
- 创建玩家: 创建 3D Object -> Cube,命名
Player,调整 Y 位置到 0.5。 - 添加物理组件: 给
Player添加 Rigidbody 组件。 - 编写移动脚本: 创建
PlayerMovement.cs并在FixedUpdate中使用rb.AddForce。 - 附加脚本: 将
PlayerMovement.cs拖拽到Player对象上。 - 配置摄像机: 调整
Main Camera到玩家后上方,并编写CameraFollow.cs脚本在LateUpdate中跟随。 - 创建地面标签: 给
Plane对象设置 Tag:Ground,用于检测玩家落地。
🚧 二、关卡元素与交互实现(9-14 步)
此阶段目标是创建障碍、定义终点和失败区,并编写相应的交互逻辑。
- 创建障碍物: 创建 Cube,调整 Scale,不勾选
Is Trigger。 - 创建终点线: 创建 Cube,命名
FinishLine,勾选Is Trigger。 - 设置终点标签: 给
FinishLine设置 Tag:FinishLine。 - 添加跳跃逻辑: 在
PlayerMovement.cs中实现isGrounded状态和 空格键 输入。 - 编写落地检测: 在
PlayerMovement.cs中实现OnCollisionEnter切换isGrounded状态。 - 编写触发逻辑: 在
PlayerMovement.cs中实现OnTriggerEnter检测终点。
🖥️ 三、UI 与流程管理(15-21 步)
引入用户界面、流程控制脚本,并实现游戏的胜利、失败、重启状态。
- 创建 UI Canvas: 右键 Hierarchy,选择 UI -> Text - TextMeshPro。
- 创建胜利文本: 创建
WinText,默认隐藏 (禁用) 。 - 创建失败文本: 复制
WinText为GameOverText,默认隐藏 (禁用) 。 - 创建流程控制器: 创建空对象
GameManager,并附加GameController.cs脚本。 - 实现场景管理: 在
GameController.cs中实现RestartGame()函数 (使用SceneManager)。 - 设置 Build Settings: File > Build Settings,将当前场景添加到 Scenes in Build。
- 实现快速重启: 在
GameController.cs的Update中检测 R 键 调用RestartGame()。
🎨 四、高级效果与优化(22-28 步)
增加游戏的专业度和视觉吸引力,优化工作流程。
- 创建障碍预制件: 将一个障碍物 拖拽 到 Project 视图中的 Prefabs 文件夹。
- 复制障碍: 从 Prefabs 文件夹拖拽障碍物到场景中,快速搭建跑道。
- 实现计时器 UI: 创建
TimerText放在屏幕上方,并附加GameTimer.cs到GameManager。 - 实现慢动作: 在
GameController.cs中实现DoSlowMotion()(调整Time.timeScale),在GameOver时调用。 - 实现落地特效: 创建 Effects -> Particle System,命名
LandingSmokeFX,作为 Player 子对象。 - 实现跳跃音效: 给
Player添加 Audio Source,并在Jump()函数中调用audioSource.PlayOneShot()。 - 完成最终引用: 在 Unity 编辑器的 Inspector 中,确保所有脚本(Player/Controller/Timer)之间所需的引用(如
winTextObject,gameController等)都已正确拖拽关联。
💻 核心代码与原理补充讲解
以下是对上述 28 步操作所依赖的 核心代码 和 编程知识 的详细解读。
I. ⭐️ Unity 脚本生命周期与交互函数
理解这些函数是 Unity 编程的基石。
| 函数 | 归属 (LifeCycle) | 作用与项目应用 |
|---|---|---|
FixedUpdate() | 物理 | 用于物理! 固定间隔调用,保证施加力 (rb.AddForce) 的稳定性。 |
Update() | 逻辑 | 用于输入! 每帧调用,监听 Input.GetKeyDown() 等按键操作。 |
OnCollisionEnter() | 碰撞 (实体) | 用于落地! 检测两个 非触发器 碰撞,如玩家与地面。 |
OnTriggerEnter() | 触发 (区域) | 用于终点! 检测进入一个 Is Trigger 区域,如终点线。 |
Time.timeScale | 全局控制 | 控制游戏时间流速。设为 为慢动作,设为 为正常速度。 |
II. 🕹️ 玩家控制与交互代码
这段代码实现了步骤 5、12、13、14 中要求的最核心的功能。
// PlayerMovement.cs
void FixedUpdate() // [对应步骤 5]:处理物理移动
{
rb.AddForce(0, 0, Input.GetAxis("Vertical") * forwardForce * Time.deltaTime);
}
void Update() // [对应步骤 12]:处理跳跃输入
{
if (isGrounded && Input.GetKeyDown(KeyCode.Space))
{
rb.AddForce(Vector3.up * jumpForce, ForceMode.Impulse);
isGrounded = false;
audioSource.PlayOneShot(jumpSound); // [对应步骤 27]:播放音效
}
}
private void OnCollisionEnter(Collision collision) // [对应步骤 13]:落地检测
{
// 检查是否为地面 Tag,如果是,则设置 isGrounded 状态
if (collision.gameObject.tag == "Ground")
{
landingSmoke.Play(); // [对应步骤 26]:播放落地特效
isGrounded = true;
}
}
private void OnTriggerEnter(Collider other) // [对应步骤 14]:终点检测
{
if (other.gameObject.tag == "FinishLine")
{
rb.isKinematic = true;
gameController.GameWon();
}
}
III. ⚙️ 流程控制与计时代码
这段代码实现了步骤 19、21、25 和 24 中要求的流程管理和计时功能。
using UnityEngine.SceneManagement;
// GameController.cs
void Update()
{
// [对应步骤 21]:R 键快速重启检测
if (Input.GetKeyDown(KeyCode.R))
{
RestartGame();
}
}
public void RestartGame() // [对应步骤 19]:实现场景重启
{
// 关键:在重启前将时间流速重置为正常速度
Time.timeScale = 1f;
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
public void DoSlowMotion() // [对应步骤 25]:实现慢动作
{
// 将 Time.timeScale 设为 0.1 实现慢动作
Time.timeScale = 0.1f;
}
// GameTimer.cs
void Update()
{
// [对应步骤 24]:计算和格式化时间
float t = Time.time - startTime;
string minutes = Mathf.Floor(t / 60).ToString("00");
string seconds = (t % 60).ToString("00.00");
timerText.text = minutes + ":" + seconds;
}