Unity相机与刚体物理实战:跟随、碰撞与抖动排查指南

发布时间:2026/10/11 16:36:00
Unity相机与刚体物理实战:跟随、碰撞与抖动排查指南 不用从“Unity是什么”讲起直接进入正题。相机和刚体这两个模块是Unity项目里最容易“看起来没问题、一跑就翻车”的地方。相机决定了玩家看到什么刚体决定了物体怎么动而两者一旦组合起来——比如第三人称角色、物理载具、可推动箱子——各种抖动、穿透、卡墙的经典问题就全来了。这篇笔记是我在实际项目中反复调试后沉淀下来的知识整理覆盖相机的基础概念与跟随方案、刚体的参数与碰撞检测、两者组合时的坑以及性能优化的一些经验。适合正在做3D游戏、模拟类应用或者刚把物理系统接进项目的开发者参考。1. 相机核心从“摆个机位”到“稳定跟手”相机在Unity里叫Camera本质是一个“看世界的窗口”。很多人觉得相机组件没什么好研究的但只要你做的是第三人称、俯视角、射击类、或者带镜头的交互应用相机的设置就决定了手感上限。1.1 正交与透视不是随便选相机有两种投影模式正交投影和透视投影。正交相机无视距离远近物体大小不随距离变化适合2D游戏、UI叠层、俯视角策略、像素风场景。透视相机模拟人眼近大远小适合3D游戏、赛车、飞行模拟、第一人称和第三人称。实际项目里切换这两种模式很常见比如RPG中大地图用透视进入背包或小地图时叠一层正交相机。切的时候要注意透视相机的FOV视野角度没法直接映射成正交的Size。正交相机的Size是“视锥半高”也就是屏幕中心到边缘的世界单位距离。同一个场景从透视切到正交画面构图会明显变化不能简单一键切换就完事。FOV的选择也有讲究。FOV太小视野窄容易晕FOV太大画面边缘畸变明显角色会被拉变形。第三人称动作游戏常用60到75竞速游戏可以用80到90来体现速度感。实际调的时候用角色站立时脑袋在屏幕中间偏上、脚在地平线附近为基准反复调整。还有一个容易忽略的参数是近裁剪面和远裁剪面。近裁剪面太小会导致近距离物体被异常拉伸甚至穿帮太大则角色贴近镜头时会被裁掉。远裁剪面决定可见距离设太大影响深度精度和遮挡剔除效率设太小远景突然消失。没有统一标准值我一般先按当前场景规模估算室内场景近裁剪面0.05到0.1、远裁剪面200到300大世界场景近裁剪面0.3到1、远裁剪面按实际视野范围控制在1000以内。1.2 跟随方案直接改坐标还是做插值相机跟随的写法多种多样但核心就两类直接把相机位置设为目标位置或者用插值让相机平滑移动。先说直接跟随。把相机做成角色的子物体或者每帧把相机transform.position设成角色坐标加一个偏移。这种方案响应最快但完全跟随刚体角色时角色跳跃、落地、碰撞减速的瞬间相机会跟着剧烈颠簸。尤其是刚体角色在被击退、撞墙、被挤压时相机抖动非常明显。平滑跟随是更常用的方案。常见写法是使用Vector3的Lerp或SmoothDamp。Lerp做线性插值写起来简单但速度恒定跟随时会有生硬的匀速感。SmoothDamp模拟弹簧阻尼效果起步快、减速缓体感更接近真实镜头的惯性适合第三人称跟随。写平滑跟随有个关键点插值系数要乘上阻尼时间不能简单地每帧写死一个值。比如“每帧朝目标移动0.1”这样写在60帧和30帧下表现完全不同低帧率下相机更“肉”。正确做法是用Time.deltaTime来补偿帧率差异。实际项目里我习惯把相机跟随逻辑放在LateUpdate里。原因很直接Update执行完所有逻辑后LateUpdate再更新相机位置相机看到的就是最终场景状态。如果把相机更新放在Update里可能赶上角色还没移动、或者物理还没结算完画面就会出现一帧滞后甚至抖动。1.3 相机碰撞防止镜头穿墙的常见方案相机和刚体碰撞最常见的问题就是穿墙。角色站在墙角相机跟随角色时被墙“吞”掉玩家只能看见一片黑。解决方案不复杂从角色位置向相机位置发射一条射线检测到碰撞物时把相机距离缩短到碰撞点之前。这样镜头会贴着墙壁内表面而不是直接穿过去。具体实现上关键点是射线要放在LateUpdate里执行并且要区分“可遮蔽相机的物体”和“普通碰撞体”。比如地面、小道具、玩家自身不应该触发射线缩减否则镜头会被自己的角色模型挡住疯狂拉近。还有一个细节缩短后的相机位置恢复要平滑。如果角色离开墙角后相机瞬间弹回原位置画面会“跳”一下。做法是记录当前相机距离每帧向目标距离做插值而不是直接赋值。1.4 视野控制FOV动态变化与画面反馈FOV不只是设置面板里的一个数字。赛车游戏加速时FOV变大产生速度感角色开镜时FOV变小拉近视野受击时瞬间抖动FOV再恢复增强打击感。这些都是通过代码动态修改camera.fieldOfView实现的。动态调FOV要注意两点一是FOV变化要经过平滑过渡而不是瞬跳否则会让人感觉镜头被猛拽二是FOV不能无限大超过100以后画面边缘变形严重影响视觉质量。还有一个容易踩的坑多个相机场景中动态修改FOV可能会误改到不期望的相机。写代码时最好使用明确的对象引用避免用Camera.main到处找。1.5 相机抖动拍屏问题的排查思路相机抖动是第三人称项目里反馈率最高的问题表现是画面高频晃动尤其在角色移动或物理碰撞后特别明显。抖动来源一般有三类。第一类是物理抖动角色刚体受力波动导致位置高频变化相机跟着剧烈晃动。解决办法是让相机跟随的目标点使用插值或滤波。第二类是代码抖动相机跟随代码写了每帧硬赋值但角色在FixedUpdate里移动渲染帧与物理帧不同步相机有的帧读到的位置是旧的有的帧是新的视觉上就抖。解决方式是用LateUpdate并配合合适的插值参数。第三类是浮点精度抖动。角色坐标很大时相机离原点远浮点精度下降画面开始肉眼可见地飘动。大世界项目要考虑原点重置或区块偏移小项目如果真的出现这种问题先怀疑坐标数值量级。2. 刚体物理理解Unity的物理引擎边界刚体Rigidbody是Unity物理系统的核心让物体受重力、碰撞和力的影响。但不少人对刚体的理解停留在“挂上组件就能动”结果遇到各种诡异行为不知道从哪里排查。2.1 三种刚体类型Dynamic、Kinematic、Static刚体组件有三种重要类型设置通过Is Kinematic和Body Type区分。Dynamic是默认状态完全受物理引擎控制有速度、受力、碰撞响应。适合玩家角色、可推动物体、掉落物。Kinematic不受物理力和碰撞影响但能通过代码移动碰到Dynamic物体会推动它们。适合电梯、移动平台、门、程序控制的敌人。要注意的是Kinematic刚体移动时必须用Rigidbody.MovePosition或直接设置position而不是修改transform。用transform移动会在高速下导致碰撞穿透因为物理引擎没有机会去处理中间过程。Static指没有刚体但有碰撞器的物体比如地面、墙壁。Static物体不会移动物理引擎对它们做了加速优化。但如果在运行时移动Static物体物理引擎的性能和碰撞检测都会出问题轻则漏碰撞重则产生抖动。动态场景中需要移动的物体哪怕它看起来是静止的也建议至少带一个Kinematic刚体。理解这三种类型的区别是排查物理问题的前提。大部分穿模、卡模型、推不动的问题根因都在于类型设错了。2.2 刚体参数Mass、Drag、Angular Drag和Constraints刚体Inspector里的参数每个都有实际影响。Mass是质量。Unity中质量不一定要等于真实物理质量重要的是相对值。两个物体碰撞时质量比决定撞击后的速度分配。如果角色Mass很小、箱子Mass很大角色推箱子就会推不动反过来角色一脚就把箱子踢飞。调整参数时先设置地面和静态物体再调整动态物体的相对质量。Drag是线性阻尼影响物体在移动方向上受到的阻力数值越大物体减速越快。Angular Drag是旋转阻尼影响旋转减速。这两个参数不要设成完全零除非是太空场景或刻意追求无限滑动。摩擦力、碰撞反弹和阻尼之间是有配合关系的调一个就要看其他表现是否符合预期。Constraints是约束面板勾选Freeze Position或Freeze Rotation可以锁定某个轴。比如2D游戏锁定Z轴旋转、滑动门锁定Y和Z移动。锁定轴之后物体会忽略对应方向的物理力效果等同于“半静态”。2.3 刚体插值解决渲染帧与物理帧不同步刚体组件上有Interpolate和Extrapolate两个选项这是很多新手完全忽略的参数。物理引擎默认以固定时间步长更新渲染帧率却是不固定的。当渲染帧率高于物理帧率时物体位置看起来会一顿一顿的。Interpolate会在两个物理帧之间插值让画面平滑Extrapolate则是基于上一帧的速度预测下一帧的位置响应更快但可能预测过头。实际使用中第三人称角色、需要碰撞的玩家物体建议开启Interpolate。Extrapolate适合高速移动且对实时操控要求高的物体但需要注意预测误差导致的抖动。有一种抖动情况不是插值能解决的角色使用Transform移动而相机跟踪角色位置位置更新频率与渲染帧率不一致画面会轻微抽搐。解决思路是让角色用物理方式移动或者移动前先把Transform同步到刚体插值位置。2.4 碰撞体形状与物理材质摩擦和弹性的计算方式碰撞体是形状的描述常见的有Box、Sphere、Capsule、Mesh和Convex组合。网格碰撞器性能较差非必要不挂在动态物体上。动态角色、敌人、道具优先使用胶囊体、球体或盒体组合。物理材质Physic Material控制摩擦力和弹性。Dynamic Friction是运动时的摩擦阻力Static Friction是静止时需要克服的静摩擦Bounciness是弹性系数Friction Combine决定了两个材质摩擦力的合成方式。合成方式有Average、Min、Max、Multiply四种。默认是Average。实际调参时例如角色站斜坡Static Friction偏低会往下滑弹球需要Bounciness设为1同时Combine方式设为Max否则弹不起来。物理材质有一个非常容易被忽略的坑物理材质需要定义在Assets文件夹中而不是挂在碰撞器上就能新建。在Inspector里直接拖拽材质球文件到碰撞器的Material栏。很多人卡在这一步因为找不到“创建物理材质”的入口——需要在Project窗口右键→Create→Physic Material。2.5 刚体睡眠和性能减少不必要的物理运算刚体在静止一段时间后会进入睡眠状态不再参与物理运算直到新的碰撞或力唤醒它。这是物理引擎的重要优化机制。可问题是有些物体需要持续感知外力或者代码每帧读取刚体的位置和速度睡眠后这些读取会得到不准确的旧值。比如一个静止的平台玩家站在上面行走如果平台刚体进入睡眠摩擦力可能变得可疑人物站不稳。此时可以在代码里调用WakeUp或者在物体的刚体上把Sleeping Threshold调小。Sleep Threshold在Project Settings的Physics里默认0.005表示速度低于该值时可能进入睡眠。如果项目频繁出现“物体明明被打了却无响应”的情况可以优先检查是否处于睡眠状态。另一个性能点是刚体数量。物理引擎对刚体数量很敏感项目里同时模拟的刚体过多CPU消耗会直线上升。优化方式是让非必要的碰撞体使用触发器或者用纯代码模拟简单移动避免把所有物体都挂刚体。3. 实操第三人称角色与物理交互全流程理论知识拆完了这里从头梳理一个带物理交互的第三人称角色实现流程。这套流程适合动作冒险、解谜、角色扮演类项目也是我常用的基础模板。3.1 角色刚体与碰撞设置的推荐参数角色物体上挂Rigidbody和Capsule Collider是绝大多数3D项目的基础配置。Capsule Collider比Box Collider更贴合人形角色在台阶、坡道上表现更平滑不容易卡边。推荐的初始参数Mass设为50到80Drag设为0到0.5Angular Drag设为5到10Constraints锁定XZ旋转和Z移动只保留Y轴移动和绕Y轴旋转。Interpolate设为InterpolateCollision Detection设为Continuous。Continuous能防止高速撞击时穿过墙体代价是性能开销略高但角色这种需要稳定碰撞的物体值得开。控制器负责移动速度物理负责碰撞响应。具体说就是代码计算出目标速度通过刚体velocity设置速度而不是直接修改position。直接修改position会绕过物理引擎的速度计算导致碰撞穿透判断不准确。3.2 移动与物理力的分离墙与坡道处理把移动拆成“输入方向”和“实际受力”两部分调试会容易很多。输入方向来自玩家操作比如前后左右经过相机方向转换后得到世界空间方向。实际受力则要考虑斜坡、碰撞、空气阻力等因素。当角色撞到墙壁时velocity中的法向分量会被物理引擎自动抵消一部分角色会贴着墙滑行。有时我们希望角色能读墙跑、不能在斜坡上站住就需要修改斜坡判断逻辑。斜坡判断的核心是从角色脚底向下发射射线检测地面法线然后根据法线与水平面的夹角决定是正常移动还是使用斜坡适配。斜坡角度超过45度时要强制角色停止或进入掉落状态否则角色会沿坡面滑下去表现很奇怪。此外跳跃和重力不要直接在Update里修改刚体velocity应在FixedUpdate里统一处理。跳跃本质是一次瞬时冲量可以用AddForce带ForceMode.Impulse实现。3.3 相机跟随角色但不穿透场景的完整逻辑相机跟随与物理结合时我的实现顺序如下LateUpdate里先计算角色目标位置一般是角色头部上方一点偏移一个向量。用SmoothDamp对位置做平滑得到相机期望位置。然后从目标点向期望位置做射线检测如果射线打了碰撞体就把期望位置缩短到命中点附近。需要注意射线检测的Layer。相机射线只应检测到场景碰撞层不应检测到角色自己的碰撞体也不应检测到可交互道具。否则角色靠近道具时相机会被道具挡住。3.4 角色朝向与移动方向的顺滑衔接第三人称项目中角色模型朝向和移动方向不一致时需要做平滑转身。做法是每帧计算当前移动方向用Quaternion.Slerp把模型的旋转角度逐步转向目标方向。Slerp的旋转速度与移动速度相关联会更自然静止时不转向移动快时转向迅速。转身时注意模型的根节点旋转轴必须与刚体旋转约束一致。如果刚体锁定了X和Z旋转但模型子节点的本地旋转包含了俯仰角看起来就会歪。3.5 手持物体与物理交互的层级体验交互系统常见玩法是捡起、投掷、推动。推动物体实现相对简单角色碰撞到物体时根据角色相对物体的方向施加一个力或者在物体碰撞响应中写入速度。如果希望角色和物体之间保持一定距离可以在碰撞期间持续修正物体速度。捡起物体更复杂一些可以使用FixedJoint临时连接角色身上的一个空节点让物体跟着节点运动。拾取时先移除物体的重力作用把useGravity设false再挂Joint扔出时解除Joint并恢复重力施加一个初速度。这类交互非常依赖刚体的Sleep和唤醒状态。物体静止时可能处于睡眠拾取瞬间要主动调用WakeUp否则Joint连接后物体可能还保持静止。4. 常见问题排查抖动、穿模、卡墙与性能诊断前面虽然零散提过一些坑但单独整理一份排查清单会更有价值。这些是我实际项目中反复踩过的点。4.1 角色抖动排查顺序先确认是否开了刚体Interpolate。再检查相机跟随代码是否放在LateUpdate。然后确认角色移动是否在FixedUpdate中完成而不是在Update里设置刚体velocity。最后检查角色坐标是否过大超出合理量级。如果这四步都合理考虑帧率波动。物理帧率固定、渲染帧率波动较大时即使有插值也会出现轻微抖动可以使用Application.targetFrameRate或垂直同步设置减少帧率波动。还有一种隐蔽情况角色的子节点包含Animator动画根运动与刚体移动叠加导致每帧的位置出现微小冲突。关闭根运动或使用OnAnimatorMove统一处理即可。4.2 穿模排查顺序碰撞穿透通常和速度、碰撞检测模式、物体厚度有关。先用Debug.DrawLine观察角色移动路径是否被碰撞体拦截。确认角色碰撞体大小是否合理——碰撞体比模型小一圈贴墙时模型会穿墙。再确认碰撞检测模式是否满足速度需求。高速运动物体使用Continuous模式。还有一种穿透原因是物理步长太大而物体太薄。比如墙壁碰撞体厚度只有0.01而角色每物理帧移动距离大于0.05就可能跳过碰撞检测。物理步长在Project Settings中修改但一般不建议为了单个物体全局调小步长会让物理计算量显著上升。4.3 卡墙与滑墙问题卡墙多发生在墙角或障碍物边缘角色被卡住无法移动。常见原因是碰撞体边角过多角色碰撞体并非平滑曲线。用Capsule Collider能降低卡角概率。滑墙则是角色撞墙后不受控制地沿墙体滑动。如果不想滑墙可以在碰撞回调里检测碰撞法线方向如果角色速度在碰撞法线方向上有分量就将其清零。但要注意结合斜坡平地滑墙与斜坡滑动的处理逻辑不同建议分开写。另一种“卡”的表现是角色被物体夹住无法动弹。这通常是两个碰撞体同时挤压角色物理引擎在持续求解接触约束角色无法逃脱。试着把物体的碰撞体改成触发器或者调整角色的碰撞检测模式与物理材质摩擦力。4.4 刚体受力后“没反应”的排查物体看起来静止被击中后没有反应先检查刚体是否处于睡眠状态。在代码中调用AddForce前调用WakeUp。再检查物体的Is Kinematic是否被误设为true。Kinematic刚体其实也有velocity但不受力影响。检查代码是否在Update里执行AddForce而不是FixedUpdate。Update帧率和物理帧率不同步AddForce可能被重复调用或漏调用。物理操作统一放在FixedUpdate中是标准做法。还有一种情况物体系在挂点下Sub Collider的刚体为空碰撞事件被父物体吞掉。需要检查非触发器碰撞器所在的物体是否确实挂载了刚体。4.5 性能优化减少物理运算压力的几招物理性能的核心矛盾是刚体数量与模拟步长。刚体数量过多时第一反应不是优化代码而是减少不必要的刚体。复盘哪些物体真正需要物理模拟。场景中纯装饰物、静态道具、由动画控制的物体都不需要刚体。可以让这些物体只带碰撞器甚至碰撞器都可以省略。需要刚体但不需要精确碰撞的物体可以改为触发器。触发器只做进入/退出事件检测不做受力模拟性能开销低很多。还有一个优化点不要给父子层级中的每个子物体都挂刚体。一个刚体加多个碰撞器比多个刚体更省性能。物理引擎处理的是一个物体上一组碰撞器的联合而非多个独立物体的各自模拟。关于物理步长全局调小会导致物理模拟次数变多适用于需要精确碰撞的项目。但一般以默认0.02秒为基准仅当检测到穿透或抖动时才微调。4.6 一个值得收藏的物理参数速查表场景需求推荐方案第三人称角色Capsule Collider RigidbodyInterpolate开启Interpolate位置碰撞Continuous移动平台Kinematic刚体用MovePosition移动不修改Transform可推动的箱子Dynamic刚体Mass设为角色2到4倍Drag适度摩擦力适中高速子弹Collision Detection设为Continuous使用射线检测或专用命中判定装饰物、树木不应挂刚体使用静态碰撞器或触发器这个表不是万能答案但作为起点调试很省时间。5. 实际项目中的心得与经验补充最后分享一些不成体系但在多次项目中验证过的经验。第一相机和刚体出现问题时不要先怀疑引擎先怀疑自己的代码顺序。绝大多数低级问题出在Update/LateUpdate/FixedUpdate的调用时机上。第二物理材质的摩擦力和弹力最好做成可运行时修改的配置。很多玩法需要临时切换手感比如冰面关卡、泥地减速、弹力机关如果材质是写死的每次切换都要改资源效率很低。第三刚体速度不要直接赋值设成极大值。高速设置下即使开启Continuous也可能产生预料之外的穿透。如果确实需要超高速物体考虑用射线检测配合分段移动模拟。第四使用层级管理碰撞矩阵时建立专门的“相机层”“角色层”“环境层”“交互层”是值得一开始就做的规划。后期再改容易遗漏部分物体的层级排查成本很高。第五注意物理材质球文件的重用问题。多个碰撞器共用同一个物理材质时运行时如果修改材质参数影响的是所有碰撞器。需要单独调整时用代码创建材质实例或者为不同碰撞器准备独立资源。这套笔记是我日常项目中最常参考的基础知识写出来主要是给自己留档也希望对正在做同类项目的开发者有帮助。如果后续有精力我会再单独整理相机震动实现、物理交互物体池、角色斜坡系统的详细代码版本作为这篇笔记的延伸。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询