赞
踩
uinity 创建一个空的gameobject 挂在一个自定义脚本AvatarCreator,AvatarCreator实现代码方式动态创建符合HumanBodyBones的骨骼人体模型,模型包含完整的骨骼节点,创建完骨骼后创建显示部分,用长方体代替骨骼,关节处用球体,头部用球体,眼睛用球体,并用AvatarBuilder.BuildHumanAvatar创建Avatar绑定到动画,AvatarCreator同时包含保存骨骼肢体动作信息为json文件,并能从json文件加载avatar姿势的完整信息
using UnityEngine;
using UnityEngine.Animations;
using System.Collections.Generic;
using System.IO;
public class AvatarCreator : MonoBehaviour
{
// 定义骨骼节点列表
private Dictionary<HumanBodyBones, Transform> boneDictionary = new Dictionary<HumanBodyBones, Transform>();
void Start() { // 创建骨骼模型 CreateAvatar(); } void CreateAvatar() { // 创建一个空的 GameObject 作为根节点 GameObject avatar = new GameObject("Avatar"); // 遍历 HumanBodyBones 中的所有枚举值 foreach (HumanBodyBones boneType in System.Enum.GetValues(typeof(HumanBodyBones))) { // 跳过不使用的骨骼类型 if (boneType == HumanBodyBones.LastBone) continue; // 创建骨骼节点的可视化表示 GameObject boneObject = new GameObject(boneType.ToString()); boneObject.transform.parent = avatar.transform; boneObject.transform.localPosition = Vector3.zero; // 创建关节的球体 GameObject jointSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); jointSphere.name = boneType.ToString() + "_Joint"; jointSphere.transform.parent = boneObject.transform; jointSphere.transform.localPosition = Vector3.zero; jointSphere.transform.localScale = new Vector3(0.1f, 0.1f, 0.1f); // 球体的大小 Destroy(jointSphere.GetComponent<Collider>()); // 移除碰撞体,使其不影响其他物体的碰撞检测 // 如果是头部,添加一个球体表示头部 if (boneType == HumanBodyBones.Head) { GameObject headSphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); headSphere.transform.parent = boneObject.transform; headSphere.transform.localPosition = Vector3.zero; headSphere.transform.localScale = new Vector3(0.2f, 0.2f, 0.2f); // 头部球体的大小 Destroy(headSphere.GetComponent<Collider>()); // 移除碰撞体,使其不影响其他物体的碰撞检测 // 添加眼睛 GameObject leftEye = GameObject.CreatePrimitive(PrimitiveType.Sphere); leftEye.transform.parent = headSphere.transform; leftEye.transform.localPosition = new Vector3(-0.05f, 0.05f, 0.1f); leftEye.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); Destroy(leftEye.GetComponent<Collider>()); GameObject rightEye = GameObject.CreatePrimitive(PrimitiveType.Sphere); rightEye.transform.parent = headSphere.transform; rightEye.transform.localPosition = new Vector3(0.05f, 0.05f, 0.1f); rightEye.transform.localScale = new Vector3(0.05f, 0.05f, 0.05f); Destroy(rightEye.GetComponent<Collider>()); } // 将骨骼节点添加到字典中 boneDictionary.Add(boneType, boneObject.transform); } // 创建并绑定 Avatar HumanDescription humanDescription = CreateHumanDescription(avatar); Avatar humanAvatar = AvatarBuilder.BuildHumanAvatar(avatar, humanDescription); Animator animator = avatar.AddComponent<Animator>(); animator.avatar = humanAvatar; } HumanDescription CreateHumanDescription(GameObject avatar) { List<HumanBone> humanBones = new List<HumanBone>(); List<SkeletonBone> skeletonBones = new List<SkeletonBone>(); foreach (KeyValuePair<HumanBodyBones, Transform> pair in boneDictionary) { HumanBone humanBone = new HumanBone { boneName = pair.Key.ToString(), humanName = pair.Key.ToString(), limit = new HumanLimit { useDefaultValues = true } }; humanBones.Add(humanBone); SkeletonBone skeletonBone = new SkeletonBone { name = pair.Key.ToString(), position = pair.Value.localPosition, rotation = pair.Value.localRotation, scale = pair.Value.localScale }; skeletonBones.Add(skeletonBone); } return new HumanDescription { human = humanBones.ToArray(), skeleton = skeletonBones.ToArray(), upperArmTwist = 0.5f, lowerArmTwist = 0.5f, upperLegTwist = 0.5f, lowerLegTwist = 0.5f, armStretch = 0.05f, legStretch = 0.05f, feetSpacing = 0.0f, hasTranslationDoF = false }; } // 保存骨骼肢体动作信息为 JSON 文件 public void SaveAvatarPose(string filePath) { List<SerializableTransform> boneTransforms = new List<SerializableTransform>(); foreach (KeyValuePair<HumanBodyBones, Transform> pair in boneDictionary) { SerializableTransform serializableTransform = new SerializableTransform(pair.Key.ToString(), pair.Value); boneTransforms.Add(serializableTransform); } string json = JsonUtility.ToJson(new SerializableTransformList { transforms = boneTransforms }); File.WriteAllText(filePath, json); } // 从 JSON 文件加载 avatar 姿势的完整信息 public void LoadAvatarPose(string filePath) { if (File.Exists(filePath)) { string json = File.ReadAllText(filePath); SerializableTransformList boneTransforms = JsonUtility.FromJson<SerializableTransformList>(json); foreach (SerializableTransform serializableTransform in boneTransforms.transforms) { HumanBodyBones boneType; if (System.Enum.TryParse(serializableTransform.boneName, out boneType) && boneDictionary.ContainsKey(boneType)) { boneDictionary[boneType].localPosition = serializableTransform.position; boneDictionary[boneType].localRotation = serializableTransform.rotation; boneDictionary[boneType].localScale = serializableTransform.scale; } } } else { Debug.LogError("File does not exist: " + filePath); } } [System.Serializable] public class SerializableTransform { public string boneName; public Vector3 position; public Quaternion rotation; public Vector3 scale; public SerializableTransform(string name, Transform transform) { boneName = name; position = transform.localPosition; rotation = transform.localRotation; scale = transform.localScale; } } [System.Serializable] public class SerializableTransformList { public List<SerializableTransform> transforms; }
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。