Roblox 物理
在模拟、角色控制、命中检测与仅视觉运动之间审慎选择; 它们是不同职责。面向 Roblox 滚动发布的 Platform API。与 physics-tuning 搭配, 以获得引擎中立的稳定性与手感。
何时使用
- 用于 BasePart 装配体、约束、碰撞/查询策略、射线/重叠查询、力、
- 当
Touched不可靠/涉及安全敏感、部件穿透或抖动、机制在锚定时损坏,
冲量、移动物理对象、网络所有权或物理清理。
或出现旧 BodyMover 模式时使用。
何时不使用: 普通 Humanoid 生命周期/控制属于 roblox-characters;远程 验证属于 roblox-networking;装饰性 UI/世界运动可能只需要补间动画。
先决定系统
| 目标 | 机制 | |---|---| | 持续物理交互 | 未锚定装配体 + 现代约束/力 | | 瞬时物理变化 | ApplyImpulse / ApplyAngularImpulse | | 运动学平台/路径 | 受控 pivot/transform,并采用明确乘客策略 | | 角色移动 | Humanoid/自定义角色控制器 (roblox-characters) | | 权威命中测试 | 服务器射线检测/重叠查询,带筛选与玩法验证 | | 装饰性拖尾/后坐力 | 本地视觉运动;无玩法权威 |
工作流
- 检查机制。 在 Studio 中,可视化装配体、锚点、约束、碰撞
- 定义交互策略。 编写碰撞组矩阵,并分别决定
- 选择模拟或查询。 不要将
.Touched用作通用命中检测器。对路径/直线使用射线, - 在装配体层级应用运动。 作用于部件的力会影响其装配体。酌情使用现代
- 审慎设置所有权。 在需要时由服务器拥有玩法关键的松散装配体;
- 限制成本与生命周期。 复用查询参数,限制查询频率/结果数量,移除
- 在负载与多人环境下验证。 测试锚定/未锚定转换、质量极端、
组、无质量部件和网络所有者。识别装配体根以及预期权威。
CanCollide、CanTouch 和 CanQuery。这些标志不可互换。
对体积使用重叠查询,并在确实需要物理响应时使用模拟接触。
LinearVelocity、AngularVelocity、VectorForce、AlignPosition 和 AlignOrientation 约束;在更改该系统时迁移已弃用的 BodyMovers。
客户端所有权可改善响应性,但绝不能授权玩法结果。
临时约束/附件,并断开事件监听器。
碰撞矩阵、快速运动、多客户端、所有权变更、流式加载与清理。
模式:经过筛选的服务器射线检测
local Workspace = game:GetService("Workspace")
local params = RaycastParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {shooterCharacter}
params.IgnoreWater = true
params.CollisionGroup = "WeaponQuery"
local direction = aimDirection.Unit * MAX_RANGE
local result = Workspace:Raycast(muzzlePosition, direction, params)
if result then
local model = result.Instance:FindFirstAncestorOfClass("Model")
local humanoid = model and model:FindFirstChildOfClass("Humanoid")
if humanoid and serverCanDamage(shooter, model, result.Position) then
humanoid:TakeDamage(serverWeaponDamage(shooter))
end
end
服务器必须根据服务器已知角色/武器状态验证原点/方向;不要 接受任意客户端原点,并把射线检测本身当作验证。
模式:具有明确策略的重叠体积
local params = OverlapParams.new()
params.FilterType = Enum.RaycastFilterType.Exclude
params.FilterDescendantsInstances = {sourceCharacter}
params.CollisionGroup = "DamageQuery"
params.MaxParts = 64
local seen: {[Model]: boolean} = {}
for _, part in Workspace:GetPartBoundsInBox(hitboxCFrame, hitboxSize, params) do
local model = part:FindFirstAncestorOfClass("Model")
if model and not seen[model] then
seen[model] = true
validateAndApplyHit(model)
end
end
边界查询使用包围盒,可能包含同一目标的多个部件;需要时进行去重并 执行精确/玩法检查。对精确几何使用 WorldRoot:GetPartsInPart(part, overlapParams) 仅当其额外成本合理时。注意 OverlapParams.RespectCanCollide 决定查询是否遵循 CanCollide 或 CanQuery —— 审慎设置它,否则它会静默覆盖下面的标志 策略。OverlapParams.Tolerance 控制接触容差。
装配体、力与所有权
- 焊接部件形成一个刚性装配体;力、冲量、速度、质量与所有权都作用于
- 对一次性变化应用冲量;对持续控制使用力或速度约束。
- 在创建或修订机制时,优先使用附件加现代约束,而不是
BodyPosition、BodyVelocity、BodyGyro和 - 自动所有权可能把附近未锚定装配体转移给客户端。对关键对象谨慎使用
- 客户端所有者可以操控物理结果与
.Touched观察。服务器独立验证
该装配体。锚定部件会改变模拟/所有权,并可使装配体实际上具有 无限质量。
设置 AssemblyLinearVelocity 是立即状态变化,不是连续力模型。
其他已弃用 BodyMovers。
SetNetworkOwner(nil),然后测量响应性/服务器 成本。在 Studio 中可视化网络所有者。
有后果的命中、位置、时机与权限。
常见故障
| 症状 | 可能原因 | 补救措施 | |---|---|---| | 焊接机制无法移动 | 某个部件已锚定 | 检查完整装配体;仅锚定有意作为世界根部的部件 | | 力的行为过强/过弱 | 忽略了装配体质量 | 检查 AssemblyMass;按预期加速度调整力/冲量 | | 未命中快速抛射物 | 离散触摸采样/穿透 | 扫掠查询 — WorldRoot:Blockcast()、Spherecast() 或 Shapecast() — 加上 physics-tuning;不要仅依赖 .Touched | | 射线命中射击者/效果 | 缺少筛选/碰撞组 | 复用显式参数与查询组 | | 同一目标多次受伤 | 重叠查询返回多个身体部件 | 按目标模型去重,并强制攻击 ID/冷却 | | 利用触发不可能的触摸 | 客户端拥有相关物理 | 服务器查询/上下文验证;审慎所有权 | | 不可见触发器阻挡或无法查询 | 三个标志被混淆 | 独立设置 CanCollide、CanTouch、CanQuery | | 机制泄漏附件 | 缺少临时约束生命周期 | 共同拥有并销毁约束、附件与连接 |
资源
- 阅读
references/queries-and-ownership.md获取碰撞/查询矩阵、装配体调试、
所有权安全、迁移选择以及物理验证矩阵。
相关技能
physics-tuning— 时间步长、抖动、穿透、质量比与稳定性方法学。roblox-characters— Humanoid/自定义移动与重生生命周期。roblox-networking— 对客户端请求的物理动作进行权威验证。roblox-studio-workflow— 可视化、Output 与多客户端验证。
主要参考资料
https://create.roblox.com/docs/physics/assemblieshttps://create.roblox.com/docs/physics/network-ownershiphttps://create.roblox.com/docs/workspace/raycasting