見出し画像

VRMお人形遊びのポーズ画像をUnityで使う方法

VRMお人形遊び?

概要

以前に以下のような記事を書きました。

この記事ではポーズテキストファイルでしたが、恐らくポーズ画像の方がご利用頂いている方が多いと思われますので、ポーズ画像に対応した方法を記載します。

コード

ファイル名はなんでも良いので、Unity上にスクリプトファイルを作成して、以下をコピーペーストしてください。

using System;
using System.IO;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Animator), true)]

public class SetPose : Editor
{
   Animator Anim;
   List<HumanBodyBones> Bones;

   void OnEnable()
   {
       Anim = target as Animator;

       Bones = new List<HumanBodyBones>();
       Bones.Add(HumanBodyBones.Head);
       Bones.Add(HumanBodyBones.Neck);
       Bones.Add(HumanBodyBones.Hips);
       Bones.Add(HumanBodyBones.Spine);
       Bones.Add(HumanBodyBones.Chest);
       Bones.Add(HumanBodyBones.UpperChest);
       Bones.Add(HumanBodyBones.LeftUpperArm);
       Bones.Add(HumanBodyBones.LeftLowerArm);
       Bones.Add(HumanBodyBones.LeftHand);
       Bones.Add(HumanBodyBones.RightUpperArm);
       Bones.Add(HumanBodyBones.RightLowerArm);
       Bones.Add(HumanBodyBones.RightHand);
       Bones.Add(HumanBodyBones.LeftUpperLeg);
       Bones.Add(HumanBodyBones.LeftLowerLeg);
       Bones.Add(HumanBodyBones.LeftFoot);
       Bones.Add(HumanBodyBones.RightUpperLeg);
       Bones.Add(HumanBodyBones.RightLowerLeg);
       Bones.Add(HumanBodyBones.RightFoot);
   }

   public override void OnInspectorGUI()
   {
       base.OnInspectorGUI();

       EditorGUILayout.LabelField("Set Pose Image");

       if (GUILayout.Button("Open Pose Image"))
       {
           var path = EditorUtility.OpenFilePanel("Select Pose Image", "", "png");
           if (!string.IsNullOrEmpty(path))
           {
               OpenPoseImage(path);
           }
       }
   }

   void OpenPoseImage(string path)
   {
       var tex = new Texture2D(1, 1);
       var img = File.ReadAllBytes(path);

       tex.LoadImage(img);

       // ポーズ画像チェック
       var color = tex.GetPixels();
       var pose = Color2Byte(color[0]);
       if (pose[0] == 'p' && pose[1] == 'o' && pose[2] == 's' && pose[3] == 'e')
       {
           for (int i = 0; i < Bones.Count; i++)
           {
               // ポーズ取得
               var index = i * 3 + 1;
               byte[] byte_x = Color2Byte(color[index + 0]);
               byte[] byte_y = Color2Byte(color[index + 1]);
               byte[] byte_z = Color2Byte(color[index + 2]);
               var float_x = BitConverter.ToSingle(byte_x, 0);
               var float_y = BitConverter.ToSingle(byte_y, 0);
               var float_z = BitConverter.ToSingle(byte_z, 0);

               // ポーズ適用
               var t = Anim.GetBoneTransform(Bones[i]);
               if (t != null && !float.IsNaN(float_x) && !float.IsNaN(float_y) && !float.IsNaN(float_z))
               {
                   t.localEulerAngles = new Vector3(float_x, float_y, float_z);
               }
           }
       }
   }

   byte[] Color2Byte(Color color)
   {
       byte[] byte4 = {
           (byte)(color.r * byte.MaxValue),
           (byte)(color.g * byte.MaxValue),
           (byte)(color.b * byte.MaxValue),
           (byte)(color.a * byte.MaxValue)
       };
       return byte4;
   }
}

使い方

Animatorを持つモデルに対してポーズを適用することができます。先述のコードにより、Animatorの一番下にOpen Pose Imageというボタンが追加されています。それをクリックすると、ファイル選択画面が開くので、ポーズ画像を選択して、モデルにポーズを適用することができます。

画像1

画像2

画像3

© Unity Technologies Japan/UCL

この記事が気に入ったらサポートをしてみませんか?