using UnityEngine;
|
using System.Collections.Generic;
|
|
#if UNITY_EDITOR
|
using UnityEditor;
|
#endif
|
|
public class SoSkill : ScriptableObject
|
{
|
/// <summary>
|
/// 攻击类型
|
/// 配置的组合类型应该为 0x0000 0000 0000 0000
|
/// 前8位表示攻击类型,后8位表示数据id索引
|
/// </summary>
|
public enum E_AttackType
|
{
|
Sweep,
|
FlyObject,
|
}
|
|
/// <summary>
|
/// 动画状态名哈希值
|
/// </summary>
|
//public int action;
|
|
/// <summary>
|
/// 动画时间
|
/// </summary>
|
//public float time;
|
|
/// <summary>
|
/// 动画帧率
|
/// </summary>
|
//public float frameRate;
|
|
/// <summary>
|
/// 可衔接的下一个技能id
|
/// </summary>
|
//public int nextSkillId;
|
|
/// <summary>
|
/// 前置技能id
|
/// </summary>
|
//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<exAnimationClipEvent> animationEventList = new List<exAnimationClipEvent>();
|
|
[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<SoSweepHit>(_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<SoFlyObject>(_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<SoGhostShadow>(_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
|