roblox-characters-animation

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Characters and animation

角色与动画

Character basics

角色基础

  • A player character is a
    Model
    with a
    Humanoid
    ,
    HumanoidRootPart
    (the root; move the character with
    character:PivotTo(cframe)
    ), R15 body parts, and an
    Animate
    LocalScript.
  • Defaults (walk speed, jump, health, R6/R15, collisions, body scaling) are configured in Studio's Avatar Settings window and
    StarterPlayer
    (
    CharacterWalkSpeed
    ,
    CharacterJumpHeight
    or
    CharacterUseJumpPower
    +
    CharacterJumpPower
    ).
  • Custom character: put a
    Model
    named
    StarterCharacter
    in
    StarterPlayer
    . Custom per-player spawns:
    Players.CharacterAutoLoads = false
    , then
    player:LoadCharacterAsync()
    when ready (e.g. after data loads).
    LoadCharacter
    (non-Async) is deprecated.
  • Characters are destroyed and recreated on death/respawn: bind per-character logic in
    CharacterAdded
    .
  • Client-set
    WalkSpeed
    /
    JumpHeight
    are trivially exploitable; enforce limits on the server or use server authority (
    roblox-security
    ,
    roblox-physics
    ).
  • 玩家角色是一个
    Model
    ,包含
    Humanoid
    、
    HumanoidRootPart
    (根部件;使用
    character:PivotTo(cframe)
    移动角色)、R15 身体部件和
    Animate
    LocalScript。
  • 默认值(步行速度、跳跃、生命值、R6/R15、碰撞、身体缩放)在 Studio 的 Avatar Settings 窗口和
    StarterPlayer
    (
    CharacterWalkSpeed
    、
    CharacterJumpHeight
    或
    CharacterUseJumpPower
    +
    CharacterJumpPower
    )中配置。
  • 自定义角色:将名为
    StarterCharacter
    的
    Model
    放入
    StarterPlayer
    。每位玩家的自定义生成方式:设置
    Players.CharacterAutoLoads = false
    ,然后在准备好时(例如数据加载完成后)调用
    player:LoadCharacterAsync()
    。
    LoadCharacter
    (非 Async 版本)已弃用。
  • 角色死亡/重生时会被销毁并重新创建:在
    CharacterAdded
    中绑定每个角色的逻辑。
  • 客户端设置的
    WalkSpeed
    /
    JumpHeight
    很容易被作弊者利用;应在服务器上强制执行限制,或采用服务器权威机制(
    roblox-security
    、
    roblox-physics
    )。

Health and damage (server)

生命值与伤害(服务器)

luau
--!strict
local Players = game:GetService("Players")

local function damage(target: Model, amount: number, source: Player?)
	local humanoid = target:FindFirstChildOfClass("Humanoid")
	if not humanoid or humanoid.Health <= 0 then
		return
	end
	humanoid:SetAttribute("LastDamagedBy", if source then source.UserId else 0)
	humanoid:TakeDamage(amount) -- respects ForceField; use Health -= amount to bypass
end

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid") :: Humanoid
		humanoid.MaxHealth = 150
		humanoid.Health = 150
		humanoid.Died:Once(function()
			local killerId = humanoid:GetAttribute("LastDamagedBy")
			print(`{player.Name} died (killer {killerId})`)
		end)
	end)
end)

return damage
  • Disable default regen by deleting/replacing the
    Health
    script via
    StarterCharacterScripts
    .
  • Humanoid.BreakJointsOnDeath = false
    + ragdoll constraints for ragdolls.
  • States:
    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
    ,
    SetStateEnabled(state, false)
    ,
    StateChanged
    .
    MoveDirection
    ,
    FloorMaterial
    ,
    RootPart
    ,
    SeatPart
    are read-only helpers.
  • humanoid:MoveTo(position)
    walks NPCs (times out after 8 s; re-issue for long paths — see
    roblox-npc-ai
    ).
luau
--!strict
local Players = game:GetService("Players")

local function damage(target: Model, amount: number, source: Player?)
	local humanoid = target:FindFirstChildOfClass("Humanoid")
	if not humanoid or humanoid.Health <= 0 then
		return
	end
	humanoid:SetAttribute("LastDamagedBy", if source then source.UserId else 0)
	humanoid:TakeDamage(amount) -- respects ForceField; use Health -= amount to bypass
end

Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function(character)
		local humanoid = character:WaitForChild("Humanoid") :: Humanoid
		humanoid.MaxHealth = 150
		humanoid.Health = 150
		humanoid.Died:Once(function()
			local killerId = humanoid:GetAttribute("LastDamagedBy")
			print(`{player.Name} died (killer {killerId})`)
		end)
	end)
end)

return damage
  • 要禁用默认生命恢复,请通过
    StarterCharacterScripts
    删除或替换
    Health
    脚本。
  • Humanoid.BreakJointsOnDeath = false
    配合布娃娃约束可实现布娃娃效果。
  • 状态:
    humanoid:ChangeState(Enum.HumanoidStateType.Jumping)
    、
    SetStateEnabled(state, false)
    、
    StateChanged
    。
    MoveDirection
    、
    FloorMaterial
    、
    RootPart
    、
    SeatPart
    是只读辅助属性。
  • humanoid:MoveTo(position)
    可使 NPC 行走(8 秒后超时;长路径需重新发起调用——参见
    roblox-npc-ai
    )。

Appearance

外观

luau
--!strict
local Players = game:GetService("Players")

local function applyUniform(player: Player)
	local character = player.Character
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		return
	end
	local ok, description = pcall(function()
		return Players:GetHumanoidDescriptionFromUserIdAsync(player.UserId)
	end)
	if not ok then
		return
	end
	description.Shirt = 123456 -- asset ids
	description.Pants = 654321
	description.HeightScale = 1.05
	pcall(function()
		humanoid:ApplyDescriptionAsync(description) -- server-side; replicates
	end)
end

return applyUniform
Player:LoadCharacterWithHumanoidDescriptionAsync(description)
spawns directly with an outfit. All the non-Async variants (
ApplyDescription
,
GetHumanoidDescriptionFromUserId
, ...) are deprecated.
luau
--!strict
local Players = game:GetService("Players")

local function applyUniform(player: Player)
	local character = player.Character
	local humanoid = character and character:FindFirstChildOfClass("Humanoid")
	if not humanoid then
		return
	end
	local ok, description = pcall(function()
		return Players:GetHumanoidDescriptionFromUserIdAsync(player.UserId)
	end)
	if not ok then
		return
	end
	description.Shirt = 123456 -- asset ids
	description.Pants = 654321
	description.HeightScale = 1.05
	pcall(function()
		humanoid:ApplyDescriptionAsync(description) -- server-side; replicates
	end)
end

return applyUniform
Player:LoadCharacterWithHumanoidDescriptionAsync(description)
可让角色穿着指定服装直接生成。所有非 Async 变体(
ApplyDescription
、
GetHumanoidDescriptionFromUserId
等)均已弃用。

Animation playback

动画播放

luau
--!strict
local function playAttack(character: Model, animation: Animation): AnimationTrack?
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local animator = humanoid and humanoid:FindFirstChildOfClass("Animator")
	if not animator then
		return nil
	end
	local track = animator:LoadAnimation(animation) -- Humanoid:LoadAnimation is deprecated
	track.Priority = Enum.AnimationPriority.Action
	track.Looped = false
	track:GetMarkerReachedSignal("Hit"):Connect(function(param)
		print("hit frame reached", param) -- apply damage window, play sound, etc.
	end)
	track:Play(0.1) -- fade time
	return track
end

return playAttack
  • Where to play: the local player's own character → play on the client (replicates automatically via its Animator); NPCs → play on the server (or on clients for purely cosmetic, high-count NPCs).
  • Load each
    Animation
    once per Animator and reuse the track; don't call
    LoadAnimation
    every time an action happens (there's a per-Animator track limit). Exception: server authority (query live tracks).
  • Priorities:
    Core < Idle < Movement < Action < Action2 < Action3 < Action4
    . Blend with
    AdjustWeight
    , change speed with
    AdjustSpeed
    , stop with
    Stop(fadeTime)
    .
  • Events:
    track.Stopped
    ,
    track.Ended
    , markers via
    GetMarkerReachedSignal
    (
    KeyframeReached
    is superseded).
  • Animation assets must be owned by (or shared with, via asset permissions) the experience's owner — otherwise they silently fail to play in live servers.
  • Replace defaults by editing the
    Animate
    script's
    StringValue
    /
    Animation
    children (
    animate.run.RunAnim.AnimationId
    ) on
    CharacterAdded
    , or ship a custom
    Animate
    in
    StarterCharacterScripts
    .
  • Procedural:
    IKControl
    (look-at, foot planting, reaching) instead of hand-written joint math.
luau
--!strict
local function playAttack(character: Model, animation: Animation): AnimationTrack?
	local humanoid = character:FindFirstChildOfClass("Humanoid")
	local animator = humanoid and humanoid:FindFirstChildOfClass("Animator")
	if not animator then
		return nil
	end
	local track = animator:LoadAnimation(animation) -- Humanoid:LoadAnimation is deprecated
	track.Priority = Enum.AnimationPriority.Action
	track.Looped = false
	track:GetMarkerReachedSignal("Hit"):Connect(function(param)
		print("hit frame reached", param) -- apply damage window, play sound, etc.
	end)
	track:Play(0.1) -- fade time
	return track
end

return playAttack
  • 在哪里播放:本地玩家自己的角色 → 在客户端播放(通过其 Animator 自动复制);NPC → 在服务器上播放(对于纯视觉效果且数量较多的 NPC,也可以在客户端播放)。
  • 每个
    Animator
    对每条
    Animation
    只应加载一次并重复使用对应的 track;不要在每次动作发生时都调用
    LoadAnimation
    (每个 Animator 的 track 数量有限)。例外:服务器权威场景(查询当前播放的 track)。
  • 优先级:
    Core < Idle < Movement < Action < Action2 < Action3 < Action4
    。使用
    AdjustWeight
    进行混合,使用
    AdjustSpeed
    调整速度,使用
    Stop(fadeTime)
    停止。
  • 事件:
    track.Stopped
    、
    track.Ended
    ,以及通过
    GetMarkerReachedSignal
    触发标记(
    KeyframeReached
    已被取代)。
  • 动画资产必须归体验的所有者所有,或通过资产权限与所有者共享,否则在正式服务器中会静默播放失败。
  • 要替换默认动画,可在
    CharacterAdded
    时编辑
    Animate
    脚本的
    StringValue
    /
    Animation
    子项(
    animate.run.RunAnim.AnimationId
    ),或者在
    StarterCharacterScripts
    中提供自定义
    Animate
    。
  • 程序化动画:使用
    IKControl
    (看向目标、脚部固定、伸手动作),代替手写关节数学计算。

Tweening

补间动画

luau
--!strict
local TweenService = game:GetService("TweenService")

local door = Instance.new("Part")
door.Anchored = true
door.Parent = workspace

local info = TweenInfo.new(0.6, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local open = TweenService:Create(door, info, { CFrame = door.CFrame * CFrame.new(0, 8, 0) })
open.Completed:Once(function(state)
	print("door tween finished:", state)
end)
open:Play()
  • Tween anchored parts or UI. For unanchored/physics objects use constraints.
  • Tweening on the server replicates every frame and stutters: for visual-only motion, tween on each client (the server sets the final state or an attribute clients react to).
  • Models: tween a
    CFrameValue
    and call
    model:PivotTo(value)
    in its
    Changed
    handler, or tween the primary part with the rest welded to it.
  • TweenService:GetValue(alpha, style, direction)
    for custom interpolation;
    SmoothDamp
    for follow motion.
luau
--!strict
local TweenService = game:GetService("TweenService")

local door = Instance.new("Part")
door.Anchored = true
door.Parent = workspace

local info = TweenInfo.new(0.6, Enum.EasingStyle.Quad, Enum.EasingDirection.Out)
local open = TweenService:Create(door, info, { CFrame = door.CFrame * CFrame.new(0, 8, 0) })
open.Completed:Once(function(state)
	print("door tween finished:", state)
end)
open:Play()
  • 对已锚定部件或 UI 使用 Tween。对于未锚定或受物理影响的物体,应使用约束。
  • 在服务器上执行补间会逐帧同步并产生卡顿:对于纯视觉运动,应让每个客户端分别执行补间(由服务器设置最终状态或客户端可响应的属性)。
  • Model:对
    CFrameValue
    执行补间,并在其
    Changed
    处理器中调用
    model:PivotTo(value)
    ;也可以补间主部件,并将其余部件焊接至该主部件。
  • 使用
    TweenService:GetValue(alpha, style, direction)
    实现自定义插值;使用
    SmoothDamp
    实现跟随运动。

Tools

工具

Tool
in
StarterPack
/
Backpack
with a
Handle
part (or
RequiresHandle = false
).
Equipped
,
Unequipped
,
Activated
fire on both client and server (
Activated
comes from the client: validate rate and state on the server). Keep weapon logic in modules and use tags rather than scripts inside every tool clone.
Tool
位于
StarterPack
/
Backpack
中,并包含
Handle
部件(或者设置
RequiresHandle = false
)。
Equipped
、
Unequipped
、
Activated
都会在客户端和服务器上触发(
Activated
来源于客户端:应在服务器上验证调用频率和状态)。将武器逻辑放在 module 中,并使用 tags,而不是在每个工具克隆体中放置脚本。

Character Controller Library (beta)

Character Controller Library(beta)

Roblox's CCL (
require("@rbx/AvatarAbilities")
) replaces the fixed Humanoid state machine with composable abilities (Running, Jumping, Climbing, custom Dash...) coordinated by labels, sensors, conditions (
StartsWhen
/
RunsWhile
with
All
/
Any
/
Not
), conflicts (
Blocks
/
Stops
/
Suspends
), and lifecycle callbacks. Enable it via File → Beta Features and Avatar Settings → Movement → Abilities. Only use it when the project has opted in; APIs may change while in beta. Sketch: references/character-controller-library.md.
Roblox 的 CCL(
require("@rbx/AvatarAbilities")
)使用可组合的 abilities(Running、Jumping、Climbing、自定义 Dash 等)替代固定的 Humanoid 状态机。这些 abilities 通过标签、传感器、条件(
StartsWhen
/
RunsWhile
,配合
All
/
Any
/
Not
)、冲突关系(
Blocks
/
Stops
/
Suspends
)和生命周期回调进行协调。通过 File → Beta Features 和 Avatar Settings → Movement → Abilities 启用。仅当项目选择启用该功能时使用;beta 期间 API 可能发生变化。 大纲:references/character-controller-library.md。

Related skills

相关 skill

roblox-npc-ai
(NPC movement),
roblox-physics
(ragdolls, knockback),
roblox-input
(ability inputs),
roblox-security
(movement/damage validation),
roblox-game-systems
(combat).
roblox-npc-ai
(NPC 移动)、
roblox-physics
(布娃娃、击退)、
roblox-input
(能力输入)、
roblox-security
(移动/伤害验证)、
roblox-game-systems
(战斗)。