diff --git a/Assets/UniGLTF/Runtime/UniHumanoid/AvatarDescription.cs b/Assets/UniGLTF/Runtime/UniHumanoid/AvatarDescription.cs index d9ac4c47b..061c60b4e 100644 --- a/Assets/UniGLTF/Runtime/UniHumanoid/AvatarDescription.cs +++ b/Assets/UniGLTF/Runtime/UniHumanoid/AvatarDescription.cs @@ -9,6 +9,7 @@ using System.Collections.Generic; namespace UniHumanoid { + // TODO: BoneLimit.cs に分ける(v0.104以降) [Serializable] public struct BoneLimit { @@ -19,26 +20,34 @@ namespace UniHumanoid public Vector3 max; public Vector3 center; public float axisLength; - private static string[] cashedHumanTraitBoneName = null; - private static readonly Dictionary cachedHumanBodyBonesToBoneNameMap = - new Dictionary(); - static BoneLimit() - { - // 呼び出し毎にGCが発生するのでキャッシュする - string[] boneNames = HumanTrait.BoneName; - cashedHumanTraitBoneName = new string[boneNames.Length]; - for (var i = 0; i < boneNames.Length; i++) - { - cashedHumanTraitBoneName[i] = boneNames[i].Replace(" ", ""); - } - } + + // HumanTrait.BoneName は HumanBodyBones.ToString とほぼ一対一に対応するが、 + // 指のボーンについては " " の有無という微妙な違いがある。 + // このスペースは AvatarBuilder.BuildHumanAvatar において必用であり、 + // HumanBodyBones.ToString と区別する必要がある。 + // + // また、下記についてGCが発生するのでキャッシュします。 + // * HumanTrait.BoneName + // * traitName.Replace + // * Enum.Parse + // + private static readonly Dictionary cachedHumanBodyBonesToBoneTraitNameMap = + HumanTrait.BoneName.ToDictionary( + traitName => (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), traitName.Replace(" ", "")), + traitName => traitName); + + // 逆引き + private static readonly Dictionary cachedBoneTraitNameToHumanBodyBonesMap = + HumanTrait.BoneName.ToDictionary( + traitName => traitName, + traitName => (HumanBodyBones)Enum.Parse(typeof(HumanBodyBones), traitName.Replace(" ", ""))); public static BoneLimit From(HumanBone bone) { return new BoneLimit { - humanBone = (HumanBodyBones) Enum.Parse(typeof(HumanBodyBones), bone.humanName.Replace(" ", ""), true), + humanBone = cachedBoneTraitNameToHumanBodyBonesMap[bone.humanName], boneName = bone.boneName, useDefaultValues = bone.limit.useDefaultValues, min = bone.limit.min, @@ -48,32 +57,12 @@ namespace UniHumanoid }; } - public static String ToHumanBoneName(HumanBodyBones b) - { - if (cachedHumanBodyBonesToBoneNameMap.TryGetValue(b, out string result)) - { - return result; - } - - var bs = b.ToString(); - foreach (var x in cashedHumanTraitBoneName) - { - if (x == bs) - { - cachedHumanBodyBonesToBoneNameMap[b] = x; - return x; - } - } - - throw new KeyNotFoundException(); - } - public HumanBone ToHumanBone() { return new HumanBone { boneName = boneName, - humanName = ToHumanBoneName(humanBone), + humanName = cachedHumanBodyBonesToBoneTraitNameMap[humanBone], limit = new HumanLimit { useDefaultValues = useDefaultValues,