#07 VRMお手軽ポーズのjsonをUnityで読み込む https://gyazo.com/f1b5a7df1986070302cb4a075fc0a1cfhttps://gyazo.com/a3228910606f9f0d1218eb3cad2f5f4e
基本情報
ポーズJSONデータの取得
VRMPoseは以下のような構造になっています。
code:json
{
ボーン名 : {
},
}
rotationは各ボーンの回転のクォータニオンです。
positionは省略可能です。
VRMへのget/setは以下の関数を使用します。
VRMPoseをpositionを削除しjsonとして出力しています。
code:js
UnityでのJSONデータの読み込み
json の構造を記述する
ファイルパスを指定してstringとして読みこむ
JsonUtilityではあらかじめ読み込むJSONを記述する必要があります。
読み込むJSONデータの例
code:json
{
chest:{
},
...
}
これのJSONの構造を定義するクラスを作成します。
ネストされている要素はSerializableなクラス作成してメンバに含めれば良いみたいです。
code:cs
public class PoseItem
{
public BoneItem chest;
...
}
public class BoneItem
{
public float[] rotation;
}
json -> PoseItem として読み込みます。
インスペクタからfilePathを設定
jsonファイルを文字列として読み込み
JsonUtility.FromJson<PoseItem>でPoseItemのインスタンス化
code:cs
public string filePath;
public void reload()
{
string json = File.ReadAllText(filePath);
PoseItem poseItem = JsonUtility.FromJson<PoseItem>(json);
// applyPose(poseItem);
}
VRMモデルにポーズを適用
foreachでPoseItemの各BoneItemを取得して関節角を適用する処理を行います。
全てのBoneItemに対して処理を行うためにType.GetFields()をしています・・
ほんとうにこれでいいんですかね
code:c#
private Animator humanoidAnimator;
private void applyPose(PoseItem poseItem)
{
humanoidAnimator = GetComponent<Animator>();
Type type = poseItem.GetType();
foreach (FieldInfo field in type.GetFields())
{
BoneItem boneItem = (BoneItem)field.GetValue(poseItem);
if (boneItem.rotation != null)
{
applyBoneRotaiton(field.Name, boneItem.rotation);
}
}
}
Animator.GetBoneTransform(bone)で関節のtransformを取得し角度を代入します。
three.jsとUnityで座標系が違うのでそのままクォータニオンを代入せずに変換する必要があります。 code:cs
private void applyBoneRotaiton(string name, float[] rotation)
{
if (humanoidAnimator != null)
{
string boneName = Char.ToUpper(name0) + name.Substring(1); HumanBodyBones bone =(HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), boneName);
var boneTrans = humanoidAnimator.GetBoneTransform(bone);
if (boneTrans != null)
{
boneTrans.localRotation = new Quaternion(-rotation0, -rotation1, rotation2, rotation3); }
}
}
filePathをinspectorからドラッグ&ドロップで設定できるようにする
filePathを入力するのが面倒なのでインスペクタからD&Dで設定できるようにします。
やり方は
そのままです。
ついでにpose読み込みを行うようにしました。
code:cs
...
m_FilePath.stringValue = AssetDatabase.GetAssetPath(draggedObject);
VRMPoseImporter targetComp = target as VRMPoseImporter;
targetComp.loadJson(AssetDatabase.GetAssetPath(draggedObject));
...
使い方
https://gyazo.com/f1b5a7df1986070302cb4a075fc0a1cf
VRMPoseImporterEditor.csをEditorフォルダに配置
VRMPoseImporter.csをVRMのモデルにアタッチ
問題がなければポーズが変わるはずです。
参考
おわり。