Skip to content

物理状态的应用

受力物体遵循基础物理定律,球体易跌落平台,可通过以下方式优化。

空气墙

第一步,从创建面板拖出一个方块到世界中,改名成空气墙(名字没有硬性要求)。

第二步,修改空气墙的位置和缩放,达到图中的效果。

第三步,将模型可见性设置为 false,以达到运行时看不见的效果。

第四步,重复一至三步骤,直至平台的四面都被空气墙包围。

测试效果:

CollisionGroup 碰撞组(可跳过)

制作仅球体可穿过、蛋仔不可穿过的过滤墙,提升游戏难度。

透明度与颜色

同时调整透明度与染色区域,让玩家可以透过墙体看到方块。亦可通过代码修改对应组件的 ModelAlphaModelColor1 属性。

lua
local passWall = World:FindFirstChild("过滤墙") -- 获取世界下的过滤墙
passWall.ModelAlpha = 0.5                       -- 透明度 0-1,0 为全透明,1 为不透明
passWall.ModelColor1 = tonumber("0000ff", 16)

碰撞组设置

接下来加上"过滤"效果,实现原理是将球体和过滤墙分别设置成不同的碰撞组,并设置两组之间不可碰撞,从而达到球体穿墙的效果。

目前有两种途径设置和分配碰撞组:

  • 通过编辑器直接管理和分配
  • 通过脚本注册与分配

编辑器方案

在过滤墙的属性面板上找到【物理】-【碰撞组】-【管理碰撞层】。

在弹出的【自定义物理碰撞】窗口中依次操作:

点击【新建碰撞层】 → 【编辑】 → 输入 PassWall → 勾选与 Character 的关系。

重复上述步骤再新建一个命名为 Ball 的碰撞层,勾选除 PassWall 之外的其他碰撞组,保存后退出当前弹窗。

WARNING

Character 指的是玩家蛋仔的默认分组。

分别选择过滤墙和球体,在属性面板上打开【碰撞组】菜单,分配到对应的 PassWallBall 碰撞组。

脚本方案

碰撞分组接口需要用到 PhysicsService 物理服务。

API 参考PhysicsService

lua
local World = game:GetService("World")          -- 获取游戏世界
local ball = World:FindFirstChild("球体")        -- 获取世界下的球体
local passWall = World:FindFirstChild("过滤墙")  -- 获取世界下的过滤墙
local PhysicsService = game:GetService("PhysicsService") -- 获取物理服务

-- 注册过滤墙与球体的专属碰撞组
PhysicsService:RegisterCollisionGroup("PassWall")
PhysicsService:RegisterCollisionGroup("Ball")

-- 分配碰撞组
passWall.CollisionGroup = "PassWall"
ball.CollisionGroup = "Ball"

-- 默认状态下,新注册的组之间不可碰撞,这里作为示例设置两组的碰撞关系为不碰撞
PhysicsService:CollisionGroupSetCollidable(ball.CollisionGroup, passWall.CollisionGroup, false)

测试效果

蛋仔无法穿过墙体,但可以将球推到墙体另一边。

运行时服务(RunService)

RunService 运行时服务提供客户端与服务端运行环境的判断能力,以及帧循环触发事件。

API 参考RunService

通过帧循环检测球体位置,异常时自动重置,避免球体卡死或丢失:

lua
local startPos = ball.Position -- 记录球体的初始坐标

local function ResetBall()
    -- 重置球体的物理状态
    ball.Position = startPos                  -- 位置
    ball.LinearVelocity = Vector3(0, 0, 0)    -- 线速度
    ball.AngularVelocity = Vector3(0, 0, 0)   -- 角速度
end

local RunService = game:GetService("RunService")
RunService.Heartbeat:Connect(function(deltaTime)
    -- 球体极端位置保护
    if startPos.y - ball.Position.y > 5
    or (ball.Position.x < passWall.Position.x and ball.LinearVelocity.Magnitude < 1) then
        ResetBall() -- 触发重置
    end
end)

测试效果:

运动器

运动器是控制场景组件自动运动的单元,支持设置运动持续时间、到达 / 返程暂停、循环和返程等参数。它提供了开始、停止、暂停、恢复和返程等控制函数,并通过本地事件通知运动开始、停止和返程等状态变化。

WARNING

使用运动器必须先将对应 WorldUnit 的物理类型设置成 Kinematic(运动学)。

lua
-- 假设 MovePart 是已获取到的 WorldUnit 实例
MovePart.BodyType = Enums.BodyType.Kinematic

线性运动器 LinearMotorUnit

线性运动器是一种控制组件沿直线运动的单元,通过设置线速度向量和运动器类型来实现不同模式的直线运动。

API 参考LinearMotorUnit

旋转运动器 AngularMotorUnit

AngularMotorUnit 是一个运动器单元,能够控制其父级组件持续旋转。通过调整角速度向量和运动器类型,可以实现不同方向与模式的旋转运动。

API 参考AngularMotorUnit

其他运动器

更多运动器请查询 BaseMotorUnit 的子类。

API 参考BaseMotorUnit