Unity 3D 漫游终极教程:从零开始打造沉浸式体验
漫游是游戏、建筑可视化、虚拟现实等领域中非常核心的功能,本教程将带你一步步掌握 Unity 中实现漫游的各种技术。

目录
- 第一部分:基础概念与准备工作
- 1 什么是漫游?
- 2 核心组件介绍
- 3 场景搭建基础
- 第二部分:第一人称漫游
- 1 创建玩家角色
- 2 实现角色移动
- 3 实现视角旋转
- 4 整合与优化
- 第三部分:第三人称漫游
- 1 创建角色与相机
- 2 实现角色移动
- 3 实现相机跟随
- 4 整合与优化
- 第四部分:自动漫游/路径漫游
- 1 使用
Navmesh实现自动寻路 - 2 使用
Waypoints实现路径漫游
- 1 使用
- 第五部分:进阶技巧与优化
- 1 添加交互功能
- 2 音效与背景音乐
- 3 性能优化
- 4 输入管理
第一部分:基础概念与准备工作
1 什么是漫游?
漫游指的是用户可以在一个三维虚拟环境中自由地移动、观察和探索,核心是控制和视角。
2 核心组件介绍
在开始之前,你需要了解几个核心组件:
Transform: 所有 GameObject 的基础组件,定义了物体的位置、旋转和缩放,这是最最核心的组件。Rigidbody(刚体): 使物体受物理影响,如重力、碰撞,对于玩家角色,通常需要它来实现真实的物理反馈。Collider(碰撞体): 定义物体的物理形状,用于检测碰撞和触发事件,常用Box Collider(盒型碰撞体) 或Capsule Collider(胶囊碰撞体)。CharacterController(角色控制器): Unity 提供的一个专门用于角色移动的组件,它内置了移动、重力、碰撞检测等功能,比手动用Rigidbody更简单。Camera(相机): 玩家的“眼睛”,你可以控制相机的位置和旋转,来改变玩家的视角。Animator(动画器): 用于控制角色的动画,如行走、跑步等。
3 场景搭建基础
- 创建新项目: 打开 Unity Hub,创建一个新的 3D 项目。
- 导入资源: 你可以从 Unity Asset Store 导入一些免费的 3D 模型(如
Standard Assets)或自己创建一些简单的几何体(如 Cube, Plane)来搭建一个测试场景。 - 创建地面: 创建一个
Plane(平面),作为地面。 - 创建墙壁: 创建几个
Cube(立方体),调整它们的位置和大小,搭建出简单的墙壁。 - 创建玩家: 我们将在下一步创建。
第二部分:第一人称漫游
这是最经典的漫游方式,玩家通过角色的眼睛来观察世界。
1 创建玩家角色
- 在
Hierarchy窗口,右键 ->3D Object->Capsule,这将作为我们的玩家模型。 - 选中这个
Capsule,在Inspector窗口将其Tag设置为Player。 - 添加相机: 在
Hierarchy窗口,右键Capsule->Camera,这样相机就成为了Capsule的子对象,会随着胶囊一起移动。 - 调整相机位置: 选中
Main Camera,调整其Position为(X: 0, Y: 0.7, Z: 0),Rotation为(X: 0, Y: 0, Z: 0),这样相机就位于角色的头部高度。 - 隐藏胶囊模型: 选中
Capsule,取消勾选Mesh Renderer组件,因为我们不需要看到它,我们只通过相机看世界。
2 实现角色移动
我们将使用 CharacterController 组件,因为它非常简单且效果不错。

- 选中
Capsule(玩家),点击Add Component,添加Character Controller。 - 调整
Character Controller的参数:Center:(0, 0.9, 0)(让控制器中心在角色脚下)Radius:2Height:8
- 创建一个新的 C# 脚本,命名为
FirstPersonMovement。 - 将脚本拖拽到
Capsule(玩家) 上。 - 打开脚本,编写以下代码:
using UnityEngine;
public class FirstPersonMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 6f;
void Update()
{
// 获取水平和垂直输入 (WASD 或 方向键)
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
// 计算移动方向
Vector3 move = transform.right * horizontal + transform.forward * vertical;
// CharacterController 的 SimpleMove 函数会自动应用重力
controller.SimpleMove(move * speed);
}
}
- 代码解释:
Input.GetAxis("Horizontal")获取 A/D 或 左/右方向键的输入值(-1 到 1)。Input.GetAxis("Vertical")获取 W/S 或 上/下方向键的输入值。transform.right和transform.forward是基于角色当前朝向的右前方向量,这样移动方向就是角色面向的方向,而不是世界坐标的固定方向。controller.SimpleMove()会自动应用重力,并确保移动时不会穿过其他物体。
3 实现视角旋转
这个脚本将控制相机的上下左右旋转。
- 创建一个新的 C# 脚本,命名为
MouseLook。 - 将脚本拖拽到
Main Camera上。 - 打开脚本,编写代码:
using UnityEngine;
public class MouseLook : MonoBehaviour
{
public float mouseSensitivity = 100f;
public Transform playerBody; // 需要拖拽玩家胶囊体到这里
private float xRotation = 0f;
void Start()
{
// 锁定鼠标光标
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
// 获取鼠标输入
float mouseX = Input.GetAxis("Mouse X") * mouseSensitivity * Time.deltaTime;
float mouseY = Input.GetAxis("Mouse Y") * mouseSensitivity * Time.deltaTime;
// 控制相机上下旋转 (俯仰)
xRotation -= mouseY;
xRotation = Mathf.Clamp(xRotation, -90f, 90f); // 限制视角不能翻转过头
transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f);
// 控制玩家左右旋转 (偏航)
playerBody.Rotate(Vector3.up * mouseX);
}
}
- 代码解释:
- 在
Inspector窗口中,你需要将Capsule(玩家) 拖拽到Mouse Look脚本的Player Body字段里。 Cursor.lockState = CursorLockMode.Locked;会将鼠标光标锁定在屏幕中央,实现无边界旋转。mouseX控制整个玩家物体的旋转,实现左右转头。mouseY控制相机自身的旋转,实现上下看。Mathf.Clamp用于限制视角,避免“托马斯全旋”。
- 在
4 整合与优化
你的第一人称漫游系统已经基本完成了!运行游戏,你就可以用 WASD 移动,用鼠标控制视角了。
第三部分:第三人称漫游
第三人称漫游可以看到自己的角色模型,并且相机通常会跟随在角色后方。
1 创建角色与相机
- 创建角色: 创建一个
Capsule或导入一个 3D 角色模型,设置Tag为Player。 - 创建相机: 创建一个空的
GameObject,命名为ThirdPersonCamera,这个物体将作为相机的父节点,方便我们控制相机围绕角色旋转。 - 在
ThirdPersonCamera下创建一个Main Camera。 - 调整
ThirdPersonCamera的位置,(0, 2, -5),这表示相机在角色后方5米,上方2米的位置。 - 调整
Main Camera的Rotation为(0, 0, 0),让它看向角色。
2 实现角色移动
移动逻辑和第一人称类似,但相机控制不同。

- 为角色添加
CharacterController。 - 创建一个
ThirdPersonMovement脚本,代码与FirstPersonMovement基本相同,但不需要引用相机。
// ThirdPersonMovement.cs (代码与 FirstPersonMovement.cs 几乎一样)
using UnityEngine;
public class ThirdPersonMovement : MonoBehaviour
{
public CharacterController controller;
public float speed = 6f;
void Update()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 move = transform.right * horizontal + transform.forward * vertical;
controller.SimpleMove(move * speed);
}
}
3 实现相机跟随
这是第三人称的核心,相机需要平滑地跟随角色,并能通过鼠标控制围绕角色旋转。
- 创建一个
ThirdPersonCameraController脚本。 - 将脚本拖拽到
ThirdPersonCamera这个空物体上。 - 打开脚本,编写代码:
using UnityEngine;
public class ThirdPersonCameraController : MonoBehaviour
{
public Transform player; // 拖拽玩家角色到这里
public float distance = 5.0f;
public float height = 2.0f;
public float smoothSpeed = 0.125f;
public float mouseSensitivity = 2.0f;
private float currentX = 0.0f;
private float currentY = 0.0f;
void Start()
{
Cursor.lockState = CursorLockMode.Locked;
}
void Update()
{
// 获取鼠标输入来旋转相机
currentX += Input.GetAxis("Mouse X") * mouseSensitivity;
currentY -= Input.GetAxis("Mouse Y") * mouseSensitivity;
currentY = Mathf.Clamp(currentY, -30f, 60f); // 限制上下旋转角度
}
void LateUpdate()
{
// 计算目标位置
Vector3 desiredPosition = player.position;
desiredPosition += Quaternion.Euler(currentY, currentX, 0) * new Vector3(0, height, -distance);
// 平滑移动相机
transform.position = Vector3.Lerp(transform.position, desiredPosition, smoothSpeed);
transform.LookAt(player.position + new Vector3(0, height/2, 0)); // 让相机看向角色的上半身
}
}
- 代码解释:
Update()函数处理鼠标输入,计算相机的水平(currentX)和垂直(currentY)旋转角度。LateUpdate()在所有Update()执行完后运行,是更新相机位置的绝佳时机,可以避免抖动。desiredPosition根据玩家的位置、鼠标偏移量和预设的distance、height计算出相机应该在的目标位置。Vector3.Lerp实现相机的平滑跟随,而不是瞬间移动。transform.LookAt()让相机始终看向角色。
4 整合与优化
将 ThirdPersonCameraController 脚本中的 Player 字段拖拽到你的角色模型上,运行游戏,你就可以用 WASD 移动,用鼠标控制视角了。
第四部分:自动漫游/路径漫游
当需要制作演示或特定路径的探索时,自动漫游非常有用。
1 使用 Navmesh 实现自动寻路
这是最灵活的方式,AI 可以自动避开障碍物。
- 烘焙 Navmesh:
- 选中你的地面和所有静态障碍物(墙壁等),在
Inspector中勾选Navigation Static。 - 点击顶部菜单
Window->Navigation,打开导航窗口。 - 在
Baking标签页,点击Bake按钮,Unity 会生成一个蓝色的导航网格。
- 选中你的地面和所有静态障碍物(墙壁等),在
- 创建 AI 控制器:
- 创建一个
Capsule作为自动漫游的角色。 - 添加
Navmesh Agent组件。 - 创建一个
AutoRoamer脚本。
- 创建一个
using UnityEngine;
using UnityEngine.AI;
public class AutoRoamer : MonoBehaviour
{
public NavMeshAgent agent;
public Transform[] waypoints; // 在 Inspector 中手动设置路径点
private int currentWaypointIndex = 0;
void Start()
{
if (waypoints.Length > 0)
{
agent.SetDestination(waypoints[currentWaypointIndex].position);
}
}
void Update()
{
if (!agent.pathPending && agent.remainingDistance < 0.5f)
{
// 到达当前路径点,前往下一个
currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Length;
agent.SetDestination(waypoints[currentWaypointIndex].position);
}
}
}
- 使用方法:
- 在场景中创建几个空的
GameObject作为路径点,并调整它们的位置。 - 将这些路径点拖拽到
AutoRoamer脚本的Waypoints数组中。 - 运行游戏,胶囊体就会自动沿着路径点移动。
- 在场景中创建几个空的
2 使用 Waypoints 实现路径漫游
这是一种更简单、更直接的控制方式,不依赖 Navmesh。
using UnityEngine;
public class WaypointFollower : MonoBehaviour
{
public Transform[] waypoints;
public float speed = 2f;
private int currentWaypointIndex = 0;
void Update()
{
if (waypoints.Length == 0) return;
Transform targetWaypoint = waypoints[currentWaypointIndex];
Vector3 moveDirection = (targetWaypoint.position - transform.position).normalized;
transform.Translate(moveDirection * speed * Time.deltaTime);
if (Vector3.Distance(transform.position, targetWaypoint.position) < 0.1f)
{
currentWaypointIndex = (currentWaypointIndex + 1) % waypoints.Length;
}
}
}
- 区别: 这种方式是直接
Translate移动物体,没有碰撞检测和路径寻找,适合简单的、无障碍的路径。
第五部分:进阶技巧与优化
1 添加交互功能
- 创建可交互物体: 创建一个物体,比如一个门或一个按钮。
- 添加脚本: 为这个物体添加一个
InteractableObject.cs脚本。
// InteractableObject.cs
using UnityEngine;
public class InteractableObject : MonoBehaviour
{
void OnMouseDown() // 当鼠标点击时触发
{
Debug.Log("你点击了: " + gameObject.name);
// 在这里添加交互逻辑,例如开门、拾取物品等
}
}
- 修改第一人称脚本: 在
MouseLook.cs中添加射线检测,以便在远处交互。
// 在 MouseLook.cs 的 Update() 函数中添加
if (Input.GetMouseButtonDown(0)) // 如果左键点击
{
Ray ray = Camera.main.ViewportPointToRay(new Vector3(0.5f, 0.5f, 0)); // 从屏幕中心发射射线
if (Physics.Raycast(ray, out RaycastHit hit))
{
// 检查击中的物体是否有 InteractableObject 组件
InteractableObject interactable = hit.collider.GetComponent<InteractableObject>();
if (interactable != null)
{
interactable.OnMouseDown(); // 调用交互方法
}
}
}
2 音效与背景音乐
- 导入音频文件: 将
.wav或.mp3文件拖入Project窗口。 - 创建 Audio Source: 为需要播放声音的物体(如玩家、场景)添加
Audio Source组件。 - 设置 Audio Clip: 在
Audio Source组件中,将你的音频文件拖到AudioClip字段。 - 播放音频: 你可以在脚本中通过
GetComponent<AudioSource>().Play()来控制播放。
3 性能优化
- LOD (Level of Detail): 为远处的模型创建不同精度的版本,减少渲染负担。
- Occlusion Culling (遮挡剔除): 在
Window->Rendering->Occlusion Culling中设置,让 Unity 自动不渲染被其他物体完全挡住的区域。 - 对象池: 对于频繁创建和销毁的对象(如子弹、特效),使用对象池技术可以极大提升性能。
4 输入管理
对于复杂的游戏,建议使用 Unity 的 Input System 包(在 Package Manager 中安装)来管理输入,这样可以将按键操作与代码解耦,方便后期修改键位。
本教程涵盖了 Unity 3D 漫游的核心技术:
- 第一人称: 适合 FPS 游戏、模拟器。
- 第三人称: 适合 RPG、动作冒险游戏。
- 自动漫游: 适合场景演示、预览。
从基础的移动和视角控制,到高级的寻路和交互,你已经掌握了构建一个完整漫游系统的能力,就是去实践、去创造属于你自己的精彩世界吧!祝你开发顺利!
