はじめに
本投稿は[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のデータへ分解する処理を解説します。