static ForeachSelectionResult CreateAnimatorPrefabImpl(UnityEngine.Object obj) { string project_relative_path = AssetDatabase.GetAssetPath(obj); if (!project_relative_path.EndsWith(".fbx") && !project_relative_path.EndsWith(".FBX")) { Debug.LogError("所选对象不是模型 !!!"); return(ForeachSelectionResult.result_continue); } // 确保有配置文件 string folder = BaseHelp.GetParentDir(project_relative_path); string clip_file_path = string.Format("{0}/MecanimConfig.asset", folder); MecanimConfig mecanim_config = AssetDatabase.LoadAssetAtPath(clip_file_path, typeof(MecanimConfig)) as MecanimConfig; if (!mecanim_config) { return(ForeachSelectionResult.result_continue); } // 创建Animator,添加一个名为"state"的变量 string name = Path.GetFileNameWithoutExtension(project_relative_path); string animator_file_path = string.Format("{0}/{1}.controller", folder, name); AnimatorController controller = AnimatorController.CreateAnimatorControllerAtPath(animator_file_path); controller.AddParameter(MecanimController.STATE_PARAMETER, AnimatorControllerParameterType.Int); List <AnimationClip> clips = new List <AnimationClip>(); AnimatorStateMachine sm = controller.layers[0].stateMachine; UnityEngine.Object[] objects = AssetDatabase.LoadAllAssetsAtPath(project_relative_path); int count = objects.Length; for (int i = 0; i < count; ++i) { UnityEngine.Object one = objects[i]; AnimationClip clip = one as AnimationClip; if (!clip) { continue; } // 排除原始的"__preview__"动作 if (clip.name.StartsWith("__")) { continue; } clips.Add(clip); } // 调整排序和配置一致 clips.Sort ( delegate(AnimationClip c1, AnimationClip c2) { int index_1 = -1; int index_2 = -1; int index_count = mecanim_config.clips.Count; for (int i = 0; i < index_count; ++i) { MecanimClipConfig clip = mecanim_config.clips[i]; if (c1.name == clip.name) { index_1 = i; } else if (c2.name == clip.name) { index_2 = i; } if (index_1 != -1 && index_2 != -1) { break; } } return((index_1 < index_2) ? -1 : 1); } ); // 创建状态 List <string> states = new List <string>(); count = clips.Count; for (int i = 0; i < count; ++i) { // 绑定clip AnimationClip clip = clips[i]; AnimatorState state = sm.AddState(clip.name); state.motion = clip; // 动作切换 AnimatorStateTransition transition = sm.AddAnyStateTransition(state); transition.AddCondition(AnimatorConditionMode.Equals, states.Count, MecanimController.STATE_PARAMETER); transition.canTransitionToSelf = false; transition.duration = 0; states.Add(clip.name); } // 创建预设,添加MecanimController Object template = AssetDatabase.LoadAssetAtPath(project_relative_path, typeof(GameObject)); GameObject instance = Object.Instantiate(template) as GameObject; Animator animator = BaseHelp.EnsureHasComponent <Animator>(instance) as Animator; animator.runtimeAnimatorController = controller; MecanimController mecanim = BaseHelp.EnsureHasComponent <MecanimController>(instance) as MecanimController; mecanim.states = states; // 如果有材质则绑定材质 if (mecanim_config.material != null) { Renderer[] renderers = instance.GetComponentsInChildren <Renderer>(); if (renderers != null) { int renderer_count = renderers.Length; for (int i = 0; i < renderer_count; ++i) { Renderer one = renderers[i]; one.material = (i == 0) ? mecanim_config.material : mecanim_config.material_addition; } } } // 设置初始形态 instance.transform.localRotation = Quaternion.Euler(mecanim_config.rotation); string prefab_path = string.Format("{0}/{1}.prefab", folder, name); PrefabUtility.SaveAsPrefabAsset(instance, prefab_path); Object.DestroyImmediate(instance, true); return(ForeachSelectionResult.result_none); }
static ForeachSelectionResult BakeGPUSkinImpl(UnityEngine.Object obj) { string project_relative_path = AssetDatabase.GetAssetPath(obj); string folder = BaseHelp.GetParentDir(project_relative_path); string file_name = Path.GetFileNameWithoutExtension(project_relative_path); Object template = AssetDatabase.LoadAssetAtPath <Object>(project_relative_path) as Object; GameObject go = Object.Instantiate(template) as GameObject; Animator animator = go.GetComponent <Animator>(); if (animator == null) { return(ForeachSelectionResult.result_continue); } SkinnedMeshRenderer smr = go.GetComponentInChildren <SkinnedMeshRenderer>(); if (smr == null) { return(ForeachSelectionResult.result_continue); } AnimatorController animator_controller = (AnimatorController)animator.runtimeAnimatorController; if (animator_controller == null) { return(ForeachSelectionResult.result_continue); } Mesh baked_mesh = new Mesh(); int vertices_count = smr.sharedMesh.vertexCount; // 贴图横坐标为顶点索引,纵坐标为采样帧索引 int texture_width = Mathf.NextPowerOfTwo(vertices_count); // 动作区段配置 List <GPUSkinSection> sections = new List <GPUSkinSection>(); // 先计算贴图的高并创建贴图 int texture_height = 0; float total_time = 0; AnimationClip[] clips = animator_controller.animationClips; int clip_count = clips.Length; for (int i = 0; i < clip_count; ++i) { AnimationClip clip = clips[i]; int cur_clip_frame = (int)(clip.frameRate * clip.length); texture_height += cur_clip_frame; total_time += clip.length; } Texture2D sample_texture = new Texture2D(texture_width, texture_height, TextureFormat.RGBAHalf, false); int texture_cur_y = 0; for (int i = 0; i < clip_count; ++i) { AnimationClip clip = clips[i]; int cur_clip_frame = (int)(clip.frameRate * clip.length); float per_frame_time = clip.length / cur_clip_frame; GPUSkinSection gpu_skin_section = new GPUSkinSection(); gpu_skin_section.start_row = texture_cur_y; gpu_skin_section.end_row = texture_cur_y + cur_clip_frame - 1; sections.Add(gpu_skin_section); float sample_time = 0; for (int j = 0; j < cur_clip_frame; ++j) { // 设置采样时间并烘焙 clip.SampleAnimation(go, sample_time); smr.BakeMesh(baked_mesh); // 写入顶点信息 for (int k = 0; k < vertices_count; ++k) { Vector3 vertex = baked_mesh.vertices[k]; sample_texture.SetPixel(k, texture_cur_y + j, new Color(vertex.x, vertex.y, vertex.z)); } sample_time += per_frame_time; } texture_cur_y += cur_clip_frame; } sample_texture.Apply(); // 输出贴图 string texture_output = string.Format("{0}/{1}_gpu_skin.asset", folder, file_name); AssetDatabase.CreateAsset(sample_texture, texture_output); // 创建材质 Material mat = new Material(Shader.Find("LYGame/GPUSkin")); mat.SetTexture("_MainTex", smr.sharedMaterial.mainTexture); mat.SetTexture("_AnimationMap", sample_texture); mat.SetFloat("_TotalTime", total_time); // 默认开启GPUInstancing mat.enableInstancing = true; string mat_output = string.Format("{0}/{1}_gpu_skin.mat", folder, file_name); AssetDatabase.CreateAsset(mat, mat_output); // 创建预设 GameObject go_prefab = new GameObject(); go_prefab.AddComponent <MeshFilter>().sharedMesh = smr.sharedMesh; go_prefab.AddComponent <MeshRenderer>().sharedMaterial = mat; GPUSkinController gpu_skin_controller = go_prefab.AddComponent <GPUSkinController>(); gpu_skin_controller.sections = sections; string prefab_output = string.Format("{0}/{1}_gpu_skin.prefab", folder, file_name); PrefabUtility.SaveAsPrefabAsset(go_prefab, prefab_output); // 销毁临时创建的GameObject Object.DestroyImmediate(go); Object.DestroyImmediate(go_prefab); return(ForeachSelectionResult.result_none); }