using UnityEngine; using System.Collections.Generic; #if UNITY_EDITOR using UnityEditor; #endif public class SoSkill : ScriptableObject { /// /// 攻击类型 /// 配置的组合类型应该为 0x0000 0000 0000 0000 /// 前8位表示攻击类型,后8位表示数据id索引 /// public enum E_AttackType { Sweep, FlyObject, } /// /// 动画状态名哈希值 /// //public int action; /// /// 动画时间 /// //public float time; /// /// 动画帧率 /// //public float frameRate; /// /// 可衔接的下一个技能id /// //public int nextSkillId; /// /// 前置技能id /// //public int prevSkillId = -1; public int effectOnTargetHead; public int ghostEffectID; public int rushArriveEffectID; public bool acceptInput; public bool hideWeapon = false; public E_HitTestType hitTestType = E_HitTestType.Sector;// 碰撞检测类型 public E_CastBaseType bastType = E_CastBaseType.Self;// 碰撞检测基于类型 public int chkRange;// 矩形检测的宽度,扇形检测时候的角度 public float chkDistance;// 矩形检测的时候的距离, 扇形检测的时候的半径 public bool interrupt = true; public bool forceMove = false; #region 动画帧事件相关定义 public List animationEventList = new List(); [System.Serializable] public class exAnimationClipEvent { public int index; public E_FrameEventType frameEventType; public int intParam; } #endregion public static E_AttackType GetAttactType(int value) { return (E_AttackType)(value >> 16); } public static int GetFrameEventId(int value) { return (value & 0x00FFFF); } } #if UNITY_EDITOR [CustomEditor(typeof(SoSkill))] public class SoSkillEditor : Editor { //private AnimatorController m_AnimatorController; //private AnimationClip m_AnimationClip; //private float _animationClipLength; private bool m_NewingData = false; private int m_NewDataIndex = 0; private E_FrameEventType m_NewFrameEventType; private SoSkill.E_AttackType m_NewAttackType; private int m_NewFrameEventId; private int m_EditIndex = -1; private E_FrameEventType m_EditFrameEventType; private int m_EditFrameIdex; private SoSkill.E_AttackType m_EditAttackType; private int m_EditFrameEventId; private void OnEnable() { m_NewDataIndex = 0; m_EditIndex = -1; } public override void OnInspectorGUI() { serializedObject.Update(); SoSkill _target = target as SoSkill; _target.acceptInput = EditorGUILayout.Toggle("接受输入", _target.acceptInput); _target.hideWeapon = EditorGUILayout.Toggle("隐藏武器", _target.hideWeapon); _target.interrupt = EditorGUILayout.Toggle("是否能被打断", _target.interrupt); _target.forceMove = EditorGUILayout.Toggle("移动至", _target.forceMove); _target.effectOnTargetHead = EditorGUILayout.IntField("目标头顶特效", _target.effectOnTargetHead); _target.rushArriveEffectID = EditorGUILayout.IntField("冲锋到达特效", _target.rushArriveEffectID); _target.ghostEffectID = EditorGUILayout.IntField("幻影配置ID", _target.ghostEffectID); EditorGUILayout.LabelField("[碰撞检测]"); _target.bastType = (E_CastBaseType)EditorGUILayout.EnumPopup("碰撞检测基于", _target.bastType); _target.hitTestType = (E_HitTestType)EditorGUILayout.EnumPopup("碰撞检测方式", _target.hitTestType); if (_target.hitTestType == E_HitTestType.Rect) { _target.chkRange = EditorGUILayout.IntField("矩形宽度(米)", _target.chkRange); _target.chkDistance = EditorGUILayout.FloatField("检测距离(米)", _target.chkDistance); } else if (_target.hitTestType == E_HitTestType.Sector) { _target.chkRange = EditorGUILayout.IntField("扇形角度(0~359,0认为是360)", _target.chkRange); _target.chkRange = Mathf.Clamp(_target.chkRange, 0, 359); _target.chkDistance = EditorGUILayout.FloatField("检测半径(米)", _target.chkDistance); } // --------------------------------------------------------------------------------- GUILayout.Space(5); EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); EditorGUILayout.LabelField("帧事件编辑"); GUILayout.FlexibleSpace(); Color _originalColor = GUI.color; GUI.color = Color.green; if (GUILayout.Button("+", EditorStyles.toolbarButton)) { m_NewingData = true; } GUI.color = _originalColor; EditorGUILayout.EndHorizontal(); DrawNewFrameEvent(_target); DrawAnimationEvent(_target); if (GUI.changed) { EditorUtility.SetDirty(target); serializedObject.ApplyModifiedProperties(); } } private void DrawAnimationEvent(SoSkill target) { if (target.animationEventList.Count == 0) { EditorGUILayout.HelpBox("暂时没有任何的动画事件,请添加.", MessageType.Info); return; } int _toDeleteIndex = -1; EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); EditorGUILayout.LabelField("帧", EditorStyles.wordWrappedLabel, GUILayout.Width(40)); EditorGUILayout.LabelField("方法", EditorStyles.wordWrappedLabel, GUILayout.Width(100)); EditorGUILayout.LabelField("配置", EditorStyles.wordWrappedLabel, GUILayout.Width(150)); EditorGUILayout.LabelField("", GUILayout.Width(80)); EditorGUILayout.LabelField(""); EditorGUILayout.EndHorizontal(); for (int i = 0; i < target.animationEventList.Count; ++i) { EditorGUILayout.BeginHorizontal(EditorStyles.toolbar); EditorGUILayout.LabelField(target.animationEventList[i].index.ToString(), EditorStyles.wordWrappedLabel, GUILayout.Width(40)); target.animationEventList[i].frameEventType = (E_FrameEventType)EditorGUILayout.EnumPopup(target.animationEventList[i].frameEventType, EditorStyles.toolbarPopup, GUILayout.Width(100)); if (target.animationEventList[i].frameEventType == E_FrameEventType.OnSkillEvent) { SoSkill.E_AttackType _type = SoSkill.GetAttactType(target.animationEventList[i].intParam); int _id = SoSkill.GetFrameEventId(target.animationEventList[i].intParam); string _content = string.Format("{0}: {1}", _type, _id); if (GUILayout.Button(_content, EditorStyles.toolbarButton, GUILayout.Width(110))) { if (_type == SoSkill.E_AttackType.Sweep) { string _path = ResourcesPath.ResourcesOutAssetPath + "Refdata/ScriptableObject/SoSweepHit/SoSweepHit_" + _id + ".asset"; SoSweepHit _sh = AssetDatabase.LoadAssetAtPath(_path); if (_sh != null) { Selection.activeObject = _sh; } } else if (_type == SoSkill.E_AttackType.FlyObject) { string _path = ResourcesPath.ResourcesOutAssetPath + "Refdata/ScriptableObject/SoFlyObject/SoFlyObject_" + _id + ".asset"; SoFlyObject _fo = AssetDatabase.LoadAssetAtPath(_path); if (_fo != null) { Selection.activeObject = _fo; } } } } else if (target.animationEventList[i].frameEventType == E_FrameEventType.OnPlayEffect || target.animationEventList[i].frameEventType == E_FrameEventType.OnPlayAudio) { string _content = target.animationEventList[i].intParam.ToString(); if (GUILayout.Button(_content, EditorStyles.toolbarButton, GUILayout.Width(110))) { } } else if (target.animationEventList[i].frameEventType == E_FrameEventType.OnCreateGhost) { string _content = string.Format("Ghost: {0}", target.animationEventList[i].intParam); if (GUILayout.Button(_content, EditorStyles.toolbarButton, GUILayout.Width(110))) { string _path = ResourcesPath.ResourcesOutAssetPath + "Refdata/ScriptableObject/SoGhostShadow/SoGhostShadow_" + target.animationEventList[i].intParam + ".asset"; SoGhostShadow _fo = AssetDatabase.LoadAssetAtPath(_path); if (_fo != null) { Selection.activeObject = _fo; } } } else { GUILayout.Label("", EditorStyles.wordWrappedLabel, GUILayout.Width(102)); } if (GUILayout.Button("编辑", EditorStyles.toolbarButton, GUILayout.Width(40))) { m_EditIndex = i; m_EditAttackType = SoSkill.GetAttactType(target.animationEventList[i].intParam); m_EditFrameEventId = SoSkill.GetFrameEventId(target.animationEventList[i].intParam); m_EditFrameIdex = target.animationEventList[i].index; m_EditFrameEventType = target.animationEventList[i].frameEventType; } if (GUILayout.Button("删除", EditorStyles.toolbarButton, GUILayout.Width(40))) { _toDeleteIndex = i; } EditorGUILayout.LabelField(""); EditorGUILayout.EndHorizontal(); if (i == m_EditIndex) { DrawEditorFrameEvent(target, target.animationEventList[i]); } } if (_toDeleteIndex != -1) { target.animationEventList.RemoveAt(_toDeleteIndex); } } private void DrawEditorFrameEvent(SoSkill target, SoSkill.exAnimationClipEvent clipEvent) { GUILayout.Space(4); m_EditFrameEventType = (E_FrameEventType)EditorGUILayout.EnumPopup("方法名", m_EditFrameEventType); if (clipEvent.frameEventType == E_FrameEventType.OnSkillEvent) { m_EditFrameIdex = EditorGUILayout.IntField("触发帧", m_EditFrameIdex); m_EditAttackType = (SoSkill.E_AttackType)EditorGUILayout.EnumPopup("攻击方式", m_EditAttackType); m_EditFrameEventId = EditorGUILayout.IntField("配置ID", m_EditFrameEventId); } else if (clipEvent.frameEventType == E_FrameEventType.OnPlayEffect) { m_EditFrameIdex = EditorGUILayout.IntField("触发帧", m_EditFrameIdex); m_EditFrameEventId = EditorGUILayout.IntField("特效ID", m_EditFrameEventId); } else if (clipEvent.frameEventType == E_FrameEventType.OnSkillComplete || clipEvent.frameEventType == E_FrameEventType.OnSkillPrepare) { m_EditFrameIdex = EditorGUILayout.IntField("触发帧", m_EditFrameIdex); } else if (clipEvent.frameEventType == E_FrameEventType.OnAnimationPause || clipEvent.frameEventType == E_FrameEventType.OnTimePause) { m_EditFrameIdex = EditorGUILayout.IntField("触发帧", m_EditFrameIdex); m_EditFrameEventId = EditorGUILayout.IntField("停顿时间(毫秒)", m_EditFrameEventId); } else if (clipEvent.frameEventType == E_FrameEventType.OnCreateGhost || clipEvent.frameEventType == E_FrameEventType.OnPlayAudio) { m_EditFrameIdex = EditorGUILayout.IntField("触发帧", m_EditFrameIdex); m_EditFrameEventId = EditorGUILayout.IntField("配置ID", m_EditFrameEventId); } EditorGUILayout.BeginHorizontal(); if (SoSkill.GetAttactType(clipEvent.intParam) != m_EditAttackType || SoSkill.GetFrameEventId(clipEvent.intParam) != m_EditFrameEventId || m_EditFrameIdex != clipEvent.index || m_EditFrameEventType != clipEvent.frameEventType) { if (GUILayout.Button("修改")) { if (m_EditFrameEventType == E_FrameEventType.OnSkillEvent) { clipEvent.intParam = (((int)m_EditAttackType) << 16) | m_EditFrameEventId; } else { clipEvent.intParam = m_EditFrameEventId; } if (clipEvent.index != m_EditFrameIdex) { clipEvent.index = m_EditFrameIdex; SortAnimationEventList(target); } clipEvent.frameEventType = m_EditFrameEventType; m_EditIndex = -1; } } if (GUILayout.Button("取消")) { m_EditIndex = -1; } EditorGUILayout.EndHorizontal(); GUILayout.Space(4); } private void DrawNewFrameEvent(SoSkill target) { if (m_NewingData) { GUILayout.Space(5); m_NewDataIndex = EditorGUILayout.IntField("触发帧", m_NewDataIndex); m_NewFrameEventType = (E_FrameEventType)EditorGUILayout.EnumPopup("方法名", m_NewFrameEventType); if (m_NewFrameEventType == E_FrameEventType.OnSkillEvent) { m_NewAttackType = (SoSkill.E_AttackType)EditorGUILayout.EnumPopup("攻击方式", m_NewAttackType); m_NewFrameEventId = EditorGUILayout.IntField("配置ID", m_NewFrameEventId); } else if (m_NewFrameEventType == E_FrameEventType.OnPlayEffect) { m_NewFrameEventId = EditorGUILayout.IntField("特效ID", m_NewFrameEventId); } else if (m_NewFrameEventType == E_FrameEventType.OnAnimationPause || m_NewFrameEventType == E_FrameEventType.OnTimePause) { m_NewFrameEventId = EditorGUILayout.IntField("停顿时间(毫秒)", m_NewFrameEventId); } else if (m_NewFrameEventType == E_FrameEventType.OnCreateGhost || m_NewFrameEventType == E_FrameEventType.OnPlayAudio) { m_NewFrameEventId = EditorGUILayout.IntField("配置ID", m_NewFrameEventId); } EditorGUILayout.BeginHorizontal(); if (GUILayout.Button("添加")) { SoSkill.exAnimationClipEvent _animationEvent = new SoSkill.exAnimationClipEvent(); _animationEvent.index = m_NewDataIndex; _animationEvent.frameEventType = m_NewFrameEventType; if (m_NewFrameEventType == E_FrameEventType.OnSkillEvent) { _animationEvent.intParam = (((int)m_NewAttackType) << 16) | m_NewFrameEventId; } else { _animationEvent.intParam = m_NewFrameEventId; } target.animationEventList.Add(_animationEvent); SortAnimationEventList(target); m_NewingData = false; } if (GUILayout.Button("取消")) { m_NewingData = false; } EditorGUILayout.EndHorizontal(); } } private void SortAnimationEventList(SoSkill target) { target.animationEventList.Sort((SoSkill.exAnimationClipEvent a, SoSkill.exAnimationClipEvent b) => { if (a.index > b.index) { return 1; } else if (a.index < b.index) { return -1; } return 0; }); } } #endif