1. 从零上手 Unity:为什么第一个 3D 场景值得认真搭
很多人第一次打开 Unity 编辑器,看到满屏的面板、按钮和密密麻麻的菜单,第一反应是“这玩意儿从哪下手”。我当初也一样,下载完 Unity Hub、装好编辑器、新建了一个 3D 项目,然后对着一个空荡荡的 Scene 视图发了十分钟呆。后来才明白,Unity 的入门门槛其实不在“会不会写代码”,而在于你有没有真正理解编辑器这套操作逻辑和 3D 空间的基本概念。
这篇内容就是写给那些刚接触 Unity、想自己动手搭一个 3D 游戏场景但不知道从哪开始的朋友。我会把从编辑器操作、3D 坐标系统、GameObject 与组件的组织方式,到场景管理这一整套流程拆开来讲,每一步都配上我实际踩过的坑和总结出来的操作习惯。你不需要有任何 3D 建模基础,也不需要提前学 C# 脚本,只要跟着走一遍,就能在自己的 Unity 里搭出一个有地面、有物体、有光照、能自由浏览的 3D 场景。
为什么强调“第一个场景”要认真搭?因为 Unity 的核心工作流——场景(Scene)、游戏对象(GameObject)、组件(Component)——这三者的关系贯穿了整个引擎的使用过程。你后面做的角色控制、UI 交互、物理碰撞、动画播放,全部都是在这个框架上叠加的。如果一开始对“场景里放了什么”“对象上挂了什么组件”“坐标怎么算”这些事没有清晰的认知,后面遇到问题就只能靠猜。我见过太多人卡在“为什么我的物体掉下去了”“为什么光照不对”“为什么相机看不到东西”这类问题上,根源都在入门阶段没把基础概念理顺。
所以这篇内容的目标很明确:让你在 Unity 编辑器里,从零搭出一个结构清晰、可运行、可继续扩展的 3D 场景。适合完全没碰过 Unity 的新手,也适合之前跟着教程做过但没搞懂原理的朋友。我会尽量用“人话”解释每个操作背后的逻辑,让你不仅知道点哪个按钮,还知道为什么要这么点。
2. 编辑器操作:先把“工作台”摸熟再动手
2.1 认识 Unity 编辑器的五大核心面板
打开 Unity 编辑器之后,你会看到一堆面板挤在一起。别急着关掉或者乱拖,先搞清楚每个面板是干什么的。默认布局下,最重要的五个面板分别是:Hierarchy(层级)、Scene(场景)、Game(游戏)、Inspector(检查器)、Project(项目)。这五个面板构成了你在 Unity 里工作的基本闭环。
Hierarchy 面板列出当前场景里所有的 GameObject。你可以把它理解成“这个场景里有什么东西”的清单。新建一个 Cube、一盏灯、一个相机,都会出现在这里。Scene 面板是你的 3D 工作区,你在这里摆放物体、调整位置、旋转角度。Game 面板是相机实际看到的画面,也就是玩家最终看到的视角。Inspector 面板显示当前选中对象的详细信息,包括它的 Transform(位置、旋转、缩放)和挂载的所有组件。Project 面板则是你项目里所有资源的存放处,模型、贴图、材质、脚本、预制体都在这里。
我刚开始用的时候,经常把 Scene 和 Game 搞混,以为在 Scene 里看到的就是玩家看到的。实际上 Scene 面板是编辑视角,你可以自由飞行、缩放、旋转,而 Game 面板才是最终输出。这个区别在调相机的时候特别重要——你在 Scene 里把相机拖来拖去,Game 面板会实时反映相机看到的内容。
提示:如果不小心把面板布局搞乱了,可以在右上角菜单里选择 Window > Layouts > Default 恢复默认布局。这个操作我用了不下几十次,尤其是刚开始不熟悉的时候。
2.2 Scene 视图的导航操作:像玩游戏一样逛场景
在 Scene 视图里移动的方式和大多数 3D 软件类似,但 Unity 有一套自己的快捷键逻辑。按住鼠标右键不放,然后移动鼠标,可以旋转视角,就像你转头看四周一样。按住鼠标右键的同时按 W/A/S/D,可以像第一人称游戏一样前后左右移动。滚动滚轮可以拉近拉远。按住鼠标中键拖动可以平移视角。
这几个操作听起来简单,但实际用起来有个手感问题:移动速度。默认的飞行速度在场景小的时候还行,场景一大就慢得像蜗牛。你可以在按住右键移动的同时滚动滚轮来实时调整飞行速度,这个技巧在大型场景里特别有用。另外,选中一个物体后按 F 键,Scene 视图会自动聚焦到该物体上,这个操作在找东西的时候非常方便。
还有一个容易被忽略的操作:按住 Alt 键配合鼠标左键可以围绕当前选中物体旋转视角,配合中键可以平移,配合右键可以缩放。这套操作在调整物体相对位置的时候比自由飞行更精准。我个人的习惯是,大范围移动用右键+WASD,精细调整用 Alt+鼠标组合。
2.3 物体的基本操作:移动、旋转、缩放
在 Scene 里操作物体,核心就是三个动作:移动、旋转、缩放。Unity 左上角有一组工具按钮,分别对应这几个操作,快捷键分别是 W(移动)、E(旋转)、R(缩放)、T(矩形工具)、Y(综合工具)。选中一个物体后按 W,会出现三个箭头(红绿蓝),拖动箭头可以在对应轴上移动物体。按 E 会出现三个圆环,拖动圆环可以绕对应轴旋转。按 R 会出现三个方块,拖动方块可以缩放。
这里有个细节值得说:Unity 的坐标轴颜色是固定的,红色代表 X 轴,绿色代表 Y 轴,蓝色代表 Z 轴。这个颜色约定在整个引擎里都通用,记住之后看任何 3D 视图都能快速判断方向。另外,如果你觉得拖动箭头不够精确,可以直接在 Inspector 面板的 Transform 组件里手动输入数值。我在做精确对齐的时候,基本都是手动输入数值,拖动只用来做粗略调整。
注意:缩放操作尽量不要用非均匀缩放(比如 X 轴缩放 2,Y 轴缩放 1,Z 轴缩放 3),因为这会导致子物体的坐标计算出现奇怪的问题,尤其是涉及物理碰撞和光照的时候。如果确实需要非均匀缩放,建议在建模软件里处理好再导入。
3. 3D 坐标系统:理解 Unity 的空间逻辑
3.1 世界坐标与本地坐标的区别
Unity 使用的是左手坐标系,X 轴向右,Y 轴向上,Z 轴向前。这个和某些 3D 软件(比如 Blender 默认是 Z 轴向上)不一样,所以从其他软件转过来的人需要适应一下。在 Unity 里,你看到的每个物体都有一个 Transform 组件,里面显示的 Position 就是它在这个世界里的位置。
但这里有个关键概念:世界坐标(World Space)和本地坐标(Local Space)是两回事。世界坐标是物体在整个场景中的绝对位置,本地坐标是物体相对于它的父物体的位置。如果一个物体没有父物体,它的本地坐标就等于世界坐标。如果它有父物体,本地坐标就是相对于父物体的偏移量。
举个例子:你有一个空物体作为父物体,位置在 (0, 0, 0),然后你创建一个 Cube 作为子物体,把它的本地坐标设为 (2, 0, 0)。这时候 Cube 的世界坐标也是 (2, 0, 0)。但如果你把父物体移动到 (5, 0, 0),Cube 的世界坐标就变成了 (7, 0, 0),而它的本地坐标仍然是 (2, 0, 0)。这个逻辑在搭建复杂物体结构的时候非常重要,比如一个角色的手臂相对于身体的位置,就应该用本地坐标来管理。
3.2 坐标轴的实际应用:怎么快速定位物体
在实际操作中,我经常用坐标轴来快速定位物体。比如我要把地面放在场景正中央,就把地面的 Position 设为 (0, 0, 0)。我要在场景里放一排柱子,就固定 Y 和 Z 的值,只改 X 的值。这种“固定两个轴、只调一个轴”的做法在搭建场景时非常高效。
还有一个技巧:在 Inspector 里点击 Position 的某个数值框,然后上下拖动鼠标,可以快速调整数值。按住 Shift 拖动可以更精细地调整。这个操作比直接输入数字快,比拖动箭头精确。我在调整光照位置和相机角度的时候经常用这招。
另外,Unity 的坐标单位是“米”,但这个“米”是虚拟的,你可以自己定义比例。一般来说,一个角色的高度设为 1.8 到 2 个单位比较合适,门的高度设为 2 到 2.5 个单位,房间的墙壁高度设为 3 个单位左右。这些数值不是固定的,但保持一致性很重要,否则后面做物理模拟和相机控制的时候会很别扭。
3.3 旋转的表示:欧拉角与四元数
旋转在 Unity 里用两种方式表示:欧拉角(Euler Angles)和四元数(Quaternion)。Inspector 面板里显示的是欧拉角,也就是绕 X、Y、Z 三个轴的旋转角度,单位是度。这种方式直观易懂,但有个问题叫“万向节锁(Gimbal Lock)”,当两个轴的旋转角度接近 90 度时,会丢失一个旋转自由度。
四元数是 Unity 内部实际使用的旋转表示方式,它用四个数(x, y, z, w)来表示旋转,避免了万向节锁的问题。在脚本里操作旋转的时候,通常用 Quaternion 而不是欧拉角。但在 Inspector 里手动调整的时候,用欧拉角更方便。我的建议是:手动调整用欧拉角,写代码用 Quaternion,两者之间可以用Quaternion.Euler()和transform.eulerAngles互相转换。
提示:如果你在 Inspector 里旋转物体时发现数值跳变或者旋转方向不对,检查一下左上角的坐标模式是 Global(世界坐标)还是 Local(本地坐标)。切换这个模式会影响旋转和移动的参考系。
4. GameObject 与组件:Unity 的核心组织方式
4.1 GameObject 是什么:一个“空壳”加一堆组件
GameObject 是 Unity 里最基础的单位,场景里的每一个物体都是一个 GameObject。但 GameObject 本身其实是个“空壳”,它默认只带一个 Transform 组件,用来记录位置、旋转和缩放。真正让 GameObject 有功能的是挂在它上面的各种组件。
这个设计思路叫“组合优于继承”。在 Unity 里,你不会创建一个“玩家类”然后继承一堆东西,而是创建一个空的 GameObject,然后给它挂上需要的组件:一个 Mesh Renderer 让它显示模型,一个 Box Collider 让它有碰撞体积,一个 Rigidbody 让它受重力影响,一个自定义脚本让它响应键盘输入。需要什么就挂什么,不需要就移除,非常灵活。
我刚开始学的时候,总想着“这个物体是什么类型”,后来才转变思路为“这个物体需要什么功能”。这个思维转变很重要,因为它决定了你组织场景的方式。比如一个“可拾取的物品”,它可能同时是一个触发器、一个可旋转的模型、一个会播放音效的物体,这些功能分别由不同的组件实现,而不是由一个“物品类”全部包办。
4.2 常用组件详解:Transform、Mesh、Collider、Rigidbody
Transform 是每个 GameObject 都有的组件,负责位置、旋转、缩放。它不能删除,也不能替换。Mesh Filter 和 Mesh Renderer 配合使用,前者决定显示什么模型,后者决定怎么渲染(用什么材质、是否投射阴影等)。Collider 定义物体的碰撞形状,常见的有 Box Collider、Sphere Collider、Capsule Collider 和 Mesh Collider。Rigidbody 让物体受物理引擎控制,有了它物体才会受重力、会被力推动、会发生碰撞反弹。
这几个组件的组合方式决定了物体的行为。比如一个静态的地面,只需要 Mesh Filter + Mesh Renderer + Box Collider,不需要 Rigidbody,因为地面不会动。一个会滚动的球,需要 Mesh Filter + Mesh Renderer + Sphere Collider + Rigidbody,这样它才会受重力下落、会被推动。一个玩家角色,通常需要 Capsule Collider + Rigidbody + 自定义控制脚本,而且要把 Rigidbody 的旋转冻结,防止角色摔倒。
注意:Mesh Collider 虽然能精确匹配模型形状,但性能开销比基本 Collider 大很多,而且不能用于非凸(non-convex)的刚体碰撞。如果模型形状复杂但不是特别需要精确碰撞,用基本 Collider 组合近似就好。
4.3 组件的添加、移除与顺序调整
在 Inspector 面板底部有一个“Add Component”按钮,点击后可以搜索并添加组件。移除组件的话,点击组件右上角的三个点,选择 Remove Component。组件的顺序会影响执行顺序,尤其是多个脚本组件的时候,上面的脚本先执行。这个细节在做依赖管理的时候很重要,比如一个脚本需要在另一个脚本之前初始化。
我个人的习惯是,把最核心的组件放在最上面,比如 Transform 下面紧接着放控制脚本,然后是物理组件,最后是渲染相关的。这样在 Inspector 里查看的时候一目了然。另外,如果你经常需要给多个物体添加同一组组件,可以创建一个预制体(Prefab),把配置好的物体拖到 Project 面板里,以后直接拖出来用就行。
5. 场景管理:让场景结构清晰可维护
5.1 用空物体做“文件夹”:层级管理的艺术
场景一复杂,Hierarchy 面板就会变得乱七八糟。我的做法是用空物体(Create Empty)来做分类文件夹。比如创建一个空物体叫“Environment”,把地面、墙壁、树木都拖进去;创建一个叫“Lights”的空物体,把所有灯光放进去;创建一个叫“UI”的空物体,把界面元素放进去。这样 Hierarchy 面板就清爽多了,找东西也快。
空物体的 Position 最好设为 (0, 0, 0),这样它的子物体的本地坐标就等于世界坐标,不会因为父物体的偏移而产生困惑。如果确实需要偏移,记得在调整子物体的时候注意坐标模式是 Local 还是 Global。
5.2 场景的保存与多场景管理
Unity 的场景文件后缀是 .unity,保存在 Project 面板的 Assets 文件夹里。我建议在 Assets 下建一个 Scenes 文件夹,专门放场景文件。保存场景用 Ctrl+S,另存为用 Ctrl+Shift+S。养成随时保存的习惯,Unity 虽然比较稳定,但偶尔崩溃一下也不是没发生过。
对于大型项目,可以把不同关卡拆成不同场景,然后用 SceneManager 在运行时加载。但在入门阶段,一个场景就够了。等你的场景内容多到 Hierarchy 面板滚半天都滚不到底的时候,再考虑拆分。
5.3 场景中的光照与相机设置
新建 3D 项目时,Unity 会自动创建一个 Directional Light(平行光)和一个 Main Camera(主相机)。平行光模拟太阳光,它的旋转角度决定了光照方向。我一般把平行光的 Rotation 设为 (50, -30, 0) 左右,这样能产生比较自然的阴影。相机的默认位置是 (0, 1, -10),看向原点。如果你在场景里放了东西但 Game 面板里看不到,八成是相机的位置或朝向不对。
相机的 Clear Flags 默认是 Skybox,也就是显示天空盒。如果你想要纯色背景,可以改成 Solid Color。相机的 Field of View(视野角度)默认是 60 度,这个值在大多数情况下都合适,调大了会有鱼眼效果,调小了会显得视野狭窄。
提示:如果场景里的物体看起来太暗,检查一下 Window > Rendering > Lighting 里的环境光设置。默认的环境光强度可能不够,可以适当调高 Environment Lighting 的 Intensity。
6. 常见问题与排查技巧实录
6.1 物体不见了?先检查这几个地方
新手最常见的问题就是“我放了个物体但看不到”。排查顺序是这样的:首先看 Hierarchy 里有没有这个物体,如果没有,可能是没创建成功或者被删了。如果有,选中它,看 Inspector 里的 Position 是不是跑到了很远的地方。然后按 F 键聚焦,看 Scene 视图里能不能找到。如果 Scene 里能看到但 Game 里看不到,检查相机的位置和朝向,或者检查物体的 Layer 是否被相机的 Culling Mask 排除了。
还有一种情况是物体被其他物体挡住了,或者缩放变成了 0。检查 Scale 是不是 (0, 0, 0),如果是,改回 (1, 1, 1)。另外,如果物体的 Mesh Renderer 被禁用了(组件前面的勾选框没打勾),也不会显示。
6.2 光照不对劲?检查这几个参数
光照问题通常表现为物体太暗、太亮、阴影不对或者颜色偏了。首先检查平行光的 Intensity 和 Color,默认是白色、强度 1。然后检查物体的材质,Standard Shader 的 Metallic 和 Smoothness 参数会影响反光效果。如果阴影看起来很奇怪,检查平行光的 Shadow Type,软阴影(Soft Shadows)比硬阴影(Hard Shadows)更自然但性能开销稍大。
还有一个容易忽略的地方:物体的 Scale 如果是不均匀的,阴影可能会变形。另外,如果场景里有多个平行光,它们会叠加,导致过亮。一般来说,一个场景一个平行光就够了,其他光源用点光源或聚光灯。
6.3 场景卡顿?可能是这几个原因
在编辑器里操作卡顿,通常是因为场景里的物体太多、面数太高,或者 Scene 视图的渲染质量设置太高。可以尝试在 Scene 视图左上角的菜单里把 Shading Mode 改成 Shaded Wireframe 或者 Wireframe,减少渲染负担。另外,如果场景里有大量使用 Mesh Collider 的物体,也会导致卡顿,可以考虑换成基本 Collider。
还有一个常见原因是编辑器本身的设置。在 Edit > Preferences > General 里,把 Auto Refresh 关掉,可以避免每次修改脚本后自动重新编译导致的卡顿。需要刷新的时候手动按 Ctrl+R 就行。
6.4 常见问题速查表
| 问题现象 | 可能原因 | 解决方法 |
|---|---|---|
| 物体在 Scene 里可见但 Game 里不可见 | 相机位置/朝向不对,或 Layer 被排除 | 调整相机 Transform,检查 Culling Mask |
| 物体不受重力影响 | 没有 Rigidbody 组件 | 添加 Rigidbody,确认 Use Gravity 已勾选 |
| 物体穿模 | Collider 太小或没有 Collider | 调整 Collider 大小,或添加合适的 Collider |
| 阴影不显示 | 光源 Shadow Type 设为 None,或质量设置太低 | 修改光源阴影设置,检查 Quality Settings |
| 材质显示为粉色 | Shader 编译错误或材质丢失 | 重新指定 Shader,或检查材质引用 |
| 场景保存后重新打开丢失内容 | 没有保存场景,或保存到了错误的场景文件 | 确认 Ctrl+S 保存,检查 Scenes 文件夹 |
提示:Unity 的 Console 面板(Window > General > Console)会显示错误和警告信息。遇到问题时先看 Console,很多问题那里会直接告诉你原因。
7. 我的实操心得与避坑建议
7.1 养成好习惯:命名规范与层级整理
我刚开始做项目的时候,Hierarchy 里全是“Cube (1)”“Cube (2)”“GameObject”这种名字,过两天自己都忘了哪个是哪个。后来强迫自己养成命名习惯:地面叫“Ground”,玩家叫“Player”,灯光叫“Main Light”,空物体分类叫“_Environment”这种带下划线前缀的,方便排在前面。这个习惯在项目变大之后能省下大量找东西的时间。
层级整理也是同理。每创建几个物体就顺手拖到对应的空物体下面,不要等到最后再整理。我现在的做法是,创建任何物体之前先想好它属于哪个分类,直接创建在对应的父物体下面。这样 Hierarchy 面板永远保持清晰。
7.2 善用预制体:一次配置,多处复用
预制体(Prefab)是 Unity 里非常强大的功能。你把一个配置好的物体拖到 Project 面板里,它就变成了一个预制体。以后需要同样的物体,直接从 Project 面板拖到 Scene 里就行,所有组件和参数都会自动带上。如果你修改了预制体的源文件,所有场景里的实例都会同步更新。
我在搭场景的时候,会把重复出现的物体都做成预制体,比如路灯、树木、箱子。这样不仅搭建速度快,后期调整也方便——改一个预制体,场景里所有实例一起变。需要注意的是,如果你在场景里单独修改了某个实例的属性,这个修改会覆盖预制体的设置,变成“覆盖(Override)”。如果想让修改同步到所有实例,要在 Inspector 里点击 Overrides > Apply All。
7.3 版本管理:别等丢了才后悔
Unity 项目一定要用版本管理工具,Git 也好,SVN 也好,哪怕只是定期手动备份整个项目文件夹。我吃过亏,有一次场景文件损坏,没有备份,一整天的活白干了。Unity 项目里有很多二进制文件,Git 默认的合并方式不太适合,建议配置 Git LFS 来管理大文件,或者在 Unity 的 Package Manager 里安装 Version Control 插件。
另外,Unity 项目里的 Library 文件夹和 Temp 文件夹不需要纳入版本管理,它们是可以自动生成的。需要管理的是 Assets、ProjectSettings 和 Packages 这三个文件夹。
7.4 性能意识:从第一个场景就开始培养
虽然入门阶段不用太纠结性能优化,但有些习惯从一开始就养成比较好。比如,不要滥用实时阴影,能烘焙的就烘焙;不要给静态物体加 Rigidbody;不要用太高的模型面数;材质尽量复用而不是每个物体一个新材质。这些习惯在场景小的时候看不出差别,但场景一大,性能差距就出来了。
我个人的经验是,在搭场景的时候经常打开 Stats 面板(Game 视图右上角的 Stats 按钮),看看 Draw Calls 和 Tris 的数量。如果 Draw Calls 超过几百,就说明该合并材质或者做批处理了。入门阶段保持在 100 以内比较理想。
7.5 学习路径建议:下一步该学什么
搭完第一个场景之后,下一步通常是学 C# 脚本,让物体动起来。我的建议是先学 Transform 的基本操作(移动、旋转、缩放),然后学 Input 类获取键盘鼠标输入,再学 Rigidbody 的力和速度控制。这几个知识点覆盖了大多数基础交互。之后再学碰撞检测、触发器和 UI 系统。
不要一上来就想着做完整的游戏,先把每个小功能单独跑通,再组合起来。比如先做一个“按 WASD 移动的方块”,再做一个“碰到就消失的硬币”,再做一个“显示分数的 UI”,最后把它们拼在一起。这种“积木式”的学习方式比直接啃一个大项目要高效得多。
提示:Unity 官方文档和 Unity Learn 平台上有大量免费教程,但不要贪多,选一个跟着做完再选下一个。我见过太多人收藏了一堆教程但一个都没做完,最后什么都没学会。
8. 场景搭好了,接下来怎么继续扩展
第一个 3D 场景搭完之后,你其实已经掌握了 Unity 最核心的工作流:在 Scene 里摆放物体,在 Inspector 里配置组件,在 Hierarchy 里管理结构,在 Project 里管理资源。这套流程在你后面做任何 Unity 项目的时候都会反复用到,只是复杂度不同而已。
我个人的体会是,Unity 入门最难的不是某个具体操作,而是建立“场景-对象-组件”这套思维模型。一旦你习惯了用组件的视角去看待物体,很多问题就变得很直观了——物体不动?看看有没有 Rigidbody。物体不显示?看看有没有 Mesh Renderer。物体穿模?看看 Collider 对不对。这种“对症下药”的排查思路,比死记硬背操作步骤有用得多。
如果你已经跟着走完了这一遍,建议你关掉教程,自己从头再搭一个类似的场景,这次不放 Cube,放几个不同的几何体,调整不同的材质颜色,加几盏不同颜色的灯,看看效果有什么变化。这种“玩”的心态比“学”的心态更容易让人记住东西。等你觉得这个场景已经没什么可玩的了,就可以开始写脚本让它动起来了。