PROJECT 01

1 / 11

Roblox Studioで剣を振るアニメーションを作る方法

Clip EditorのGUIでR15の斜め斬りを作り、クリック1回で再生しよう。関節角度をcodeで書く必要はない。

公開日 更新日
Roblox StudioのPlay画面で剣を身体の正面へ斜めに振り抜くR15 avatar

Blenderで作ったOriginalSwordを装備する記事の続きとして、クリックまたはタップ1回で完結する通常攻撃を作る。関節の角度はcodeへ書かない。Roblox StudioのClip Editorでavatarを直接動かし、見たままの姿勢を保存する。

実際のPlayで剣を頭上へ引き、身体の正面を斜めに振り抜いて構えへ戻る動き

今回は見た目だけを完成させる。TrainingDummyへダメージを与える処理は次の記事で追加する。

1. Clip Editorを開く

Playを止め、上部のAvatar > Character > Generate Rigを開く。R15のblock rigを追加し、ExplorerでSwordAnimationRigへ名前を変えよう。次にAvatar > Clip Editorを開き、rigを選ぶ。

Studioの下に表示される画面がAnimation Editorだ。現在のtoolbarでは入口がClip Editorと表示されるが、Robloxの公式ドキュメントではAnimation Editorという名前で説明されている。

Clip EditorでR15 rigを選び、下部にAnimation Editorのtimelineを開いたStudio画面

animation名はSwordSlashPreview、長さは0.92秒にする。timelineの青い縦線を動かし、viewportのrigをRotateで回すと、その時刻へkeyframeが保存される。最初は剣がないrigのままでよい。PlayではOriginalSwordが右手に追従する。

Tip — keyframeは「その時刻の姿勢」

codeの数値ではなく、rigを回した結果をtimelineへ記録する点だ。Studioがkeyframeの間を自動でつなぐ。

2. 5つの主ポーズを画面で作る

まず次の5点だけを作る。いきなり細かな調整を増やさず、Editorの再生ボタンまたはSpaceで毎回つながりを見よう。

  1. 0.00秒 READY — 右手を身体の前へ置き、剣が斜めに見える構え
  2. 0.22秒 WINDUP — 腰と胸を少しひねり、右手を頭の右上へ引く
  3. 0.34秒 CUT — 右手を胸の前から左下へ通し、刃の長さが斜めに見える姿勢
  4. 0.54秒 FOLLOW — 右手を左腰の前まで抜き、勢いを止めない姿勢
  5. 0.92秒 READY — 0秒と同じ構え

実際のPlayで構え、頭上のため、正面を横切る斬り、左腰前の抜けを並べた4姿勢

動かす順番はLowerTorso > UpperTorso > RightUpperArm > RightLowerArm > RightHandにする。中心から手先へ進めると、腕だけを振る機械的な動きになりにくい。左腕は右腕と反対へ少し開き、balanceを取る。

一番大切なのはCUTだ。剣先をcameraへ向けると、刃が短く見えて突きのようになる。右手を胸の前へ置きながら、刃は右上から左下へ斜めに見せる。avatarの真横でも背中側でもなく、胸の少し前を通す。

CUTで刃の長さを見せながら身体の正面を右上から左下へ通すPlay画面

5点が自然につながったら、0.12 / 0.28 / 0.40 / 0.72秒へ調整用keyframeを追加する。0.12では腰だけを先に動かし、0.28で斬り始め、0.40で腕を左下へ抜き、0.72から構えへ戻す。主ポーズを変えるのではなく、身体の部位が同時に動き出す不自然さを減らす4点だ。

keyframeを右クリックしてCubicV2を選ぶ。WINDUPまではIn、CUTからFOLLOWはOut、戻りはInOutを目安にする。斬る直前に加速し、斬った後は少し余韻を残せる。

3. HitStartとHitEndをGUIで置く

Animation Editorの設定からShow Animation Eventsをonにする。timelineを0.28秒へ合わせ、Edit Animation Events > Add EventHitStartを追加する。同じ手順で0.40秒HitEndを置く。Animation eventsの公式手順でも、eventはtimeline上の名前付きの時刻として作成する。

Animation Editorのtimeline設定からAnimation Eventsを表示する位置

eventは姿勢を変えない。次の記事の当たり判定と、今回のtrailへ「ここから斬る」「ここで斬り終わる」と知らせる。

READY、WINDUP、ACTIVE、RECOVERYとHitStart、HitEndの位置

Editorの… > Set Animation PriorityActionを選ぶ。その後… > Save AsSwordSlashPreviewとしてlocal保存する。保存したKeyframeSequenceServerStorageに作られる。見つからない場合はSwordAnimationRig > AnimSavesの参照先を開こう。clientのlocal testで読めるよう、そのsequenceをReplicatedStorage直下へ複製し、名前をSwordSlashPreviewにする。asset uploadは不要だ。

4. ACTIVEだけtrailを出す

OriginalSword > HandleAttachmentを2つ追加し、TrailTopTrailBottomにする。この剣ではPositionを(0, 2.5, 0)(0, -2.5, 0)へ置く。次にTrailを追加してSlashTrailへ変え、Attachment0Attachment1へ2点を指定する。Enabledはoff、Lifetime0.10にしよう。

Tool.Gripは前の記事で決めた値のまま、animation中に変更しない。右手と剣はRightGripでつながるため、GUIで作った肩、肘、手首の動きへ剣も追従する。

右手と持ち手の接触を保ち、animation中にTool.Gripを回さない固定位置

5. 保存したanimationを再生する

StarterPack > OriginalSwordLocalScriptを追加し、SwordAnimationClientへ名前を変える。codeの役目はGUIで作ったclipを読み、markerに合わせてtrailを切り替えることだけだ。関節角度を作るCFrame.Angles()は1行もない。

local AnimationClipProvider = game:GetService("AnimationClipProvider")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

local player = Players.LocalPlayer
local tool = script.Parent
local trail = tool.Handle:WaitForChild("SlashTrail")
local sequence = ReplicatedStorage:WaitForChild("SwordSlashPreview")
local track
local busy = false

local function getTrack()
	if track then return track end

	local character = player.Character or player.CharacterAdded:Wait()
	local animator = character.Humanoid:WaitForChild("Animator")
	local animation = Instance.new("Animation")
	animation.AnimationId =
		AnimationClipProvider:RegisterAnimationClip(sequence)

	track = animator:LoadAnimation(animation)
	track.Priority = Enum.AnimationPriority.Action

	track:GetMarkerReachedSignal("HitStart"):Connect(function()
		trail.Enabled = true
	end)
	track:GetMarkerReachedSignal("HitEnd"):Connect(function()
		trail.Enabled = false
	end)
	track.Stopped:Connect(function()
		trail.Enabled = false
		busy = false
	end)

	return track
end

tool.Activated:Connect(function()
	if busy then return end
	busy = true
	getTrack():Play(0.04)
end)

tool.Unequipped:Connect(function()
	if track and track.IsPlaying then
		track:Stop(0.08)
	end
end)

AnimationClipProvider:RegisterAnimationClip()は、localのKeyframeSequenceを現在のStudio testで再生する一時IDへ変える。poseや速度を決めているのはGUIのclipであり、このcodeではない。将来animationを公開する場合はasset IDへ置き換えられるが、今回は公開しない。

busyは再生中の連打を無視する印だ。track.Stoppedでfalseへ戻るため、1入力につき1回だけ振る。

6. 正面からPlay確認する

Playを開始し、OriginalSwordを装備して1回クリックする。最初は歩かず、avatarを正面から見る。

確認するのは次の5点だ。

  1. 剣を頭上へ引く
  2. 右手が胸の前へ入る
  3. 刃の長さが見える斜めの軌道で右上から左下へ通る
  4. 左腰の前まで振り抜く
  5. 約0.92秒後に構えへ戻る

振っている途中に連打してもmotionが重ならず、TrainingDummyのHPが減らなければ今回の結果は完成だ。剣が顔へ突き刺さるように短く見える場合は、codeではなくAnimation Editorへ戻り、0.34秒RightHandを回して刃の側面を見せよう。

うまく動かないとき

  • 腕が動かない場合は、editor rigとPlay中のavatarがどちらもR15か確認する
  • timelineが空の場合は、SwordAnimationRigを選んでからClip Editorを開き直す
  • SwordSlashPreviewが見つからない場合は、ReplicatedStorage直下の名前を確認する
  • markerが反応しない場合は、空白なしのHitStartHitEndへ戻す
  • 剣が身体の横へ逃げる場合は、CUTFOLLOWの右手を胸と左腰の前へ寄せる
  • 剣がcameraを向く場合は、0.34秒の手首を回し、刃の長さが斜めに見える向きへ直す

これで、GUIで作った斬撃を1入力から1回再生できた。次はHitStartからHitEndの間だけserverが前方を調べ、TrainingDummyへ25ダメージを与える。

公式リファレンス

画像の拡大表示