本篇核心知识点:Unity 场景与游戏物体 GameObject 组件Component 概念、高速运动物体穿模问题、摄像机、光线、刚体与碰撞体、Transform 组件(位置 / 旋转 / 缩放)、父子层级关系、本地坐标 & 世界坐标、物体四种查找方式(名称 / 标签 / 层级遍历)、代码动态设置父物体、坐标转换基础
一、Unity 核心基础概念:场景、GameObject游戏物体、Component组件
1 场景(Scene)
概念
Scene 是 Unity 工程的独立关卡 / 页面容器,所有游戏内容都存放在场景内,项目可创建多个场景(登录、大厅、战斗),通过SceneManager切换。
特性
-
编辑器层级面板(Hierarchy)展示当前场景所有物体;
-
未激活物体(取消勾选)仍存在场景,只是画面不可见;
-
每个场景独立资源、独立物体层级,切换场景默认销毁非常驻物体。
2 GameObject 游戏物体
概念
场景内所有可见 / 不可见对象统称 GameObject(UI、3D 模型、摄像机、空物体都属于),空物体无渲染,仅用于层级分组 。实际就是一个容器,用于存放Component组件。
核心标配组件:Transform
所有 GameObject 创建时自动挂载 Transform,无法删除;控制物体三维核心属性:
-
Position:坐标位置
-
Rotation:旋转(欧拉角,Z 轴 2D 平面旋转、X/Y 控制 3D 俯仰)
-
Scale:缩放倍数
3 Component 组件
基础组件(引擎原生底层组件,无业务逻辑)
Unity 引擎内置、不继承 Mono、承载底层硬件 / 渲染 / 物理能力,是所有功能的载体,只负责数据与底层运算,不含游戏逻辑。
代表:
Transform、MeshFilter、MeshRenderer、Camera、Rigidbody、BoxCollider、Light、AudioSource、SpriteRenderer、ParticleSystem 等。
特点:
-
引擎原生自带,无需编写;
-
只提供基础能力:空间变换、渲染、碰撞、物理、音效;
-
不能写游戏规则,只能被脚本读取 / 控制参数。
模块功能组件(业务功能单元,独立可复用 Mono 脚本)
单一功能独立封装,只完成一件事,高内聚、低耦合,可单独挂载、重复复用,属于中层功能模块。
代表:
子弹移动脚本、巡逻 AI 脚本、鼠标瞬移脚本、相机滚轮缩放、圆周运动脚本、伤害判定、拾取道具、门开关逻辑。
特点:
-
继承 MonoBehaviour,C# 自定义脚本;
-
单一职责:一个脚本只实现一套完整独立功能;
-
不跨模块耦合,不直接操控其他系统,仅对外暴露变量 / 方法;
-
可直接拖给任意物体单独运行。
高层胶水代码(统筹调度、模块整合,控制器 / 入口脚本)
作为上层调度器,不实现具体运动、AI、渲染逻辑,只负责串联多个功能模块、处理输入、分发指令、管理状态,粘合各个独立功能组件。
代表:
PlayerInput 玩家总控脚本、GameManager 游戏管理器、BattleManager 战斗管理器、主相机总控制器。
特点:
-
持有多个模块组件引用(巡逻、射击、缩放、移动脚本);
-
处理全局输入、切换游戏状态、调用下层功能方法;
-
自身无底层运动 / 渲染实现,仅做逻辑调度;
-
全局唯一 / 单例居多,统筹整个模块系统。
分层关系示例(玩家角色)
-
基础组件:Transform、CapsuleCollider、Rigidbody、MeshRenderer
-
模块功能组件:BulletShoot(射击)、PatrolAI(巡逻)、CameraZoom(相机缩放)
-
高层胶水代码:PlayerMain(总控)
读取鼠标 / 键盘输入;
调用 BulletShoot.Fire () 发射子弹;
控制 CameraZoom 滚轮缩放;
切换 PatrolAI 启停巡逻。
拓展
高速运动物体穿模
概念:物体单帧移动距离超过碰撞体厚度,物理引擎仅在帧末做一次碰撞检测,直接跳过中间碰撞区域,穿透墙体 / 地面。
典型场景:高速子弹、冲刺角色、高速飞行器。
解决方案(从简单到专业)
1. 开启连续碰撞检测 CCD(Rigidbody 自带,最常用)
适用:带 Rigidbody 的高速物理物体
-
选中物体 Rigidbody 组件
-
Collision Detection(碰撞检测模式)切换:
Discrete 离散(默认,高速必穿)
Continuous 连续动态:高速物体,和静态地形检测
Continuous Dynamic 连续动态 + 动态:高速物体 vs 其他高速移动物体
原理:运动区间内做射线扫描,不会跳过碰撞层。
2. 运动时发射射线 / 胶囊扫描(无刚体、子弹弹道)
物体移动前,从上一帧位置 → 当前帧位置发射射线 / 胶囊检测,中途碰到碰撞体就拦截,限制位置。
核心函数:
Physics.Raycast 射线
Physics.CapsuleCast 胶囊扫描(适配角色)
Physics.SphereCast 球体扫描(子弹)
Vector3 prevPos = transform.position;
transform.position += moveDir * speed * Time.deltaTime;
// 补检测中间路径
if(Physics.Raycast(prevPos, transform.position - prevPos, out hit)){
transform.position = hit.point; // 停在碰撞点,不穿透
}
3. 缩小单帧移动步长(分段步进移动)
速度极快时,把一帧位移拆成多小段,每段都做碰撞检测,避免一步跨太厚碰撞体。
4. 扩大碰撞体尺寸
轻微提速场景,加厚 Collider,降低 "一步跨过去" 概率,治标不治本。
5. 调高物理引擎帧率(Project Settings → Time)
Fixed Timestep 数值改小(默认 0.02,改成 0.01)
物理更新更频繁,每帧移动距离缩短,代价:性能消耗上升。
总结
-
子弹、投射物:SphereCast 球体扫描
-
高速角色、怪物:Rigidbody → Continuous Dynamic + CapsuleCast
-
高速飞行器、动态互撞物体:开启 Continuous Dynamic CCD
-
性能低配小游戏:分段步进移动 + 加厚碰撞体
二、摄像机(Camera)
1 摄像机概念
Camera 摄像机是 Unity 的核心渲染组件,相当于游戏的"眼睛",负责将三维场景画面投射为二维屏幕图像,所有游戏可视画面均由摄像机渲染生成。一个场景可存在多台摄像机,分别渲染远景、UI、特效、倒影等画面。
投影分为正交和透视,视觉效果分别是3D和2D
2 摄像机核心属性
Clear Flags 清除标记
作用:控制每帧渲染前屏幕残留内容的清除方式
Skybox:默认模式,清空画面并填充天空盒,主相机常用
Solid Color:清空画面并填充纯色背景
Depth Only:只清空深度信息,保留颜色,用于叠加相机(UI相机、特效相机)
Don't Clear:不清除任何内容,画面叠加,极少用
Culling Mask 遮挡层
作用:选择性渲染指定层级的物体,过滤不需要显示的对象
原理:相机只渲染勾选 Layer 的物体,可实现 3D场景、UI、特效分层渲染分离
Projection 投影模式
Perspective 透视投影(默认)
近大远小,符合人眼视觉,用于3D游戏场景、角色、地形
Orthographic 正交投影
无近大远小,物体尺寸恒定,用于2D游戏、UI、地图、编辑器视图
Field Of View / Size 视野
透视相机:Field Of View 视野角度,数值越大画面越广、物体越小
正交相机:Size 控制可视范围大小
Clipping Planes 裁剪平面
Near 近裁剪面:距离相机过近的物体直接裁剪不渲染
Far 远裁剪面:距离相机过远的物体直接裁剪不渲染
Unity 相机核心能力:实现世界坐标、屏幕坐标、视口坐标互相转换,适配鼠标拾取、UI跟随、屏幕适配、射线检测功能。
核心转换API
视口 → 世界:ViewportToWorldPoint(必须指定深度Z)
原理:从相机镜头位置,穿过鼠标屏幕点发射一条无限长射线,配合物理碰撞检测,实现点击地面、物体拾取、瞬移功能。
通过鼠标滚轮增量,修改相机相对目标的偏移向量长度,方向不变、只改变距离,实现拉近拉远效果
\4. 配合 Clear Flags 防止底层画面残留闪烁。
物体远处消失
解决:使用渲染场景的主相机、转换世界坐标必须赋值Z深度
三、光线(Light)
1 光线概念
Light 灯光是 Unity 的核心渲染组件,负责模拟场景光照、物体明暗、阴影、色彩氛围,决定游戏画面的亮度与质感。场景可以创建多个灯光,灯光叠加形成整体光照效果,没有灯光的场景物体默认漆黑。
灯光分为四种类型,分别模拟现实中的点光源、方向光、聚光灯、面光源,适配不同场景氛围。
2 灯光四种类型(Type)
Directional 方向光(太阳光):光线平行照射、无衰减、无范围限制,模拟太阳光、天光。整张场景均匀照亮,是场景主光源首选。支持全局阴影。
Point 点光源(灯泡):从一个点向四面八方发光,有球形照射范围,距离越远亮度越低,有光照衰减。模拟灯泡、火焰、室内小灯。
Spot 聚光灯(手电筒):锥形区域发光,有照射范围、角度限制,中心亮边缘暗。模拟手电筒、探照灯、舞台射灯。
Area 面光源(面光):矩形平面向一侧发光,仅烘焙有效,实时模式无效。模拟灯管、屏幕发光、橱窗灯带,用于静帧美化。
3 灯光核心属性
Intensity 强度
控制灯光亮度,数值越大场景越亮,可动态代码调光、闪灯、熄灯。
Color 灯光颜色
修改光线色调,用于氛围制作:暖光黄昏、冷光夜景、恐怖红光、科技蓝光。
Range 照射范围
仅点光源、聚光灯有效,控制灯光最大照射距离,超出范围无光照、无衰减。
Spot Angle 聚光角度
仅聚光灯有效,控制锥形照射区域大小,角度越大照射范围越宽。
Indirect Multiplier 间接光倍数
控制灯光反射、漫反射的亮度,影响环境整体柔和度。
4 阴影系统 Shadows
Shadow Type 阴影模式
No Shadows:关闭阴影,性能最高,画面扁平
Hard Shadows:硬阴影,边缘锐利、生硬,性能中等
Soft Shadows:软阴影,边缘模糊、真实柔和,性能开销最大
原理:灯光照射物体遮挡光线,地面/墙面形成投影,增强画面立体感。
5 光照两种模式
实时光照 Realtime
每帧实时计算光照,物体移动、灯光移动都能实时更新,支持动态场景,消耗性能较高。
烘焙光照 Baked
提前预计算光照信息,保存到光照贴图,场景运行不计算灯光,性能极高。只对静态物体生效,动态物体无法接收烘焙光影。
混合光照 Mixed
兼顾实时与烘焙,静态物体用烘焙光影,动态物体接收实时灯光。
6 灯光常见问题与解决
1. 场景整体漆黑、物体无光照
解决:缺少主方向光、灯光强度过低、物体设置为静态未烘焙
2. 动态物体没有阴影、不接光照
解决:动态物体只能接收实时光照,需将灯光设置为 Realtime 或 Mixed
3. 阴影锯齿、模糊、断层
解决:提升灯光阴影分辨率,开启软阴影,调整阴影距离
4. 游戏卡顿、帧率低
解决:减少实时光灯数量,静态场景全部使用烘焙光照,关闭不必要软阴影
四、刚体(Rigidbody)与碰撞体(Collider)
1 物理组件核心概念
Rigidbody(刚体)和 Collider(碰撞体)是 Unity 物理系统的两大核心组件,二者配合实现物体物理运动、碰撞检测、受力交互。物体想要参与物理模拟、发生碰撞、受重力影响,必须依赖这两个组件配合生效。
刚体负责物理运动与受力计算 ,碰撞体负责物理边界与碰撞判定,缺一不可。
2 Rigidbody 刚体核心属性
Mass 质量
控制物体物理重量,质量越大惯性越大,受力运动越缓慢,碰撞冲击力更强。默认数值为1,禁止设置为负数。
Drag 空气阻力
控制物体运动减速效果,数值越大物体停下越快,0为无空气阻力,适合自由落体运动。
Angular Drag 角阻力
控制物体旋转减速阻力,数值越大物体越难旋转、旋转后快速停稳。
Use Gravity 是否受重力
勾选后物体受场景重力影响自动下落,取消勾选物体悬浮不受重力。
Is Kinematic 是否为运动学刚体
默认关闭:动态刚体,受物理、重力、外力影响,可被碰撞推动。
开启后:不受物理引擎模拟,不受重力、外力影响,只能通过代码移动,可碰撞其他物体,常用于移动平台、机关、动画物体。
Constraints 冻结约束
冻结指定轴的位置或旋转,勾选后物体对应轴无法移动、无法旋转,常用于防止角色落地抖动、物体歪倒。
Collision Detection 碰撞检测模式
Discrete 离散检测(默认):常规检测,性能高,高速物体容易穿模。
Continuous 连续检测:高速静态碰撞,用于高速物体碰撞静态场景。
Continuous Dynamic 连续动态检测:高速互撞检测,高速物体碰撞动态物体,杜绝穿模,性能开销最大。
3 Collider 碰撞体核心概念与类型
碰撞体是物体的物理碰撞边界,隐形网格,不影响模型外观,仅用于物理判定。模型本身无碰撞能力,必须挂载碰撞体才能产生碰撞、触发、阻挡效果。
基础规则
两个物体发生碰撞的必要条件:双方均有碰撞体,至少一方带有刚体。
常用碰撞体类型
Box Collider 盒碰撞体:立方体碰撞区域,适配方形、矩形物体,场景最常用。
Sphere Collider 球碰撞体:球形碰撞区域,适配球体、角色头部、小型道具。
Capsule Collider 胶囊碰撞体:圆柱+半球结构,适配人物、怪物、柱子,稳定性最高。
Mesh Collider 网格碰撞体 :贴合模型形状的精准碰撞,精度高、性能差,且两个网格碰撞体无法互相碰撞,仅适合静态模型。
4 碰撞体核心属性
Is Trigger 触发器
默认关闭:实体碰撞体,产生物理阻挡、反弹、撞击效果。
开启后:变为触发器,无物理阻挡,物体可以穿透,仅检测进入、停留、离开事件,用于拾取道具、传送门、伤害区域判定。
Center 中心点、Size 大小
自定义碰撞体位置和范围,适配模型大小,解决模型与碰撞体错位、大小不符问题。
5 物理核心事件函数
普通碰撞事件(实体碰撞,非触发器)
OnCollisionEnter:刚接触碰撞瞬间触发一次
OnCollisionStay:持续接触碰撞时每帧触发
OnCollisionExit:脱离碰撞瞬间触发一次
触发器事件(Is Trigger 开启后生效)
OnTriggerEnter:刚进入触发区域瞬间触发一次
OnTriggerStay:停留在触发区域每帧触发
OnTriggerExit:离开触发区域瞬间触发一次
6 物理更新规则
物理运算、刚体移动、碰撞检测全部在 FixedUpdate 中执行,不受帧率影响,固定0.02秒执行一次。所有刚体位移、受力代码必须写在FixedUpdate中,不能写在Update中。
7 刚体与碰撞体常见问题与解决
1. 物体无法碰撞、直接穿透
解决:检查双方是否有碰撞体、至少一方带刚体;确认未误开Is Trigger;高速物体开启连续碰撞检测。
2. 物体自动下落、悬浮抖动
解决:无需物理运动的物体删除刚体;运动物体开启冻结旋转约束,防止歪倒抖动。
3. 触发器不生效
解决:碰撞体勾选Is Trigger;其中一个物体带刚体;事件函数拼写完全正确。
4. 高速物体穿模
解决:刚体开启Continuous/Continuous Dynamic连续检测;缩短物理Fixed Timestep;添加射线路径检测。
5. 模型碰撞精准但游戏卡顿
解决:尽量使用基础几何体碰撞体,减少Mesh Collider使用,降低物理运算压力。
五、变换组件(Transform)
1 Transform 核心概念
Transform 是所有 GameObject 默认自带、无法删除 的核心基础组件,是物体的空间核心。所有游戏物体的位置、旋转、缩放、父子层级关系全部由 Transform 组件管理,是 Unity 一切空间运算的基础。
区别于其他组件:物体可以没有渲染、物理、脚本组件,但必须拥有 Transform 组件。
2 Transform 三大核心属性
Position 位置
物体在世界空间中的三维坐标,决定物体的空间所在位置。所有物体的移动、坐标赋值均依赖 Position。
transform.position = new Vector3(1,0,0);
Rotation 旋转(欧拉角)
控制物体三轴旋转角度,Unity 场景面板展示为欧拉角:X、Y、Z。
常规规律:Y轴为水平左右旋转、X轴为俯仰上下旋转、Z轴为平面倾斜旋转。
transform.rotation = Quaternion.Euler(0,90,0);
Scale 缩放
物体局部缩放倍数,默认值为(1,1,1)。数值大于1物体放大,小于1物体缩小,负数可实现镜像翻转。
transform.localScale = Vector3.one * 1.5f;
3 世界空间 & 局部空间(必考区分)
世界空间 World
全局统一坐标系,不受父物体影响,所有物体的最终真实空间位置。对应属性:position、rotation。
局部空间 Local
相对于父物体的相对坐标、旋转、缩放,父物体移动旋转,子物体局部数值不变。对应属性:localPosition、localRotation、localScale。
核心规则:无子物体时,局部坐标=世界坐标。
4 内置方向向量(世界 / 局部)
世界固定方向(恒定不变)
Vector3.right(X右1,0,0)、Vector3.left(X左)、Vector3.up(Y上0,1,0)、
Vector3.down(Y下)、Vector3.forward(Z前0,0,1)、Vector3.back(Z后)
物体局部方向(跟随物体旋转变化)
transform.right、transform.up、transform.forward
常用于物体自身前进、朝向移动、自身旋转,是角色移动、子弹发射核心参数。
5 常用核心方法
Translate 平移
实现物体相对移动,默认局部空间移动,可设置世界空间。适合角色持续移动、物体位移动画。
transform.Translate(transform.forward * Time.deltaTime);
Rotate 旋转
实现物体三轴旋转,可自身旋转或绕世界轴旋转,适配自转、视角旋转逻辑。
增量旋转 (在原有旋转基础上,每一帧叠加转动角度):
transform.Rotate(Vector3.up * Time.deltaTime * 60);
绝对旋转 (无视当前角度,直接把物体旋转固定设死):
transformer.rotation = Quaternion.Euler(30,30,30);
Rotate = 叠加增量,适合持续转动、动态旋转;直接赋值 rotation = Quaternion = 固定目标角度,适合瞬间摆正、瞬移朝向。
LookAt 朝向
让物体Z轴正对目标物体/目标坐标,常用于角色转头、相机对准目标、追踪朝向。
transform.LookAt(target);
Find 查找子物体
根据物体名称查找子物体,快速获取场景子对象,适配层级批量管理。
Transform child = transform.Find("Gun");
6 父子层级关系(重点)
父子规则定义
将物体拖拽到另一个物体下方,形成父物体 - 子物体层级结构;父物体是子物体的坐标基准。
父子三大核心特性
-
父物体变换同步影响子物体
父物体移动 / 旋转 / 缩放,所有子物体同步跟随变化;
例:父 Cube 放大 2 倍,内部子小球同步放大,坐标、尺寸全部联动。
-
子物体坐标为相对本地坐标
子物体 Transform 显示的 Position/Rotation/Scale 是相对于父物体的本地值,不是世界原点;父物体归零后,子本地坐标 = 世界坐标。
-
**支持多层嵌套:**子物体还能拥有子物体,变换逐级传递(爷爷→父→子全部联动)
代码动态设置父子关系
基础写法
// 方法1:直接赋值parent
ball.transform.parent = cube.transform;
// 方法2:SetParent(父Transform),推荐
ball.transform.SetParent(cube.transform);
// 解除父子:父赋值null
ball.transform.SetParent(null);
重载
transform.SetParent(target, false):第二个参数 false,设置父物体时不修改子物体当前世界坐标,仅变更层级;默认 true 会同步缩放旋转导致子物体位置偏移,做 UI / 道具挂载常用 false。
拓展
万向节死锁(Gimbal Lock)
一、概念
仅**欧拉角(X/Y/Z 三个角度分步旋转)**会出现的缺陷:当其中两根旋转轴重合对齐,3 个旋转自由度丢失 1 个,只剩 2 轴可控,视角 / 物体旋转出现错乱、画面翻滚、角度数值剧烈跳变,这个临界状态叫万向锁Unity。
根源:欧拉角是按顺序依次旋转局部轴,前一步旋转会改变后一步轴的方向,存在几何奇点。
二、Unity 典型现象
把物体 X 轴俯仰转到 ±90°,此时 Y 轴、Z 轴重合:
-
左右水平转动时,物体莫名倾斜翻滚;
-
检视面板 Rotation 欧拉角数值大幅跳跃;
-
无法独立控制水平、俯仰、倾斜三个方向。
三、两种旋转代码对比(对应你之前两行代码)
1. 直接赋值欧拉角(极易触发万向锁)
transform.rotation = Quaternion.Euler(30,30,30);
底层是欧拉角运算,多次叠加、大幅旋转时会出现锁死、角度跳变。
2. Rotate 增量旋转(单轴小幅叠加,不易锁死)
transform.Rotate(Vector3.up * Time.deltaTime * 60);
逐帧小角度叠加,仅单轴旋转,不会触发轴重合;多轴同时大幅旋转仍会出现万向锁。
四、核心解决方案(考试 / 开发必背)
方案 1:全程使用四元数(根治,首选)
Unity 底层存储旋转是四元数,四维数学结构无万向锁缺陷。
核心一行代码:
transform.rotation = Quaternion.LookRotation(target.position - transform.position);
方案 2:分层父子分离旋转(FPS 相机通用)
父物体只做水平 Yaw(Y 轴),子相机只做俯仰 Pitch(X 轴),永远不会到达 ±90° 奇点。
层级结构:Player (Y 旋转) → Camera (X 俯仰)
方案 3:限制欧拉角范围(临时规避)
俯仰角约束在 -85° ~ 85°,避开 ±90° 死锁临界点。
float pitch = Mathf.Clamp(pitchAngle, -85, 85);
六、本地坐标 LocalPosition & 世界坐标 Position
1 概念区分
-
世界坐标 transform.position
以场景原点 (0,0,0) 为基准,整个全局空间的真实坐标,所有物体统一基准;无父物体时,本地坐标 = 世界坐标。
-
本地坐标 transform.localPosition
仅相对父物体原点的偏移值,父物体移动,localPosition 数值不变,但世界坐标同步改变;
-
对应配套:
本地旋转
localRotation/ 世界旋转rotation本地缩放
localScale/ 世界缩放lossyScale(只读,父缩放叠加后的真实尺寸)
2 换算逻辑
子物体世界坐标 = 父物体世界变换 + 自身本地变换(矩阵叠加);
多层嵌套逐层叠加矩阵,Unity 底层自动计算,无需手写矩阵。
3 代码获取示例
Transform ball = transform;
Vector3 worldPos = ball.position; // 世界坐标
Vector3 localPos = ball.localPosition; // 相对父本地坐标
Vector3 realScale = ball.lossyScale; // 叠加父缩放后的真实尺寸
4 拓展
1. 屏幕坐标 Screen Point
原点:屏幕左上角 (0,0)
X:向右增大;Y:向下增大
单位:像素 px
范围:(0,0) ~ (Screen.width, Screen.height)
适用:鼠标输入 Input.mousePosition、UI 像素位置
2. 视口坐标 Viewport Point(相机视口)
原点:相机画面左下角 (0,0)
X:向右 0→1;Y:向上 0→1
单位:比例(无像素)
固定范围:(0,0) ~ (1,1)
适用:相机边缘归一化计算、分屏、自适应屏幕
3. 世界坐标 World Point
场景全局三维坐标 (x,y,z)
物体 transform.position、射线碰撞 hit.point
不受屏幕、相机影响
4.坐标转换
设相机变量 Camera cam = Camera.main;
-
世界 → 屏幕
Vector2 screenPos = cam.WorldToScreenPoint(worldPos);
输入:Vector3 世界点 输出:Vector2 像素屏幕坐标
-
世界 → 视口
Vector2 viewportPos = cam.WorldToViewportPoint(worldPos);
输出:0~1 比例视口坐标
-
屏幕 → 世界(平面,必须指定 Z 深度)
// z:该点距离相机的深度(Z轴距离)
Vector3 worldPos = cam.ScreenToWorldPoint(new Vector3(screenX, screenY, z)); -
屏幕 → 视口
Vector2 viewportPos = cam.ScreenToViewportPoint(screenPos);
-
视口 → 屏幕
Vector2 screenPos = cam.ViewportToScreenPoint(viewportPos);
-
视口 → 世界(指定深度 z)
Vector3 worldPos = cam.ViewportToWorldPoint(new Vector3(vx, vy, z));
七、四种物体查找方式(工程高频)
方式 1:按物体名称查找 GameObject.Find ("物体全名")
规则
-
全局遍历整个场景所有物体,匹配名称完全一致的对象;
-
缺点:遍历效率极低,物体越多卡顿越明显,禁止 Update 循环内调用;
-
支持层级路径查找:
GameObject.Find("Cube/Ball")逐层定位子物体; -
找不到返回 null,直接调用组件会空引用报错。
示例
GameObject ballObj = GameObject.Find("Ball");
if(ballObj != null){
Transform ballT = ballObj.transform;
}
方式 2:按标签查找 GameObject.FindWithTag ("自定义标签")
概念
Hierarchy 选中物体,Inspector 顶部 Tag 下拉自定义标记(Player、Bullet、Enemy),同类型物体统一标签批量查找。
特性
-
查找效率高于按名称;
-
只能精确匹配单个标签;
-
批量查找同标签所有物体:
GameObject.FindGameObjectsWithTag("Enemy")返回数组; -
标签可以无数次添加
使用步骤
-
选中物体 → Tag 下拉 → Add Tag 新增自定义标识;
-
物体赋值对应 Tag,代码查找。
方式 3 层级父子查找(性能最优)
适合已知父子固定结构,无需全局遍历,仅在父物体内部检索
-
查找直接子物体:
transform.GetChild(索引),索引从 0 开始; -
遍历所有子物体:
foreach(Transform child in transform); -
查找自身父物体:
transform.parent; -
递归向上查找父级指定名称 / 物体:多层嵌套专用;
-
可以查找隐藏的游戏物体;
-
层级最多只有32个
代码示例
// 获取第一个子物体
Transform child0 = transform.GetChild(0);
// 遍历全部子物体
foreach(Transform t in transform){
Debug.Log(t.name);
}
transform.Find("../"); // 查找上一层物体
transform.parent; // 查找父物体
transform.root; // 查找根物体
方式 4 序列化拖拽赋值(最优性能,项目标准写法)
概念
脚本声明public Transform target;,编辑器 Inspector 面板直接拖拽物体赋值;
优势
-
游戏运行前已绑定,运行无任何查找开销;
-
不会出现 null 空引用(开发阶段直接检查)
-
项目开发优先推荐,仅动态生成物体才用 Find/Tag 查找。
八、运行时操作开发规范 & 易错 Bug
1 禁止运行中频繁删除 / 创建大量物体
Update 循环内反复 Instantiate/Destroy 会造成 GC 卡顿,游戏采用对象池优化。
2 空引用崩溃解决方案
所有 Find 查找物体后,必须做if(obj != null)判空,再调用组件、属性;
3 父子层级坑
SetParent 默认 true 会继承父缩放,挂载 UI、道具时传 false 固定世界坐标;
4 坐标混淆坑
修改子物体位置优先用 localPosition,修改全局世界位置用 position;
5 查找性能排序(从优到差)
拖拽赋值 > 父子层级 GetChild > Tag 查找 > GameObject.Find 名称查找
九、拓展
1 Transform 能否删除?所有 GameObject 自带,不可移除;
2 本地坐标与世界坐标核心区别、多层嵌套换算逻辑;
3 四种物体查找方式性能差异与项目使用规范;
4 SetParent 第二个布尔参数作用;
5 父子层级变换联动底层矩阵原理;
6 运行时频繁 Find 的性能缺陷优化方案。