第 18 章 内置组件图鉴:想要什么效果,就挂什么组件
第 17 章讲了”组件是什么、为什么这么设计”。这一章给你一张实战字典——以后你脑子里冒出”我想让这个东西 XX”,直接查这张表:该挂哪个组件、调哪些参数、它本质上解决了什么现实问题。
记住这一章的元认知:先想”我要什么效果”,再查”挂什么组件”,最后调参数。不要先想”我该写个什么类”。 这是从”会写代码”到”会用引擎”的关键一跃。
18.0 怎么用这张图鉴
两种方式挂组件:
- 编辑器里选中物体 → Inspector 面板最下方 Add Component → 搜名字。
- 代码里
gameObject.AddComponent<AudioSource>()。
参数都在 Inspector 里实时可调,这也是为什么前面所有章节我都强调”理解参数”——你调的就是这些组件的字段。
下面按”效果/需求”分类。每条都标了:挂什么组件 → 关键参数 → 解决什么问题(连回你学过的概念章)。
18.1 想让物体”存在并能被定位” → Transform
- 组件:
Transform(强制拥有,删不掉) - 关键参数:Position / Rotation / Scale
- 解决什么:给物体一个世界里的”地址”(第 2 章)。没有它,物体没法渲染、没法算碰撞。
- 用法直觉:移动物体 = 改 Position;转向 = 改 Rotation;放大 = 改 Scale。
18.2 想让物体”被看见(有形状)” → MeshFilter + MeshRenderer
- 组件:
MeshFilter(指定用哪个网格数据)+MeshRenderer(负责把它画出来) - 关键参数:MeshFilter.Mesh(用哪个模型)、MeshRenderer.Material(用什么材质/贴图,第 5 章)
- 解决什么:第 4 章讲过,3D 物体是三角形网格。MeshFilter 决定”形状长啥样”,MeshRenderer 决定”怎么画出来、贴什么皮”。
- 特例:会动的人物/怪物用
SkinnedMeshRenderer(骨骼蒙皮),因为顶点会随骨骼变形。
18.3 想让物体”有体积、能被碰/被打中” → Collider
- 组件:
Collider家族——Box(盒子)、Sphere(球)、Capsule(胶囊)、Mesh Collider(贴着模型形状) - 关键参数:Size / Center(大小位置)、Is Trigger(是否只触发不挡)
- 解决什么:给物体一个”可被撞击的边界”。子弹打到敌人,本质是子弹的碰撞体和敌人的碰撞体”相交”了。
- 设计直觉:人用 Capsule(贴合身形又便宜),墙用 Box,地形可用 Mesh Collider。
18.4 想让物体”受物理(重力、被推、碰撞反弹)” → Rigidbody
- 组件:
Rigidbody - 关键参数:Mass(质量)、Drag(空气阻力)、Use Gravity(是否受重力)、Is Kinematic(是否不受物理控制,常用于电梯/平台)
- 解决什么:Collider 只管”形状”,Rigidbody 才让物体”听物理的话”。没有它,物体不会掉下去、不会被推开。
- 重要:Rigidbody 的移动要放在
FixedUpdate里,用AddForce/velocity,别直接改 Transform(会跟物理引擎打架)。
18.5 想让物体”动起来 / 沿路走” → 脚本 或 Animator 或 NavMeshAgent
- 组件 A(自定义):写脚本在
Update里改 Transform,适合简单移动(直线飞、上下浮)。 - 组件 B:
Animator播”走路”动画(只管动作表现,不管位移)。 - 组件 C:
NavMeshAgent(自动寻路)——给场景烘焙一张”可走地图”,Agent 会自动绕开障碍走到目标点。 - 解决什么:移动的”表现”(动画)和”寻路”(绕障)是两件事,分开挂。
- 塔防用法:怪物用 NavMeshAgent 沿路点走到基地;玩家控制的单位也用它避障。
18.6 想让物体”放光 / 照亮场景” → Light
- 组件:
Light - 关键参数:Type(Directional 平行光/Point 点光/Spot 聚光)、Color、Intensity(强度)、Range(照射范围)、Shadows(是否投影)
- 解决什么:第 6 章讲的”光照”就是它。Directional 像太阳(无尽远、平行),Point 像灯泡(向四周),Spot 像手电。
- 性能提醒:实时阴影很贵,室外大场景常用一个 Directional 光 + 烘焙(第 6 章讲过”提前算假光”)。
18.7 想让”玩家从某处看世界” → Camera
- 组件:
Camera(第 7 章) - 关键参数:Field of View(视野角,广角/长焦)、Near/Far Clip Plane(近/远裁剪面,这之外的不画)、Projection(透视/正交)
- 解决什么:决定”玩家看到什么、从哪看”。小地图、过场、画中画 = 多台 Camera 叠加。
- 联机注意:联机时每个客户端有自己的 Camera,但看到的”世界状态”由服务器同步(第 19 章)。
18.8 想”播放声音 / 听到位置声音” → AudioSource + AudioListener
- 组件:
AudioSource(播放器,挂在发声物体上)+AudioListener(耳朵,通常挂在摄像机上,第 12 章) - 关键参数:Clip(用哪段音频)、Volume、Pitch、Loop(循环)、Spatial Blend(2D↔3D)、Min/Max Distance(3D 衰减范围)
- 解决什么:AudioSource 是”唱片机”,AudioListener 是”人耳”。Spatial Blend 调到 3D 后,声音会随距离/方位衰减,远处怪的吼声自然变小。
- 联机用法:服务器同步物体的位置,客户端据此播放带 Spatial Blend 的音效——“声音从哪来”也是服务器说了算。
18.9 想”播放动画(走路/攻击/死亡)” → Animator + AnimationClip
- 组件:
Animator(状态机控制器)+AnimationClip(具体一段动画) - 关键参数:Animator Controller(状态切换图:Idle→Walk→Attack)、动画里的曲线
- 解决什么:把”动作”做成可切换的状态。攻击时切到 Attack 片段,播完回 Idle。
- 设计直觉:Animator 是个”状态机”——你写 Go 时用的状态机(比如订单状态流转),和这玩意是一个脑子。
18.10 想”做火焰 / 烟 / 爆炸 / 拖尾” → ParticleSystem
- 组件:
ParticleSystem - 关键参数:Emission(每秒喷多少粒子)、Shape(从什么形状喷出)、Color over Lifetime(一生颜色变化)、Size over Lifetime、Velocity
- 解决什么:用大量小粒子模拟流体/烟雾/火花。塔防里炮口火光、敌人死亡碎裂、技能特效都靠它。
- 效果设计心法:粒子是”氛围层”,不参与逻辑。它让画面”活”,但怪死没死由血量脚本定,不是由粒子定。
18.11 想”显示血条 / 按钮 / 文字” → Canvas + UI 组件
- 组件:
Canvas(UI 画布)+Image/Text/Button/Slider(血条) - 关键参数:Render Mode(屏幕空间/世界空间)、锚点(Anchor,适配不同分辨率)
- 解决什么:游戏里所有 2D 界面(菜单、血条、得分、聊天框)都是 UI 组件,和 3D 世界的渲染是两套体系。
- 联机用法:血条显示的数值来自服务器同步的 HP,UI 只负责”把数字画出来”。
18.12 想”自动寻路绕过障碍” → NavMeshAgent
- 组件:
NavMeshAgent+ 场景烘焙的 NavMesh(可走区域) - 关键参数:Speed、Stopping Distance、Path(自动算好的路径)
- 解决什么:不用你手写 A* 寻路,引擎帮你算”从 A 到 B 怎么绕开墙”。塔防怪寻路标配。
- 前提:要先在场景里”烘焙”NavMesh(标记哪里能走),Agent 才知道路。
18.13 想”两物体碰撞时触发逻辑” → Collider + 脚本回调
- 组件:
Collider(两个物体都要有;至少一个有 Rigidbody) - 脚本方法:
OnCollisionEnter(实打实撞上)/OnTriggerEnter(穿过触发区,Collider 勾了 Is Trigger) - 解决什么:子弹打中敌人、玩家踩到陷阱、进.trigger 区触发剧情——都是碰撞/触发回调。
- 区分:Collision 会物理弹开(有 Rigidbody),Trigger 像”感应区”不挡路(适合技能范围、出生点)。
18.14 想”联机同步这个物体” → Network 组件
- 组件:用 Unity Netcode for GameObjects 时:
NetworkObject(标识”这个物体归网络管”)+NetworkTransform(自动同步位置/旋转)+ 你自己的NetworkBehaviour(同步自定义逻辑) - 关键参数:Ownership(谁拥有这个物体)、Sync Mode(插值/预测)
- 解决什么:第 19 章要细讲。简单说,单机时物体状态只存在你机器;联机时,它的位置/血量要”广播”给其他玩家。这些 Network 组件就是干这个的。
- 你做塔防联机必碰:怪的位置、塔的建造、玩家的血量,都得通过这类组件或你自己的消息协议同步。
18.15 组合示例:一座”塔”、一颗”子弹”、一个”玩家”各要什么
把前面串起来,你做塔防时这三个核心物体,组件组合大概是:
塔(防御设施,固定)
Transform + MeshFilter + MeshRenderer + BoxCollider(范围检测用 Trigger)+ 自定义
TowerAttack(检测范围内敌人、定时开火)+ AudioSource(开火声)+ ParticleSystem(炮口火光)
子弹(飞行物)
Transform + MeshFilter + MeshRenderer + CapsuleCollider(Is Trigger)+ 自定义
BulletMove(直线飞)+ 自定义BulletHit(OnTriggerEnter 扣敌人血、销毁自己)
玩家(操作主体)
Transform + MeshFilter + MeshRenderer + CapsuleCollider + Rigidbody + 自定义
PlayerMove(输入控制移动)+ 自定义PlayerHP+ Camera(跟在身后或第一人称)+ AudioListener(耳朵)
你看,没有一个”塔类""子弹类""玩家类”把所有逻辑写死。全是组件拼装 + 少量自定义脚本。这就是第 17 章说的”组合优于继承”在真实项目里的样子。
18.16 设计心法:从”效果”反推”组件”
最后送你一条工作流,以后写任何功能都按这个来:
- 说人话:我要”敌人死亡时炸开一团火、播放惨叫、加分”。
- 拆效果:炸火 = ParticleSystem;惨叫 = AudioSource;加分 = 自定义脚本改分数。
- 查图鉴:上面三个组件分别挂哪、调什么参数。
- 拼起来:死亡事件触发时,同时启动粒子、播放音效、调分数。
- 调参数:火多大、声多响、分数多少——在 Inspector 里实时试。
你面试时被问”你怎么实现一个 XX 功能”,就用这套”效果→组件→参数”的回答,比背 API 强十倍,因为面试官听得出你懂设计意图。
反问:你玩过的游戏里,有没有哪个”效果”你现在能反推出它大概挂了哪些组件了?比如”角色脚下有个跟随的光圈""技能命中时屏幕闪一下”——试试拆一下。
【思考题】
- 怪物的”走路动画”和”沿路移动”为什么建议用不同组件(Animator vs NavMeshAgent)而不是一个搞定?如果只挂 Animator 不挂寻路,怪物会怎样?
- 同样是”两个物体碰到一起”,OnCollisionEnter 和 OnTriggerEnter 适用场景有什么不同?举一个塔防里该用 Trigger 的例子。
- 你说”塔防里炮口火光用 ParticleSystem,但怪死没死由血量脚本定”。这句话体现了什么设计原则?如果有人把”怪物是否死亡”的判断写进粒子系统里,会出什么问题?
- 用这一章的图鉴,拆解一个你熟悉的游戏效果(比如”玩家受伤时屏幕变红 + 角色变红 + 播放痛呼声”),列出涉及的组件和各自参数方向。
【参考答案】
- Animator 只管”动作表现”(腿在动),不管”位置怎么变”;NavMeshAgent 管”往哪走、绕开障碍”。只挂 Animator:角色会原地踢腿但永远到不了目的地;只挂寻路:能走到但像滑行没有走路动作。两者配合才是”一边走一边动”。这正体现”表现层”和”逻辑/寻路层”分离。
- Collision 是实打实物理碰撞(双方有 Rigidbody,会弹开、阻挡),适合”车撞墙""角色站在地上”。Trigger 是感应区(勾了 Is Trigger,不挡路,只通知”进入了”),适合”技能范围圈""出生点""塔的攻击范围检测”。塔防例子:塔的攻击范围用 Trigger 球形碰撞体,敌人进入就加入”可攻击列表”,不挡敌人路。
- 体现单一职责 + 逻辑与表现分离:粒子是”氛围层”,死亡是”逻辑层”,逻辑层决定状态,表现层只反映状态。若把死亡判断写进粒子:粒子只是视觉,可能被跳过/关掉,导致”看着没死但其实该死”或”粒子放完了却没真死”的诡异 bug,且逻辑耦合到表现,难维护、难联机同步。
- 拆解:“屏幕变红”= 一个全屏 UI Image(红色、半透明、淡出动画)挂在 Canvas 上;“角色变红”= 角色材质/Shader 的 color 或 emissive 临时变红(MeshRenderer.material 改色,计时恢复);“痛呼声”= AudioSource 播受伤音效(第 12 章 Spatial Blend 视情况)。三者由”受伤事件”统一触发,各自是独立组件,互不依赖——典型的”一个事件,多个表现”组合。