はじめに
本投稿は[Roblox ムービー演出の作り方(1) MoonAnimator2]、[Roblox ムービー演出の作り方(2) データ構造とエクスポート]にて作成されたアニメーションデータをもとに、ローカルのScriptにて再生する方法を3回に分けて紹介していきます。
また、MoonAnimator2でエクスポートされるデータのうち、MoonAnimator2フォルダ配下にあるデータはアニメーションの各ターゲット(キャラクターやカメラなど)の位置情報と向いている方向になるため、本投稿の紹介とは別にキャラクターのアニメーションは編集して再生する必要があります。
下準備
[Roblox ムービー演出の作り方(2) データ構造とエクスポート]にてエクスポートされたMoonAnimator2のデータはServerStorage配下に格納されているためローカルのScriptからアクセスすることができません。
そのため、ServerStorage配下にあるMoonAnimator2Savesフォルダを、ReplicatedStorage/MoonAnimator2Savesとなる様にReplicatedStorage配下にコピーします。
また、実際にアニメーションを読み込んだり再生するScriptとして以下のファイルを用意します。
StartPlayer/StarterCharacterScripts/LocalScript
手順
MoonAnimtor2のエクスポートされたデータをScriptにて再生する方法の手順として、以下の様に3つの内容に分けています。
- エクスポートされたデータから必要な情報を抜き出す
- 各ターゲットの位置データをフレーム単位に分解
- 再生
では、実際に手順に沿って説明していきます。
エクスポートされたデータから必要な情報を抜き出す
まずはスクリプト内で使用する変数等と、エクスポートされたデータから必要な情報を抜き出して準備するためのSetup関数をLocalScript内に用意します。
Scriptのサンプルについては本記事の下部に記載してありますので、解説と共に参照してください。
MoonAnimtor2フォルダ配下のCFrameオブジェクト(StringValue)のValue要素には、アニメーション全体の情報がJSONデータとして入っています。
このままでは扱いづらいので、JSONデータをHttpService:JSONDecode関数を使用して配列に変換します。①
このJSONデータの構造については[Roblox ムービー演出の作り方(2) データ構造とエクスポート]に記載されていますが、Items配下にアニメーションの各ターゲットの情報が入っているため、その対象となるオブジェクトの名称を取得します。②
また、MoonAnimtor2/CFrameオブジェクトの配下には、Items配下の要素数分のフォルダが1からの連番で存在し、その中に各ターゲットのキーフレーム毎のCFrameのデータ(位置と向き)が入っています。
今回の記事で用意しているデータの場合、Items配下には順番にRig、Rig2、CurrentCameraの3つのターゲットの情報があり、MoonAnimtor2/CFrameの配下にはそれぞれ1、2、3フォルダがありますが、ターゲットの順番とフォルダの順番(添字)がそれぞれ対応しています。
MoonAnimator2が用意してくれるデータは各ターゲットのキーフレーム毎のCFrameのデータなので、このまま特定のキーフレーム時にターゲットに対してCFrameのデータを渡してしまうと見た目上はワープしている様に見えてしまいます。
そのため、キーフレーム毎に用意されたCFrameのデータを元に1フレーム毎のCFrameのデータが必要になるため、別の関数を用意して1フレーム毎のCFrameのデータを準備します。③
StartPlayer/StarterCharacterScripts/LocalScript
-- 各種サービスを取得
local HttpService = game:GetService("HttpService")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
-- アニメーション時以外のカメラのTypeを保持
local currentCameraType = nil
-- アニメーション前のカメラのCFrame
local currentCameraCFrame = nil
-- 総フレーム数を保持
local totalFrameCount = 0
-- アニメーションに使用するデータを入れる配列
local animationDataArray = {}
-- アニメーション用のconnectを保持
local connection = nil
-- アニメーションを実行中か
local isPlayingAnimation = false
-- マウス操作用の処理
local player = Players.LocalPlayer
local mouse = player:GetMouse()
-- セットアップ関数
function Setup()
-- ゲームがロードされるまで待機
repeat wait() until game:IsLoaded()
-- アニメーション全体のデータが格納されたオブジェクトを取得
local animationData = ReplicatedStorage:WaitForChild("MoonAnimator2Saves"):FindFirstChild("CFrame")
-- ①JSONの文字列を配列に変換
local animationInfoArray = HttpService:JSONDecode(animationData.Value)
-- アニメーションの総フレーム数を取得
totalFrameCount = animationInfoArray["Information"]["Length"]
-- アニメーションのターゲット毎に処理
for i, data in ipairs(animationInfoArray["Items"]) do
-- ②ターゲットの名称を取得
local targetName = data["Path"]["InstanceNames"][#data["Path"]["InstanceNames"]]
local targetObject = nil
-- 「CurrentCamera」かどうかで取得方法を分岐
if targetName == "CurrentCamera" then
targetObject = workspace.Camera
else
targetObject = workspace:FindFirstChild(targetName)
end
-- HumanoidRootPartがあるか
local isHaveHRP = false
if targetObject:FindFirstChild("HumanoidRootPart") then
isHaveHRP = true
end
-- ターゲット毎に配列に挿入
animationDataArray[targetName] = {
target = targetObject,
-- ③1フレーム毎の位置情報に分解
frameArray = CreateAnimationFrames(animationData:FindFirstChild(i), totalFrameCount),
isHaveHRP = isHaveHRP
}
end
end
Setup()
次の手順
次回の記事では、キーフレームのCFrameのデータを元に1フレーム毎のCFrameのデータへ分解する処理を解説します。