| | |
| | | using UnityEngine; |
| | | using System.Collections.Generic; |
| | | using UnityEditor; |
| | | using UnityEditor.Animations; |
| | | using System.IO; |
| | | |
| | | public class ResourcesBuilder |
| | | { |
| | | protected const byte param_NoExist = 1; |
| | | protected const byte param_Prefab = 2; |
| | | protected const byte param_Clip = 4; |
| | | protected const byte param_AnimatorController = 8; |
| | | |
| | | protected class MountPointInfo |
| | | { |
| | | public string path; |
| | | public string name; |
| | | public Vector3 localPosition; |
| | | public Quaternion localRotation; |
| | | public Vector3 localScale; |
| | | } |
| | | |
| | | protected class ColliderInfo |
| | | { |
| | | public Vector3 center; |
| | | public float radius; |
| | | public float height; |
| | | } |
| | | |
| | | public static int buildParams = 0; |
| | | |
| | | public static bool OnlyBuildNoExist |
| | | { |
| | | get |
| | | { |
| | | return (buildParams & param_NoExist) != 0; |
| | | } |
| | | |
| | | set |
| | | { |
| | | if (value) |
| | | { |
| | | buildParams |= param_NoExist; |
| | | } |
| | | else |
| | | { |
| | | buildParams &= ~param_NoExist; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static bool IsBuildPrefab |
| | | { |
| | | get |
| | | { |
| | | return (buildParams & param_Prefab) != 0; |
| | | } |
| | | set |
| | | { |
| | | if (value) |
| | | { |
| | | buildParams |= param_Prefab; |
| | | } |
| | | else |
| | | { |
| | | buildParams &= ~param_Prefab; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static bool IsBuildAnimationClip |
| | | { |
| | | get |
| | | { |
| | | return (buildParams & param_Clip) != 0; |
| | | } |
| | | set |
| | | { |
| | | if (value) |
| | | { |
| | | buildParams |= param_Clip; |
| | | } |
| | | else |
| | | { |
| | | buildParams &= ~param_Clip; |
| | | } |
| | | } |
| | | } |
| | | |
| | | public static bool IsBuildAnimatorController |
| | | { |
| | | get |
| | | { |
| | | return (buildParams & param_AnimatorController) != 0; |
| | | } |
| | | set |
| | | { |
| | | if (value) |
| | | { |
| | | buildParams |= param_AnimatorController; |
| | | } |
| | | else |
| | | { |
| | | buildParams &= ~param_AnimatorController; |
| | | } |
| | | } |
| | | } |
| | | |
| | | protected static List<MountPointInfo> m_MountPointInfoList = new List<MountPointInfo>(); |
| | | |
| | | public void BuildPrefab(string path, string resName, string suffix) |
| | | { |
| | | string _absOriginalePath = string.Format("{0}/ART/Role/{1}/{2}.FBX", Application.dataPath, path, resName); |
| | | string _originalAssetPath = string.Format("Assets/ART/Role/{0}/{1}.FBX", path, resName); |
| | | |
| | | string _absAssetPath = string.Format("{0}Mob/{1}{2}.prefab", ResourcesPath.ResourcesOutPath, suffix, resName); |
| | | string _assetPath = string.Format("{0}Mob/{1}{2}.prefab", ResourcesPath.ResourcesOutAssetPath, suffix, resName); |
| | | |
| | | string _acAbsAssetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, path, AnimatorControllerLoader.controllerSuffix, path); |
| | | string _acAssetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, path, AnimatorControllerLoader.controllerSuffix, path); |
| | | |
| | | if (string.IsNullOrEmpty(_absOriginalePath)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | // 指定动画控制器 |
| | | if (!File.Exists(_acAbsAssetPath)) |
| | | { |
| | | Debug.LogWarningFormat("检测到此prefab资源: {0} 的AnimatorContorller(动画控制器)资源尚未生成, 这里需要注意啊此资源是否需要先生成AnimatorContorller(动画控制器), 再生成prefab资源.", path); |
| | | } |
| | | |
| | | ColliderInfo _colliderInfo = null; |
| | | |
| | | if (File.Exists(_absAssetPath)) |
| | | { |
| | | if (OnlyBuildNoExist) |
| | | { |
| | | //Debug.LogFormat("当前为只生成不存在的资源模式, 这里检测到 {0} 已经存在, 不进行生成."); |
| | | return; |
| | | } |
| | | |
| | | GameObject _originalAssetRes = null; |
| | | |
| | | _originalAssetRes = AssetDatabase.LoadAssetAtPath<GameObject>(_assetPath); |
| | | |
| | | if (_originalAssetRes) |
| | | { |
| | | Transform _mpNode; |
| | | |
| | | // 这里需要记录旧的对象身上的绑点信息, 然后给新的prefab设置绑点 |
| | | m_MountPointInfoList.Clear(); |
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Down"); |
| | | if (_mpNode) |
| | | { |
| | | CreateMountPointInfo(_mpNode); |
| | | } |
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Name"); |
| | | if (_mpNode) |
| | | { |
| | | CreateMountPointInfo(_mpNode); |
| | | } |
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Name2"); |
| | | if (_mpNode) |
| | | { |
| | | CreateMountPointInfo(_mpNode); |
| | | } |
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Hit"); |
| | | if (_mpNode) |
| | | { |
| | | CreateMountPointInfo(_mpNode); |
| | | } |
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Stun"); |
| | | if (_mpNode) |
| | | { |
| | | CreateMountPointInfo(_mpNode); |
| | | } |
| | | |
| | | CapsuleCollider _collider = _originalAssetRes.GetComponent<CapsuleCollider>(); |
| | | if (_collider) |
| | | { |
| | | _colliderInfo = new ColliderInfo(); |
| | | _colliderInfo.center = _collider.center; |
| | | _colliderInfo.height = _collider.height; |
| | | _colliderInfo.radius = _collider.radius; |
| | | } |
| | | } |
| | | } |
| | | |
| | | GameObject _fbxRes = AssetDatabase.LoadAssetAtPath<GameObject>(_originalAssetPath); |
| | | |
| | | if (_fbxRes == null) |
| | | { |
| | | _originalAssetPath = _originalAssetPath.Remove(_originalAssetPath.LastIndexOf(".")) + ".prefab"; |
| | | _fbxRes = AssetDatabase.LoadAssetAtPath<GameObject>(_originalAssetPath); |
| | | if (_fbxRes == null) |
| | | { |
| | | Debug.LogFormat("无法读取 {0}, 地址: {1}", resName, _originalAssetPath); |
| | | return; |
| | | } |
| | | } |
| | | |
| | | // 为了防止fbx本身就带有材质, 这里去掉fbx上的Import material属性 |
| | | ModelImporter _modelImport = AssetImporter.GetAtPath(_originalAssetPath) as ModelImporter; |
| | | if (_modelImport != null) |
| | | { |
| | | if (_modelImport.importMaterials) |
| | | { |
| | | _modelImport.importMaterials = false; |
| | | _modelImport.SaveAndReimport(); |
| | | } |
| | | } |
| | | |
| | | GameObject _prefab = Object.Instantiate(_fbxRes); |
| | | |
| | | // 设置绑点 |
| | | if (m_MountPointInfoList.Count > 0) |
| | | { |
| | | MountPointInfo _mpInfo = null; |
| | | |
| | | for (int i = 0; i < m_MountPointInfoList.Count; ++i) |
| | | { |
| | | _mpInfo = m_MountPointInfoList[i]; |
| | | GameObject _mp = new GameObject(_mpInfo.name); |
| | | Transform _parent = null; |
| | | if (string.IsNullOrEmpty(_mpInfo.path)) |
| | | { |
| | | _parent = _prefab.transform; |
| | | } |
| | | else |
| | | { |
| | | _parent = _prefab.transform.Find(_mpInfo.path); |
| | | } |
| | | |
| | | if (_parent != null) |
| | | { |
| | | _mp.transform.SetParent(_parent); |
| | | _mp.transform.localPosition = _mpInfo.localPosition; |
| | | _mp.transform.localRotation = _mpInfo.localRotation; |
| | | _mp.transform.localScale = _mpInfo.localScale; |
| | | } |
| | | } |
| | | } |
| | | |
| | | // 加载特效 |
| | | if (InstanceResourcesLoader.horseSuffix.Equals(suffix) |
| | | || resName.Contains("B_Cw")) |
| | | { |
| | | HandlerModelEffect("horseEffectConfig", null, resName, ref _prefab); |
| | | } |
| | | else if (InstanceResourcesLoader.raceSuffix.Equals(suffix)) |
| | | { |
| | | HandlerModelEffect("clothesEffectConfig", path, resName, ref _prefab); |
| | | } |
| | | |
| | | if (_colliderInfo != null) |
| | | { |
| | | CapsuleCollider _collider = _prefab.AddMissingComponent<CapsuleCollider>(); |
| | | _collider.center = _colliderInfo.center; |
| | | _collider.radius = _colliderInfo.radius; |
| | | _collider.height = _colliderInfo.height; |
| | | } |
| | | |
| | | Transform _rendererNode = _prefab.transform.Find(resName); |
| | | if (!_rendererNode) |
| | | { |
| | | _rendererNode = _prefab.transform; |
| | | } |
| | | |
| | | Renderer _renderer = _rendererNode.GetComponent<Renderer>(); |
| | | if (_renderer) |
| | | { |
| | | OnSetupRenderer(path, resName, ref _renderer); |
| | | } |
| | | |
| | | Animation _animation = _prefab.GetComponent<Animation>(); |
| | | if (_animation) |
| | | { |
| | | Object.DestroyImmediate(_animation); |
| | | } |
| | | |
| | | Animator _animator = _prefab.GetComponent<Animator>(); |
| | | |
| | | if (!_animator) |
| | | { |
| | | _animator = _prefab.AddComponent<Animator>(); |
| | | } |
| | | |
| | | // 绑定动画控制器 |
| | | RuntimeAnimatorController _runtimeAnimatorContorller = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(_acAssetPath); |
| | | if (_runtimeAnimatorContorller) |
| | | { |
| | | _animator.runtimeAnimatorController = _runtimeAnimatorContorller; |
| | | } |
| | | |
| | | PrefabUtility.CreatePrefab(_assetPath, _prefab, ReplacePrefabOptions.Default); |
| | | |
| | | // 设置打包路径 |
| | | AssetImporter _assetImport = AssetImporter.GetAtPath(_assetPath); |
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME |
| | | + (InstanceResourcesLoader.raceSuffix + resName).ToLower(); |
| | | EditorUtility.SetDirty(_prefab); |
| | | AssetDatabase.Refresh(); |
| | | Object.DestroyImmediate(_prefab); |
| | | AssetDatabase.SaveAssets(); |
| | | } |
| | | |
| | | private void HandlerModelEffect(string configName, string path, string modelName, ref GameObject _go) |
| | | { |
| | | if (_go == null) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | string _configPath = ResourcesPath.ResourcesOutAssetPath + "Mob/" + configName + ".asset"; |
| | | HorseEffectConfig _horseEffectConfig = AssetDatabase.LoadAssetAtPath<HorseEffectConfig>(_configPath); |
| | | if (_horseEffectConfig == null |
| | | || _horseEffectConfig.effectConfigList == null |
| | | || _horseEffectConfig.effectConfigList.Count == 0) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | HorseEffectConfig.EffectConfig _effectConfig; |
| | | int _index = -1; |
| | | |
| | | for (int i = 0; i < _horseEffectConfig.effectConfigList.Count; ++i) |
| | | { |
| | | _effectConfig = _horseEffectConfig.effectConfigList[i]; |
| | | if (_effectConfig.modelName.Equals(modelName)) |
| | | { |
| | | _index = i; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (_index == -1) |
| | | { |
| | | Debug.LogFormat("HandlerModelEffect() => 模型 {0} 没有配置任何特效", modelName); |
| | | return; |
| | | } |
| | | |
| | | _effectConfig = _horseEffectConfig.effectConfigList[_index]; |
| | | |
| | | Transform _parent; |
| | | GameObject _effect; |
| | | string _bonePath; |
| | | string _effectName; |
| | | |
| | | for (int i = 0; i < _effectConfig.boneNameList.Count; ++i) |
| | | { |
| | | _bonePath = _effectConfig.boneNameList[i]; |
| | | |
| | | _parent = _go.transform.GetChildTransformDeeply(_bonePath); |
| | | if (_parent == null) |
| | | { |
| | | Debug.LogWarningFormat("HandlerModelEffect() => 坐骑 {0} 配置的骨骼名称: {1} 找不到", modelName, _bonePath); |
| | | continue; |
| | | } |
| | | |
| | | _effectName = _effectConfig.effectNameList[i]; |
| | | if (string.IsNullOrEmpty(path)) |
| | | { |
| | | _configPath = string.Format("Assets/Art/Role/{0}/Effects/{1}.prefab", modelName, _effectName); |
| | | } |
| | | else |
| | | { |
| | | _configPath = string.Format("Assets/Art/Role/{0}/Effects/{1}.prefab", path, _effectName); |
| | | } |
| | | _effect = AssetDatabase.LoadAssetAtPath<GameObject>(_configPath); |
| | | if (_effect == null) |
| | | { |
| | | Debug.LogWarningFormat("HandlerModelEffect() => 坐骑 {0} 配置的特效资源: {1} 找不到", modelName, _configPath); |
| | | continue; |
| | | } |
| | | _effect = Object.Instantiate(_effect); |
| | | _effect.name = _effect.name.Replace("(Clone)", ""); |
| | | _effect.transform.SetParentEx(_parent, Vector3.zero, Quaternion.identity, Vector3.one); |
| | | _effect.SetLayer(LayerUtility.BattleEffect, true); |
| | | } |
| | | } |
| | | |
| | | protected static void CreateMountPointInfo(Transform t) |
| | | { |
| | | MountPointInfo _info = new MountPointInfo(); |
| | | _info.path = SampleEditorTool.PrintHierarchyPath(t); |
| | | if (!string.IsNullOrEmpty(_info.path)) |
| | | { |
| | | if (_info.path.Contains("/")) |
| | | { |
| | | _info.path = _info.path.Replace("/" + t.name, ""); |
| | | } |
| | | else |
| | | { |
| | | _info.path = _info.path.Replace(t.name, ""); |
| | | } |
| | | } |
| | | _info.name = t.name; |
| | | _info.localPosition = t.localPosition; |
| | | _info.localRotation = t.localRotation; |
| | | _info.localScale = t.localScale; |
| | | m_MountPointInfoList.Add(_info); |
| | | } |
| | | |
| | | public static void BuildAnimationClip(string path) |
| | | { |
| | | string _absOriginaleDirectory = string.Format("{0}/ART/Role/{1}", Application.dataPath, path); |
| | | string _assetOriginalDirectory = string.Format("Assets/ART/Role/{0}", path); |
| | | string _absAssetDirectory = string.Format("{0}/ResourcesOut/Mob/{1}/AnimationClips", Application.dataPath, path); |
| | | string _assetDirectory = string.Format("Assets/ResourcesOut/Mob/{0}/AnimationClips", path); |
| | | |
| | | if (!Directory.Exists(_absOriginaleDirectory)) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | // 生成目标文件夹是否存在, 不存在则创建 |
| | | if (!Directory.Exists(_absAssetDirectory)) |
| | | { |
| | | Directory.CreateDirectory(_absAssetDirectory); |
| | | } |
| | | |
| | | DirectoryInfo _dInfo = new DirectoryInfo(_absOriginaleDirectory); |
| | | FileInfo[] _fInfos = _dInfo.GetFiles("*.fbx"); |
| | | FileInfo _fInfo = null; |
| | | Object _animationClip = null; |
| | | AssetImporter _assetImport = null; |
| | | |
| | | int _count = _fInfos.Length; |
| | | string _newName = string.Empty; |
| | | string _assetDestPath = string.Empty; |
| | | string _originalPath = string.Empty; |
| | | |
| | | List<AnimationClip> clips = new List<AnimationClip>(); |
| | | for (int i = 0; i < _fInfos.Length; ++i) |
| | | { |
| | | _fInfo = _fInfos[i]; |
| | | if (!_fInfo.Name.Contains("@")) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | _newName = _fInfo.Name.Substring(_fInfo.Name.IndexOf("@") + 1); |
| | | _newName = _newName.Substring(0, _newName.Length - 4); |
| | | |
| | | _assetDestPath = string.Format("{0}/{1}.anim", _absAssetDirectory, _newName); |
| | | |
| | | EditorUtility.DisplayProgressBar(string.Format("正在生成 {0} 的动画中...", path), |
| | | string.Format("{0} => {1}.", _fInfo.Name, _assetDestPath), |
| | | i * 1f / _count); |
| | | |
| | | if (File.Exists(_assetDestPath)) |
| | | { |
| | | if (OnlyBuildNoExist) |
| | | { |
| | | continue; |
| | | } |
| | | } |
| | | |
| | | _assetDestPath = string.Format("{0}/{1}.anim", _assetDirectory, _newName); |
| | | _originalPath = _fInfo.FullName.Substring(Application.dataPath.Length + 1); |
| | | _originalPath = Path.Combine("Assets/", _originalPath); |
| | | _originalPath = _originalPath.Replace("\\", "/"); |
| | | |
| | | _animationClip = AssetDatabase.LoadAssetAtPath(_originalPath, typeof(AnimationClip)); |
| | | AnimationClip _newClip = new AnimationClip(); |
| | | EditorUtility.CopySerialized(_animationClip, _newClip); |
| | | |
| | | _newClip.legacy = false; |
| | | if (_newClip.name.Contains("Idle") || _newClip.name.Contains("Run") || _newClip.name.Contains("Stun")) |
| | | { |
| | | if (_newClip.isLooping == false) |
| | | { |
| | | AnimationClipSettings _clipSetting = AnimationUtility.GetAnimationClipSettings(_newClip); |
| | | _clipSetting.loopTime = true; |
| | | AnimationUtility.SetAnimationClipSettings(_newClip, _clipSetting); |
| | | } |
| | | } |
| | | |
| | | AssetDatabase.CreateAsset(_newClip, _assetDestPath); |
| | | _assetImport = AssetImporter.GetAtPath(_assetDestPath); |
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME + ResourcesPath.MOB_SUFFIX + path.ToLower(); |
| | | |
| | | clips.Add(_newClip); |
| | | EditorUtility.SetDirty(_newClip); |
| | | } |
| | | |
| | | EditorUtility.ClearProgressBar(); |
| | | |
| | | AssetDatabase.SaveAssets(); |
| | | AssetDatabase.Refresh(); |
| | | } |
| | | |
| | | public static void BuildAnimatorController(string resName, string templeName, string configName) |
| | | { |
| | | string _absAssetPath = string.Format("{0}Mob/{1}", ResourcesPath.ResourcesOutPath, resName); |
| | | |
| | | if (!Directory.Exists(_absAssetPath)) |
| | | { |
| | | Directory.CreateDirectory(_absAssetPath); |
| | | } |
| | | |
| | | _absAssetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, resName, AnimatorControllerLoader.controllerSuffix, resName); |
| | | |
| | | string _assetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, resName, AnimatorControllerLoader.controllerSuffix, resName); |
| | | if (templeName.Equals("Temple_AnimatorController_BossShow")) |
| | | { |
| | | _absAssetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, resName, AnimatorControllerLoader.controllerShowSuffix, resName); |
| | | _assetPath = string.Format("{0}Mob/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, resName, AnimatorControllerLoader.controllerShowSuffix, resName); |
| | | } |
| | | string _templePath = string.Format("{0}Mob/{1}.controller", ResourcesPath.ResourcesOutPath, templeName); |
| | | |
| | | if (File.Exists(_absAssetPath)) |
| | | { |
| | | if (OnlyBuildNoExist) |
| | | { |
| | | return; |
| | | } |
| | | else |
| | | { |
| | | File.Delete(_absAssetPath); |
| | | } |
| | | } |
| | | |
| | | File.Copy(_templePath, _absAssetPath); |
| | | AssetDatabase.Refresh(); |
| | | |
| | | AnimatorController _animatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(_assetPath); |
| | | |
| | | if (!_animatorController) |
| | | { |
| | | Debug.LogErrorFormat("找不到所需要的动画状态机, 地址为: {0}", _assetPath); |
| | | return; |
| | | } |
| | | |
| | | AnimatorControllerLayer _layer = _animatorController.layers[0]; |
| | | AnimatorStateMachine _stateMachine = _layer.stateMachine; |
| | | |
| | | |
| | | // 读取配置文件 |
| | | string _configPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, |
| | | "mob/", |
| | | configName, |
| | | ".asset"); |
| | | |
| | | AnimatorBuildConfig _buildConfig = AssetDatabase.LoadAssetAtPath<AnimatorBuildConfig>(_configPath); |
| | | |
| | | HandleStateMachine(resName, _stateMachine, _buildConfig); |
| | | |
| | | EditorUtility.SetDirty(_animatorController); |
| | | |
| | | AssetImporter _assetImport = AssetImporter.GetAtPath(_assetPath); |
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME + ResourcesPath.MOB_SUFFIX + resName; |
| | | |
| | | EditorUtility.ClearProgressBar(); |
| | | |
| | | AssetDatabase.SaveAssets(); |
| | | AssetDatabase.Refresh(); |
| | | } |
| | | |
| | | protected static void HandleStateMachine(string modelName, AnimatorStateMachine stateMachine, AnimatorBuildConfig _buildConfig) |
| | | { |
| | | if (stateMachine.states == null || stateMachine.states.Length == 0) |
| | | { |
| | | return; |
| | | } |
| | | |
| | | AnimatorState _animatorState = null; |
| | | Motion _motion = null; |
| | | |
| | | int _configStateIndex = -1; |
| | | |
| | | for (int i = 0; i < stateMachine.states.Length; ++i) |
| | | { |
| | | _animatorState = stateMachine.states[i].state; |
| | | _motion = _animatorState.motion; |
| | | |
| | | foreach (var _clipInfo in _buildConfig.clipConfigs) |
| | | { |
| | | if (_clipInfo.stateName.Equals(_animatorState.name)) |
| | | { |
| | | _configStateIndex = _buildConfig.clipConfigs.IndexOf(_clipInfo); |
| | | } |
| | | } |
| | | |
| | | if (_configStateIndex == -1) |
| | | { |
| | | Debug.LogWarningFormat("没有找到状态机上名称为: {0}在animatorBuildConfig里的对应配置. ", _animatorState.name); |
| | | continue; |
| | | } |
| | | |
| | | // 处理融合树类型 |
| | | if (_motion is BlendTree) |
| | | { } |
| | | else |
| | | {// 非融合树类型处理 |
| | | |
| | | if (_configStateIndex < 0 || _configStateIndex >= _buildConfig.clipConfigs.Count) |
| | | { |
| | | Debug.LogWarningFormat("state的名称{0}在配置表 animatorBuildConfig 找到索引{1} 找不到它对应的 clipConfigs 动画配置. ", |
| | | _animatorState.name, |
| | | _configStateIndex); |
| | | continue; |
| | | } |
| | | |
| | | // 读取配置上的动画片段 |
| | | List<string> _configClipNames = _buildConfig.clipConfigs[_configStateIndex].clipNames; |
| | | |
| | | if (_configClipNames == null || _configClipNames.Count == 0) |
| | | { |
| | | continue; |
| | | } |
| | | |
| | | AnimationClip _configClip; |
| | | for (int j = 0; j < _configClipNames.Count; ++j) |
| | | { |
| | | _configClip = LoadModelAnimationClip(modelName, _configClipNames[j]); |
| | | if (_configClip != null) |
| | | { |
| | | _animatorState.motion = _configClip; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (_animatorState.motion == null) |
| | | { |
| | | Debug.LogWarningFormat("为{0}状态设置动画失败!!!", _animatorState.name); |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | for (int i = 0; i < stateMachine.stateMachines.Length; ++i) |
| | | { |
| | | HandleStateMachine(modelName, stateMachine.stateMachines[i].stateMachine, _buildConfig); |
| | | } |
| | | } |
| | | |
| | | protected static AnimationClip LoadModelAnimationClip(string modelName, string clipName) |
| | | { |
| | | |
| | | string _assetPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath, |
| | | "mob/", |
| | | modelName, |
| | | "/AnimationClips/", |
| | | clipName, |
| | | ".anim"); |
| | | |
| | | AnimationClip _animationClip = AssetDatabase.LoadAssetAtPath<AnimationClip>(_assetPath); |
| | | return _animationClip; |
| | | } |
| | | |
| | | protected virtual void OnSetupRenderer(string path, string resName, ref Renderer renderer) |
| | | { |
| | | |
| | | } |
| | | using UnityEngine;
|
| | | using System.Collections.Generic;
|
| | | using UnityEditor;
|
| | | using UnityEditor.Animations;
|
| | | using System.IO;
|
| | |
|
| | | public class ResourcesBuilder
|
| | | {
|
| | | protected const byte param_NoExist = 1;
|
| | | protected const byte param_Prefab = 2;
|
| | | protected const byte param_Clip = 4;
|
| | | protected const byte param_AnimatorController = 8;
|
| | | protected const byte param_AnimatorUIController = 16;
|
| | |
|
| | | protected class MountPointInfo
|
| | | {
|
| | | public string path;
|
| | | public string name;
|
| | | public Vector3 localPosition;
|
| | | public Quaternion localRotation;
|
| | | public Vector3 localScale;
|
| | | }
|
| | |
|
| | | protected class ColliderInfo
|
| | | {
|
| | | public Vector3 center;
|
| | | public float radius;
|
| | | public float height;
|
| | | }
|
| | |
|
| | | public static int buildParams = 0;
|
| | |
|
| | | public static bool OnlyBuildNoExist
|
| | | {
|
| | | get
|
| | | {
|
| | | return (buildParams & param_NoExist) != 0;
|
| | | }
|
| | |
|
| | | set
|
| | | {
|
| | | if (value)
|
| | | {
|
| | | buildParams |= param_NoExist;
|
| | | }
|
| | | else
|
| | | {
|
| | | buildParams &= ~param_NoExist;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public static bool IsBuildPrefab
|
| | | {
|
| | | get
|
| | | {
|
| | | return (buildParams & param_Prefab) != 0;
|
| | | }
|
| | | set
|
| | | {
|
| | | if (value)
|
| | | {
|
| | | buildParams |= param_Prefab;
|
| | | }
|
| | | else
|
| | | {
|
| | | buildParams &= ~param_Prefab;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public static bool IsBuildAnimationClip
|
| | | {
|
| | | get
|
| | | {
|
| | | return (buildParams & param_Clip) != 0;
|
| | | }
|
| | | set
|
| | | {
|
| | | if (value)
|
| | | {
|
| | | buildParams |= param_Clip;
|
| | | }
|
| | | else
|
| | | {
|
| | | buildParams &= ~param_Clip;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public static bool IsBuildAnimatorController
|
| | | {
|
| | | get
|
| | | {
|
| | | return (buildParams & param_AnimatorController) != 0;
|
| | | }
|
| | | set
|
| | | {
|
| | | if (value)
|
| | | {
|
| | | buildParams |= param_AnimatorController;
|
| | | }
|
| | | else
|
| | | {
|
| | | buildParams &= ~param_AnimatorController;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public static bool IsBuildAnimatorUIController
|
| | | {
|
| | | get
|
| | | {
|
| | | return (buildParams & param_AnimatorUIController) != 0;
|
| | | }
|
| | | set
|
| | | {
|
| | | if (value)
|
| | | {
|
| | | buildParams |= param_AnimatorUIController;
|
| | | }
|
| | | else
|
| | | {
|
| | | buildParams &= ~param_AnimatorUIController;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | protected static List<MountPointInfo> m_MountPointInfoList = new List<MountPointInfo>();
|
| | |
|
| | | public void BuildPrefab(string path, string resName, string suffix, string outName = null, bool isHighMesh = false)
|
| | | {
|
| | | if (string.IsNullOrEmpty(outName))
|
| | | {
|
| | | outName = resName;
|
| | | }
|
| | |
|
| | | string _absOriginalePath = string.Format("{0}/ART/Role/{1}/{2}.FBX", Application.dataPath, path, resName);
|
| | | string _originalAssetPath = string.Format("Assets/ART/Role/{0}/{1}.FBX", path, resName);
|
| | |
|
| | | if ((resName.StartsWith("A_Zs") || resName.StartsWith("A_Fs"))
|
| | | && !isHighMesh
|
| | | && (suffix.Equals(InstanceResourcesLoader.raceSuffix) || suffix.Equals(InstanceResourcesLoader.handSuffix)))
|
| | | {
|
| | | _absOriginalePath = string.Format("{0}/ART/Role/{1}/{2}_Dm.FBX", Application.dataPath, path, resName);
|
| | | _originalAssetPath = string.Format("Assets/ART/Role/{0}/{1}_Dm.FBX", path, resName);
|
| | | }
|
| | |
|
| | | string _tempPrefabName = outName;
|
| | |
|
| | | if (isHighMesh
|
| | | && ((resName.StartsWith("A_Zs") || resName.StartsWith("A_Fs"))
|
| | | && (suffix.Equals(InstanceResourcesLoader.raceSuffix) || suffix.Equals(InstanceResourcesLoader.handSuffix))))
|
| | | {
|
| | | _tempPrefabName += "_UI";
|
| | |
|
| | | _absOriginalePath = string.Format("{0}/ART/Role/{1}/{2}.FBX", Application.dataPath, path, resName);
|
| | | _originalAssetPath = string.Format("Assets/ART/Role/{0}/{1}.FBX", path, resName);
|
| | | }
|
| | |
|
| | | string _absAssetPath = string.Format("{0}Gmodels/{1}{2}.prefab", ResourcesPath.ResourcesOutPath, suffix, _tempPrefabName);
|
| | | string _assetPath = string.Format("{0}Gmodels/{1}{2}.prefab", ResourcesPath.ResourcesOutAssetPath, suffix, _tempPrefabName);
|
| | |
|
| | | string _acAbsAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, path, AnimatorControllerLoader.controllerSuffix, path);
|
| | | string _acAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, path, AnimatorControllerLoader.controllerSuffix, path);
|
| | |
|
| | | if (!outName.Equals(resName))
|
| | | {
|
| | | _acAbsAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, path, AnimatorControllerLoader.controllerSuffix, outName);
|
| | | _acAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, path, AnimatorControllerLoader.controllerSuffix, outName);
|
| | | }
|
| | |
|
| | | if (string.IsNullOrEmpty(_absOriginalePath))
|
| | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | // 指定动画控制器
|
| | | if (!File.Exists(_acAbsAssetPath))
|
| | | {
|
| | | Debug.LogWarningFormat("检测到此prefab资源: {0} 的AnimatorContorller(动画控制器)资源尚未生成, 这里需要注意啊此资源是否需要先生成AnimatorContorller(动画控制器), 再生成prefab资源.", _acAssetPath);
|
| | | }
|
| | |
|
| | | ColliderInfo _colliderInfo = null;
|
| | |
|
| | | if (File.Exists(_absAssetPath))
|
| | | {
|
| | | if (OnlyBuildNoExist)
|
| | | {
|
| | | //Debug.LogFormat("当前为只生成不存在的资源模式, 这里检测到 {0} 已经存在, 不进行生成.");
|
| | | return;
|
| | | }
|
| | |
|
| | | GameObject _originalAssetRes = null;
|
| | |
|
| | | _originalAssetRes = AssetDatabase.LoadAssetAtPath<GameObject>(_assetPath);
|
| | |
|
| | | if (_originalAssetRes)
|
| | | {
|
| | | Transform _mpNode;
|
| | |
|
| | | // 这里需要记录旧的对象身上的绑点信息, 然后给新的prefab设置绑点
|
| | | m_MountPointInfoList.Clear();
|
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Down");
|
| | | if (_mpNode)
|
| | | {
|
| | | CreateMountPointInfo(_mpNode);
|
| | | }
|
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Name");
|
| | | if (_mpNode)
|
| | | {
|
| | | CreateMountPointInfo(_mpNode);
|
| | | }
|
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Name2");
|
| | | if (_mpNode)
|
| | | {
|
| | | CreateMountPointInfo(_mpNode);
|
| | | }
|
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Hit");
|
| | | if (_mpNode)
|
| | | {
|
| | | CreateMountPointInfo(_mpNode);
|
| | | }
|
| | | _mpNode = _originalAssetRes.transform.GetChildTransformDeeply("A_Stun");
|
| | | if (_mpNode)
|
| | | {
|
| | | CreateMountPointInfo(_mpNode);
|
| | | }
|
| | |
|
| | | CapsuleCollider _collider = _originalAssetRes.GetComponent<CapsuleCollider>();
|
| | | if (_collider)
|
| | | {
|
| | | _colliderInfo = new ColliderInfo();
|
| | | _colliderInfo.center = _collider.center;
|
| | | _colliderInfo.height = _collider.height;
|
| | | _colliderInfo.radius = _collider.radius;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | GameObject _fbxRes = AssetDatabase.LoadAssetAtPath<GameObject>(_originalAssetPath);
|
| | |
|
| | | if (_fbxRes == null)
|
| | | {
|
| | | _originalAssetPath = _originalAssetPath.Remove(_originalAssetPath.LastIndexOf(".")) + ".prefab";
|
| | | _fbxRes = AssetDatabase.LoadAssetAtPath<GameObject>(_originalAssetPath);
|
| | | if (_fbxRes == null)
|
| | | {
|
| | | Debug.LogFormat("无法读取 {0}, 地址: {1}", resName, _originalAssetPath);
|
| | | return;
|
| | | }
|
| | | }
|
| | |
|
| | | // 为了防止fbx本身就带有材质, 这里去掉fbx上的Import material属性
|
| | | //ModelImporter _modelImport = AssetImporter.GetAtPath(_originalAssetPath) as ModelImporter;
|
| | | //if (_modelImport != null)
|
| | | //{
|
| | | // if (_modelImport.importMaterials)
|
| | | // {
|
| | | // _modelImport.importMaterials = false;
|
| | | // _modelImport.SaveAndReimport();
|
| | | // }
|
| | | //}
|
| | |
|
| | | GameObject _prefab = Object.Instantiate(_fbxRes);
|
| | |
|
| | | // 设置绑点
|
| | | if (m_MountPointInfoList.Count > 0)
|
| | | {
|
| | | MountPointInfo _mpInfo = null;
|
| | |
|
| | | for (int i = 0; i < m_MountPointInfoList.Count; ++i)
|
| | | {
|
| | | _mpInfo = m_MountPointInfoList[i];
|
| | | GameObject _mp = new GameObject(_mpInfo.name);
|
| | | Transform _parent = null;
|
| | | if (string.IsNullOrEmpty(_mpInfo.path))
|
| | | {
|
| | | _parent = _prefab.transform;
|
| | | }
|
| | | else
|
| | | {
|
| | | _parent = _prefab.transform.Find(_mpInfo.path);
|
| | | }
|
| | |
|
| | | if (_parent != null)
|
| | | {
|
| | | _mp.transform.SetParent(_parent);
|
| | | _mp.transform.localPosition = _mpInfo.localPosition;
|
| | | _mp.transform.localRotation = _mpInfo.localRotation;
|
| | | _mp.transform.localScale = _mpInfo.localScale;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | // 加载特效
|
| | | //if (outName.StartsWith("M")
|
| | | // || outName.StartsWith("N")
|
| | | // || outName.StartsWith("B_")
|
| | | // || outName.StartsWith("Zq"))
|
| | | //{
|
| | | // HandlerModelEffect("horseEffectConfig", null, outName, ref _prefab);
|
| | | //}
|
| | | //else if (InstanceResourcesLoader.raceSuffix.Equals(suffix))
|
| | | //{
|
| | | // HandlerModelEffect("clothesEffectConfig", path, resName, ref _prefab);
|
| | | //}
|
| | |
|
| | | if (_colliderInfo != null)
|
| | | {
|
| | | CapsuleCollider _collider = _prefab.AddMissingComponent<CapsuleCollider>();
|
| | | _collider.center = _colliderInfo.center;
|
| | | _collider.radius = _colliderInfo.radius;
|
| | | _collider.height = _colliderInfo.height;
|
| | | }
|
| | |
|
| | | string _tempName = resName;
|
| | |
|
| | | if ((resName.StartsWith("A_Zs") || resName.StartsWith("A_Fs"))
|
| | | && (suffix.Equals(InstanceResourcesLoader.raceSuffix)
|
| | | || suffix.Equals(InstanceResourcesLoader.handSuffix))
|
| | | && !isHighMesh)
|
| | | {
|
| | | _tempName += "_Dm";
|
| | | }
|
| | |
|
| | | Transform _rendererNode = _prefab.transform.Find(_tempName);
|
| | | if (!_rendererNode)
|
| | | {
|
| | | _rendererNode = _prefab.transform;
|
| | | }
|
| | |
|
| | | Renderer _renderer = _rendererNode.GetComponent<Renderer>();
|
| | | if (_renderer)
|
| | | {
|
| | | OnSetupRenderer(path, _tempName, ref _renderer);
|
| | | }
|
| | |
|
| | | Animation _animation = _prefab.GetComponent<Animation>();
|
| | | if (_animation)
|
| | | {
|
| | | Object.DestroyImmediate(_animation);
|
| | | }
|
| | |
|
| | | if (suffix.Equals(InstanceResourcesLoader.raceSuffix)
|
| | | || suffix.Equals(InstanceResourcesLoader.horseSuffix)
|
| | | || suffix.Equals(InstanceResourcesLoader.wingSuffix))
|
| | | {
|
| | | Animator _animator = _prefab.GetComponent<Animator>();
|
| | |
|
| | | if (!_animator)
|
| | | {
|
| | | _animator = _prefab.AddComponent<Animator>();
|
| | | }
|
| | |
|
| | | if (suffix.Equals(InstanceResourcesLoader.wingSuffix))
|
| | | {
|
| | | // 绑定动画控制器
|
| | | RuntimeAnimatorController _runtimeAnimatorContorller = AssetDatabase.LoadAssetAtPath<RuntimeAnimatorController>(_acAssetPath);
|
| | | if (_runtimeAnimatorContorller)
|
| | | {
|
| | | _animator.runtimeAnimatorController = _runtimeAnimatorContorller;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | PrefabUtility.CreatePrefab(_assetPath, _prefab, ReplacePrefabOptions.Default);
|
| | |
|
| | | // 设置打包路径
|
| | | AssetImporter _assetImport = AssetImporter.GetAtPath(_assetPath);
|
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME
|
| | | + (InstanceResourcesLoader.raceSuffix + resName).ToLower();
|
| | | EditorUtility.SetDirty(_prefab);
|
| | | AssetDatabase.Refresh();
|
| | | Object.DestroyImmediate(_prefab);
|
| | | AssetDatabase.SaveAssets();
|
| | | }
|
| | |
|
| | | private void HandlerModelEffect(string configName, string path, string modelName, ref GameObject _go)
|
| | | {
|
| | | if (_go == null)
|
| | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | string _configPath = ResourcesPath.ResourcesOutAssetPath + "Gmodels/" + configName + ".asset";
|
| | | HorseEffectConfig _horseEffectConfig = AssetDatabase.LoadAssetAtPath<HorseEffectConfig>(_configPath);
|
| | | if (_horseEffectConfig == null
|
| | | || _horseEffectConfig.effectConfigList == null
|
| | | || _horseEffectConfig.effectConfigList.Count == 0)
|
| | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | HorseEffectConfig.EffectConfig _effectConfig;
|
| | | int _index = -1;
|
| | |
|
| | | for (int i = 0; i < _horseEffectConfig.effectConfigList.Count; ++i)
|
| | | {
|
| | | _effectConfig = _horseEffectConfig.effectConfigList[i];
|
| | | if (_effectConfig.modelName.Equals(modelName))
|
| | | {
|
| | | _index = i;
|
| | | break;
|
| | | }
|
| | | }
|
| | |
|
| | | if (_index == -1)
|
| | | {
|
| | | Debug.LogFormat("HandlerModelEffect() => 模型 {0} 没有配置任何特效", modelName);
|
| | | return;
|
| | | }
|
| | |
|
| | | _effectConfig = _horseEffectConfig.effectConfigList[_index];
|
| | |
|
| | | Transform _parent;
|
| | | GameObject _effect;
|
| | | string _bonePath;
|
| | | string _effectName;
|
| | |
|
| | | for (int i = 0; i < _effectConfig.boneNameList.Count; ++i)
|
| | | {
|
| | | _bonePath = _effectConfig.boneNameList[i];
|
| | |
|
| | | _parent = _go.transform.GetChildTransformDeeply(_bonePath);
|
| | | if (_parent == null)
|
| | | {
|
| | | Debug.LogWarningFormat("HandlerModelEffect() => 坐骑 {0} 配置的骨骼名称: {1} 找不到", modelName, _bonePath);
|
| | | continue;
|
| | | }
|
| | |
|
| | | _effectName = _effectConfig.effectNameList[i];
|
| | | if (string.IsNullOrEmpty(path))
|
| | | {
|
| | | _configPath = string.Format("Assets/Art/Role/{0}/Effects/{1}.prefab", modelName, _effectName);
|
| | | }
|
| | | else
|
| | | {
|
| | | _configPath = string.Format("Assets/Art/Role/{0}/Effects/{1}.prefab", path, _effectName);
|
| | | }
|
| | | _effect = AssetDatabase.LoadAssetAtPath<GameObject>(_configPath);
|
| | | if (_effect == null)
|
| | | {
|
| | | Debug.LogWarningFormat("HandlerModelEffect() => 坐骑 {0} 配置的特效资源: {1} 找不到", modelName, _configPath);
|
| | | continue;
|
| | | }
|
| | | _effect = Object.Instantiate(_effect);
|
| | | _effect.name = _effect.name.Replace("(Clone)", "");
|
| | | _effect.transform.SetParentEx(_parent, Vector3.zero, Quaternion.identity, Vector3.one);
|
| | | _effect.SetLayer(LayerUtility.BattleEffectLow, true);
|
| | | }
|
| | | }
|
| | |
|
| | | protected static void CreateMountPointInfo(Transform t)
|
| | | {
|
| | | MountPointInfo _info = new MountPointInfo();
|
| | | _info.path = SampleEditorTool.PrintHierarchyPath(t);
|
| | | if (!string.IsNullOrEmpty(_info.path))
|
| | | {
|
| | | if (_info.path.Contains("/"))
|
| | | {
|
| | | _info.path = _info.path.Replace("/" + t.name, "");
|
| | | }
|
| | | else
|
| | | {
|
| | | _info.path = _info.path.Replace(t.name, "");
|
| | | }
|
| | | }
|
| | | _info.name = t.name;
|
| | | _info.localPosition = t.localPosition;
|
| | | _info.localRotation = t.localRotation;
|
| | | _info.localScale = t.localScale;
|
| | | m_MountPointInfoList.Add(_info);
|
| | | }
|
| | |
|
| | | public static void BuildAnimationClip(string path)
|
| | | {
|
| | | string _absOriginaleDirectory = string.Format("{0}/ART/Role/{1}", Application.dataPath, path);
|
| | | string _assetOriginalDirectory = string.Format("Assets/ART/Role/{0}", path);
|
| | | string _absAssetDirectory = string.Format("{0}/ResourcesOut/Gmodels/{1}/AnimationClips", Application.dataPath, path);
|
| | | string _assetDirectory = string.Format("Assets/ResourcesOut/Gmodels/{0}/AnimationClips", path);
|
| | |
|
| | | if (!Directory.Exists(_absOriginaleDirectory))
|
| | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | // 生成目标文件夹是否存在, 不存在则创建
|
| | | if (!Directory.Exists(_absAssetDirectory))
|
| | | {
|
| | | Directory.CreateDirectory(_absAssetDirectory);
|
| | | }
|
| | |
|
| | | DirectoryInfo _dInfo = new DirectoryInfo(_absOriginaleDirectory);
|
| | | FileInfo[] _fInfos = _dInfo.GetFiles("*.fbx");
|
| | | FileInfo _fInfo = null;
|
| | | Object _animationClip = null;
|
| | | AssetImporter _assetImport = null;
|
| | |
|
| | | int _count = _fInfos.Length;
|
| | | string _newName = string.Empty;
|
| | | string _assetDestPath = string.Empty;
|
| | | string _originalPath = string.Empty;
|
| | |
|
| | | List<AnimationClip> clips = new List<AnimationClip>();
|
| | | for (int i = 0; i < _fInfos.Length; ++i)
|
| | | {
|
| | | _fInfo = _fInfos[i];
|
| | | if (!_fInfo.Name.Contains("@"))
|
| | | {
|
| | | continue;
|
| | | }
|
| | |
|
| | | _newName = _fInfo.Name.Substring(_fInfo.Name.IndexOf("@") + 1);
|
| | | _newName = _newName.Substring(0, _newName.Length - 4);
|
| | |
|
| | | _assetDestPath = string.Format("{0}/{1}.anim", _absAssetDirectory, _newName);
|
| | |
|
| | | EditorUtility.DisplayProgressBar(string.Format("正在生成 {0} 的动画中...", path),
|
| | | string.Format("{0} => {1}.", _fInfo.Name, _assetDestPath),
|
| | | i * 1f / _count);
|
| | |
|
| | | if (File.Exists(_assetDestPath))
|
| | | {
|
| | | if (OnlyBuildNoExist)
|
| | | {
|
| | | continue;
|
| | | }
|
| | | }
|
| | |
|
| | | _assetDestPath = string.Format("{0}/{1}.anim", _assetDirectory, _newName);
|
| | | _originalPath = _fInfo.FullName.Substring(Application.dataPath.Length + 1);
|
| | | _originalPath = Path.Combine("Assets/", _originalPath);
|
| | | _originalPath = _originalPath.Replace("\\", "/");
|
| | |
|
| | | _animationClip = AssetDatabase.LoadAssetAtPath(_originalPath, typeof(AnimationClip));
|
| | | AnimationClip _newClip = new AnimationClip();
|
| | | EditorUtility.CopySerialized(_animationClip, _newClip);
|
| | |
|
| | | _newClip.legacy = false;
|
| | | if (_newClip.name.Contains("Idle") || _newClip.name.Contains("Run") || _newClip.name.Contains("Stun"))
|
| | | {
|
| | | if (_newClip.isLooping == false)
|
| | | {
|
| | | AnimationClipSettings _clipSetting = AnimationUtility.GetAnimationClipSettings(_newClip);
|
| | | _clipSetting.loopTime = true;
|
| | | AnimationUtility.SetAnimationClipSettings(_newClip, _clipSetting);
|
| | | }
|
| | | }
|
| | |
|
| | | AssetDatabase.CreateAsset(_newClip, _assetDestPath);
|
| | | _assetImport = AssetImporter.GetAtPath(_assetDestPath);
|
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME + ResourcesPath.MOB_SUFFIX + path.ToLower();
|
| | |
|
| | | clips.Add(_newClip);
|
| | | EditorUtility.SetDirty(_newClip);
|
| | | }
|
| | |
|
| | | EditorUtility.ClearProgressBar();
|
| | |
|
| | | AssetDatabase.SaveAssets();
|
| | | AssetDatabase.Refresh();
|
| | | }
|
| | |
|
| | | public static void BuildAnimatorController(string resName, string templeName, string configName, string outName = null)
|
| | | {
|
| | | if (string.IsNullOrEmpty(outName))
|
| | | {
|
| | | outName = resName;
|
| | | }
|
| | |
|
| | | string _absAssetPath = string.Format("{0}Gmodels/{1}", ResourcesPath.ResourcesOutPath, outName);
|
| | |
|
| | | if (!Directory.Exists(_absAssetPath))
|
| | | {
|
| | | Directory.CreateDirectory(_absAssetPath);
|
| | | }
|
| | |
|
| | | _absAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, outName, AnimatorControllerLoader.controllerSuffix, outName);
|
| | | string _assetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, outName, AnimatorControllerLoader.controllerSuffix, outName);
|
| | |
|
| | | if (templeName.Equals("Temple_AnimatorController_BossShow"))
|
| | | {
|
| | | _absAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, resName, AnimatorControllerLoader.controllerShowSuffix, resName);
|
| | | _assetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, resName, AnimatorControllerLoader.controllerShowSuffix, resName);
|
| | | }
|
| | |
|
| | | if (templeName.Equals("Temple_AnimatorController_Realm"))
|
| | | {
|
| | | _absAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, resName, AnimatorControllerLoader.controllerRealmSuffix, resName);
|
| | | _assetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, resName, AnimatorControllerLoader.controllerRealmSuffix, resName);
|
| | | }
|
| | |
|
| | | if (templeName.Equals("Temple_AnimatorController_UI"))
|
| | | {
|
| | | _absAssetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutPath, outName, AnimatorControllerLoader.controllerUISuffix, outName);
|
| | | _assetPath = string.Format("{0}Gmodels/{1}/{2}{3}.controller", ResourcesPath.ResourcesOutAssetPath, outName, AnimatorControllerLoader.controllerUISuffix, outName);
|
| | | }
|
| | |
|
| | | string _templePath = string.Format("{0}Gmodels/{1}.controller", ResourcesPath.ResourcesOutPath, templeName);
|
| | |
|
| | | if (File.Exists(_absAssetPath))
|
| | | {
|
| | | if (OnlyBuildNoExist)
|
| | | {
|
| | | return;
|
| | | }
|
| | | else
|
| | | {
|
| | | File.Delete(_absAssetPath);
|
| | | }
|
| | | }
|
| | |
|
| | | File.Copy(_templePath, _absAssetPath);
|
| | | AssetDatabase.Refresh();
|
| | |
|
| | | AnimatorController _animatorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(_assetPath);
|
| | |
|
| | | if (!_animatorController)
|
| | | {
|
| | | Debug.LogErrorFormat("找不到所需要的动画状态机, 地址为: {0}", _assetPath);
|
| | | return;
|
| | | }
|
| | |
|
| | | AnimatorControllerLayer _layer = _animatorController.layers[0];
|
| | | AnimatorStateMachine _stateMachine = _layer.stateMachine;
|
| | |
|
| | |
|
| | | // 读取配置文件
|
| | | string _configPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
|
| | | "gmodels/",
|
| | | configName,
|
| | | ".asset");
|
| | |
|
| | | AnimatorBuildConfig _buildConfig = AssetDatabase.LoadAssetAtPath<AnimatorBuildConfig>(_configPath);
|
| | |
|
| | | HandleStateMachine(resName, _stateMachine, _buildConfig);
|
| | |
|
| | | EditorUtility.SetDirty(_animatorController);
|
| | |
|
| | | AssetImporter _assetImport = AssetImporter.GetAtPath(_assetPath);
|
| | | _assetImport.assetBundleName = ResourcesPath.MOB_FOLDER_NAME + ResourcesPath.MOB_SUFFIX + outName;
|
| | |
|
| | | EditorUtility.ClearProgressBar();
|
| | |
|
| | | AssetDatabase.SaveAssets();
|
| | | AssetDatabase.Refresh();
|
| | | }
|
| | |
|
| | | protected static void HandleStateMachine(string modelName, AnimatorStateMachine stateMachine, AnimatorBuildConfig _buildConfig)
|
| | | {
|
| | | if (stateMachine.states == null || stateMachine.states.Length == 0)
|
| | | {
|
| | | return;
|
| | | }
|
| | |
|
| | | AnimatorState _animatorState = null;
|
| | | Motion _motion = null;
|
| | |
|
| | | int _configStateIndex = -1;
|
| | |
|
| | | for (int i = 0; i < stateMachine.states.Length; ++i)
|
| | | {
|
| | | _animatorState = stateMachine.states[i].state;
|
| | | _motion = _animatorState.motion;
|
| | |
|
| | | foreach (var _clipInfo in _buildConfig.clipConfigs)
|
| | | {
|
| | | if (_clipInfo.stateName.Equals(_animatorState.name))
|
| | | {
|
| | | _configStateIndex = _buildConfig.clipConfigs.IndexOf(_clipInfo);
|
| | | }
|
| | | }
|
| | |
|
| | | if (_configStateIndex == -1)
|
| | | {
|
| | | Debug.LogWarningFormat("没有找到状态机上名称为: {0}在animatorBuildConfig里的对应配置. ", _animatorState.name);
|
| | | continue;
|
| | | }
|
| | |
|
| | | // 处理融合树类型
|
| | | if (_motion is BlendTree)
|
| | | { }
|
| | | else
|
| | | {// 非融合树类型处理
|
| | |
|
| | | if (_configStateIndex < 0 || _configStateIndex >= _buildConfig.clipConfigs.Count)
|
| | | {
|
| | | Debug.LogWarningFormat("state的名称{0}在配置表 animatorBuildConfig 找到索引{1} 找不到它对应的 clipConfigs 动画配置. ",
|
| | | _animatorState.name,
|
| | | _configStateIndex);
|
| | | continue;
|
| | | }
|
| | |
|
| | | // 读取配置上的动画片段
|
| | | List<string> _configClipNames = _buildConfig.clipConfigs[_configStateIndex].clipNames;
|
| | |
|
| | | if (_configClipNames == null || _configClipNames.Count == 0)
|
| | | {
|
| | | continue;
|
| | | }
|
| | |
|
| | | AnimationClip _configClip;
|
| | | for (int j = 0; j < _configClipNames.Count; ++j)
|
| | | {
|
| | | _configClip = LoadModelAnimationClip(modelName, _configClipNames[j]);
|
| | | if (_configClip != null)
|
| | | {
|
| | | _animatorState.motion = _configClip;
|
| | | break;
|
| | | }
|
| | | }
|
| | |
|
| | | if (_animatorState.motion == null)
|
| | | {
|
| | | Debug.LogWarningFormat("为{0}状态设置动画失败!!!", _animatorState.name);
|
| | | }
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | for (int i = 0; i < stateMachine.stateMachines.Length; ++i)
|
| | | {
|
| | | HandleStateMachine(modelName, stateMachine.stateMachines[i].stateMachine, _buildConfig);
|
| | | }
|
| | | }
|
| | |
|
| | | protected static AnimationClip LoadModelAnimationClip(string modelName, string clipName)
|
| | | {
|
| | |
|
| | | string _assetPath = StringUtility.Contact(ResourcesPath.ResourcesOutAssetPath,
|
| | | "gmodels/",
|
| | | modelName,
|
| | | "/AnimationClips/",
|
| | | clipName,
|
| | | ".anim");
|
| | |
|
| | | AnimationClip _animationClip = AssetDatabase.LoadAssetAtPath<AnimationClip>(_assetPath);
|
| | | return _animationClip;
|
| | | }
|
| | |
|
| | | protected virtual void OnSetupRenderer(string path, string resName, ref Renderer renderer)
|
| | | {
|
| | |
|
| | | }
|
| | | } |