Unity3D学习笔记-跑酷练习

110 阅读4分钟

🎯 一、项目基础搭建与玩家核心(1-8 步)

这是项目的起点,主要目标是搭建场景和实现玩家的基本移动。

  1. 新建 3D 项目: 在 Unity Hub 中选择 "3D" 模板。
  2. 创建地面: 在 Hierarchy 中创建 3D Object -> Plane,并调整 Scale (10, 1, 10)
  3. 创建玩家: 创建 3D Object -> Cube,命名 Player,调整 Y 位置到 0.5
  4. 添加物理组件:Player 添加 Rigidbody 组件。
  5. 编写移动脚本: 创建 PlayerMovement.cs 并在 FixedUpdate 中使用 rb.AddForce
  6. 附加脚本:PlayerMovement.cs 拖拽到 Player 对象上。
  7. 配置摄像机: 调整 Main Camera 到玩家后上方,并编写 CameraFollow.cs 脚本在 LateUpdate 中跟随。
  8. 创建地面标签:Plane 对象设置 Tag: Ground,用于检测玩家落地。

🚧 二、关卡元素与交互实现(9-14 步)

此阶段目标是创建障碍、定义终点和失败区,并编写相应的交互逻辑。

  1. 创建障碍物: 创建 Cube,调整 Scale,不勾选 Is Trigger
  2. 创建终点线: 创建 Cube,命名 FinishLine勾选 Is Trigger
  3. 设置终点标签:FinishLine 设置 Tag: FinishLine
  4. 添加跳跃逻辑:PlayerMovement.cs 中实现 isGrounded 状态和 空格键 输入。
  5. 编写落地检测:PlayerMovement.cs 中实现 OnCollisionEnter 切换 isGrounded 状态。
  6. 编写触发逻辑:PlayerMovement.cs 中实现 OnTriggerEnter 检测终点。

🖥️ 三、UI 与流程管理(15-21 步)

引入用户界面、流程控制脚本,并实现游戏的胜利、失败、重启状态。

  1. 创建 UI Canvas: 右键 Hierarchy,选择 UI -> Text - TextMeshPro
  2. 创建胜利文本: 创建 WinText,默认隐藏 (禁用)
  3. 创建失败文本: 复制 WinTextGameOverText,默认隐藏 (禁用)
  4. 创建流程控制器: 创建空对象 GameManager,并附加 GameController.cs 脚本。
  5. 实现场景管理:GameController.cs 中实现 RestartGame() 函数 (使用 SceneManager)。
  6. 设置 Build Settings: File > Build Settings,将当前场景添加到 Scenes in Build
  7. 实现快速重启:GameController.csUpdate 中检测 R 键 调用 RestartGame()

🎨 四、高级效果与优化(22-28 步)

增加游戏的专业度和视觉吸引力,优化工作流程。

  1. 创建障碍预制件: 将一个障碍物 拖拽 到 Project 视图中的 Prefabs 文件夹。
  2. 复制障碍: 从 Prefabs 文件夹拖拽障碍物到场景中,快速搭建跑道。
  3. 实现计时器 UI: 创建 TimerText 放在屏幕上方,并附加 GameTimer.csGameManager
  4. 实现慢动作:GameController.cs 中实现 DoSlowMotion() (调整 Time.timeScale),在 GameOver 时调用。
  5. 实现落地特效: 创建 Effects -> Particle System,命名 LandingSmokeFX,作为 Player 子对象。
  6. 实现跳跃音效:Player 添加 Audio Source,并在 Jump() 函数中调用 audioSource.PlayOneShot()
  7. 完成最终引用: 在 Unity 编辑器的 Inspector 中,确保所有脚本(Player/Controller/Timer)之间所需的引用(如 winTextObject, gameController 等)都已正确拖拽关联。


💻 核心代码与原理补充讲解

以下是对上述 28 步操作所依赖的 核心代码编程知识 的详细解读。

I. ⭐️ Unity 脚本生命周期与交互函数

理解这些函数是 Unity 编程的基石。

函数归属 (LifeCycle)作用与项目应用
FixedUpdate()物理用于物理! 固定间隔调用,保证施加力 (rb.AddForce) 的稳定性。
Update()逻辑用于输入! 每帧调用,监听 Input.GetKeyDown() 等按键操作。
OnCollisionEnter()碰撞 (实体)用于落地! 检测两个 非触发器 碰撞,如玩家与地面。
OnTriggerEnter()触发 (区域)用于终点! 检测进入一个 Is Trigger 区域,如终点线。
Time.timeScale全局控制控制游戏时间流速。设为 0.10.1 为慢动作,设为 11 为正常速度。

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;
}