本日はMRTK調査枠です。
MRTKでは[Input Recording Service]と呼ばれる機能が実装されています。
[Input Recording Service]はユーザーの動きを記録・保存する機能で[Input Simulation Service]を用いてUnityエディタ内で再生することができます。
今回はこれを勉強しながらアプリ内でユーザーの動きを録画してみます。
その①はドキュメントを読み解きながら各サービスの概要をつかみました。
その②では実際にアプリで記録を行いUnityエディタ内で再生を行いました。
今回はコードを読み解きながらどのようなデータを記録しているのか見ていきます。
〇InputRecordingControls
記録を行う際に呼び出されるコンポーネントは
Mixed Reality Toolkit Foundation/SDK/Features/UX/Scripts/Utilities内の[InputRecordingControls.cs]の[StartRecording()]になります。

public void StartRecording()
{
eyeGazeProvider = CoreServices.InputSystem.EyeGazeProvider;
IsRecording = true;
frameRate = InputRecordingProfile.FrameRate;
frameInterval = 1f / frameRate;
nextFrame = Time.time + frameInterval;
if (UseBufferTimeLimit)
{
PruneBuffer();
}
if (!unlimitedRecordingStartTime.HasValue)
{
unlimitedRecordingStartTime = Time.time;
}
OnRecordingStarted?.Invoke();
}
ここではフレームレートなどを定義し[IsRecording]をTrueに変えています。
これにより[LateUpdate]無いの処理が走り[RecordKeyframe()]が実行されます。
public override void LateUpdate()
{
if (IsEnabled && IsRecording && Time.time > nextFrame)
{
EndTime = Time.time;
nextFrame += frameInterval * (Mathf.Floor((Time.time - nextFrame) * frameRate) + 1f);
if (UseBufferTimeLimit)
{
PruneBuffer();
}
RecordKeyframe();
}
}
[RecordKeyframe()]で実際の記録が行われています。
ここで各Inputごとの処理関数を実行しています。例えばHandTrackingの記録を行う場合[RecordInputHandData(Handedness.Left)]が実行されます。
private void RecordKeyframe()
{
float time = Time.time;
var profile = InputRecordingProfile;
recordingBuffer.NewKeyframe(time);
if (profile.RecordHandData)
{
RecordInputHandData(Handedness.Left);
RecordInputHandData(Handedness.Right);
}
MixedRealityPose cameraPose;
if (profile.RecordCameraPose && CameraCache.Main)
{
cameraPose = new MixedRealityPose(CameraCache.Main.transform.position, CameraCache.Main.transform.rotation);
recordingBuffer.SetCameraPose(cameraPose);
}
else
{
cameraPose = new MixedRealityPose(Vector3.zero, Quaternion.identity);
}
if (profile.RecordEyeGaze)
{
if (eyeGazeProvider != null)
{
recordingBuffer.SetGazeRay(eyeGazeProvider.LatestEyeGaze);
}
else
{
recordingBuffer.SetGazeRay(new Ray(cameraPose.Position, cameraPose.Forward));
}
}
}
[RecordInputHandData]を見ていきます。
private void RecordInputHandData(Handedness handedness)
{
float time = Time.time;
var profile = InputRecordingProfile;
var hand = HandJointUtils.FindHand(handedness);
...
if (isTracked)
{
for (int i = 0; i < ArticulatedHandPose.JointCount; ++i)
{
if (hand.TryGetJoint((TrackedHandJoint)i, out MixedRealityPose jointPose))
{
recordingBuffer.SetJointPose(handedness, (TrackedHandJoint)i, jointPose);
}
}
}
}
ここで記録を行っている部分は次の一行になります。
recordingBuffer.SetJointPose(handedness, (TrackedHandJoint)i, jointPose);
SetJointPoseではHandTrackingによって取得される各Jointが記録されていることがわかります。

以上でRecordServiceを読み解いていきました。
実際はバイナリーデータで書き出されるためもう少し読み解いていきたいです。