You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
351 lines
10 KiB
351 lines
10 KiB
using Spine; |
|
using Spine.Unity; |
|
using Spine.Unity.AttachmentTools; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
using UnityEngine; |
|
|
|
public class Motion : MonoBehaviour |
|
{ |
|
public enum Type { Idle, Run, RunBack, Attack, AttackUp, AttackDown, AttackEnd, Die, Hit, Idle2, Get, Appear } |
|
//public enum Emoji { Normal, Shoot } |
|
|
|
[System.Serializable] |
|
public class SpineControl |
|
{ |
|
public Motion.Type type; |
|
//public Motion.Emoji emoji; |
|
|
|
[Space(10)] |
|
[SpineAnimation] |
|
public string name; |
|
public int layer = 1; |
|
public bool loop = false; |
|
|
|
[Space] |
|
public float timeScale = 1f; |
|
[Space] |
|
public bool useMixDuration = true; |
|
public float mixDuration = 0.1f; |
|
//public bool useChainToControl; |
|
//public int chainToControl; |
|
} |
|
|
|
public SkeletonAnimation skeletonAnimation; |
|
Spine.AnimationState spineState; |
|
Skeleton skeleton; |
|
[Space(10)] |
|
public List<SpineControl> controls; |
|
Dictionary<Type, SpineControl> dicControls = null; |
|
List<SpineControl> idles = null; |
|
void Start() |
|
{ |
|
spineState = skeletonAnimation.state; |
|
skeleton = skeletonAnimation.Skeleton; |
|
|
|
if (dicControls == null) |
|
{ |
|
dicControls = new Dictionary<Type, SpineControl>(); |
|
idles = new List<SpineControl>(); |
|
for (int i = 0; i < controls.Count; i++) |
|
{ |
|
if (controls[i].type == Type.Idle) |
|
idles.Add(controls[i]); |
|
else |
|
dicControls.Add(controls[i].type, controls[i]); |
|
} |
|
values = new List<SpineControl>(dicControls.Values); |
|
} |
|
|
|
//Play(Type.Idle); |
|
} |
|
void OnEnable() |
|
{ |
|
typeBefore = Motion.Type.AttackEnd; |
|
} |
|
void OnDisable() |
|
{ |
|
Play(Type.Idle); |
|
} |
|
|
|
[Space(10)] |
|
public bool isATK = false; |
|
/// <summary> |
|
/// 공격 모션 중인지 확인합니다. |
|
/// </summary> |
|
/// <returns></returns> |
|
public bool Check_ATK() |
|
{ |
|
return typeBefore == Type.Attack; |
|
} |
|
/// <summary> |
|
/// 등장 모션 중인지 확인합니다. |
|
/// </summary> |
|
/// <returns></returns> |
|
public bool Check_Appear() |
|
{ |
|
return typeBefore == Type.Appear; |
|
} |
|
public Motion.Type typeBefore = Motion.Type.AttackEnd; |
|
/// <summary> |
|
/// 죽는 모션 중인지 확인합니다. |
|
/// </summary> |
|
/// <returns></returns> |
|
public bool Check_Die() |
|
{ |
|
return typeBefore == Type.Die; |
|
} |
|
|
|
/// <summary> |
|
/// 스파인 애니메이션을 재생합니다. |
|
/// </summary> |
|
/// <param name="type"></param> |
|
/// <param name="FORCE">true = 강제 재생</param> |
|
/// <param name="OnEnd">모션 종료시 호출</param> |
|
/// <param name="OnEvent">모션 이벤트 발생시 호출</param> |
|
/// <param name="RESET"></param> |
|
public void Play(Motion.Type type, bool FORCE = false, System.Action OnEnd = null, System.Action<Spine.Event> OnEvent = null, bool RESET = false) |
|
{ |
|
//if (Check_Die() && !FORCE)//원래 코드, 테스트 진행 후 이상 없으면 삭제 |
|
if (Check_Die()) |
|
return; |
|
|
|
if (FORCE || typeBefore != type) |
|
{ |
|
if (dicControls == null) |
|
Start(); |
|
|
|
TrackEntry track = null; |
|
SpineControl control = null; |
|
|
|
if (type == Type.Idle) |
|
control = idles[Random.Range(0, idles.Count)]; |
|
else |
|
control = dicControls[type]; |
|
|
|
if (control == null) |
|
return; |
|
|
|
switch (type) |
|
{ |
|
case Motion.Type.Attack: |
|
case Motion.Type.AttackUp: |
|
case Motion.Type.AttackDown: |
|
{ |
|
isATK = true; |
|
|
|
typeBefore = type; |
|
track = spineState.SetAnimation(control.layer, control.name, control.loop); |
|
} |
|
break; |
|
case Type.AttackEnd: |
|
{ |
|
if (isATK) |
|
{ |
|
isATK = false; |
|
|
|
typeBefore = type; |
|
track = spineState.SetEmptyAnimation(control.layer, 0.2f); |
|
} |
|
} |
|
break; |
|
case Type.Hit: |
|
{ |
|
typeBefore = type; |
|
track = spineState.SetAnimation(control.layer, control.name, control.loop); |
|
} |
|
break; |
|
default: |
|
{ |
|
typeBefore = type; |
|
track = spineState.SetAnimation(control.layer, control.name, control.loop); |
|
} |
|
break; |
|
} |
|
|
|
if (track != null) |
|
{ |
|
if (control != null) |
|
{ |
|
track.MixDuration = control.useMixDuration ? control.mixDuration : 0; |
|
track.TimeScale = control.timeScale; |
|
} |
|
|
|
if (OnEnd != null) |
|
{ |
|
track.Complete += delegate (TrackEntry entry) |
|
{ |
|
OnEnd(); |
|
}; |
|
} |
|
|
|
if (OnEvent != null) |
|
{ |
|
track.Event += delegate (TrackEntry trackEntry, Spine.Event e) |
|
{ |
|
OnEvent(e); |
|
|
|
if (RESET) |
|
track.ResetEvent(); |
|
}; |
|
} |
|
} |
|
} |
|
} |
|
public bool isSkill = false; |
|
/// <summary> |
|
/// 애니메이션을 강제 재생 합니다. |
|
/// 현재는 캐릭터가 스킬을 사용할때만 사용되는 중입니다. |
|
/// </summary> |
|
/// <param name="control"></param> |
|
/// <param name="OnEnd"></param> |
|
/// <param name="OnEvent"></param> |
|
/// <returns></returns> |
|
public bool Play_Force(SpineControl control, System.Action OnEnd = null, System.Action<Spine.Event> OnEvent = null) |
|
{ |
|
//if (Check_Die()) |
|
// return false; |
|
|
|
if (spineState == null) |
|
Start(); |
|
|
|
TrackEntry track = spineState.SetAnimation(control.layer, control.name, control.loop); |
|
|
|
if (track != null) |
|
{ |
|
if (control != null) |
|
{ |
|
track.MixDuration = control.useMixDuration ? control.mixDuration : 0; |
|
track.TimeScale = control.timeScale; |
|
} |
|
|
|
if (OnEnd != null) |
|
{ |
|
track.Complete += delegate (TrackEntry entry) |
|
{ |
|
OnEnd(); |
|
}; |
|
} |
|
|
|
if (OnEvent != null) |
|
{ |
|
track.Event += delegate (TrackEntry trackEntry, Spine.Event e) |
|
{ |
|
OnEvent(e); |
|
}; |
|
} |
|
} |
|
|
|
return true; |
|
} |
|
//public void Play_Force(string name, int layer, bool loop, System.Action OnEnd = null, System.Action<Spine.Event> OnEvent = null) |
|
//{ |
|
// if (Check_Die()) |
|
// return; |
|
|
|
// if (spineState == null) |
|
// Start(); |
|
|
|
// TrackEntry track = spineState.SetAnimation(layer, name, loop); |
|
|
|
// if (track != null) |
|
// { |
|
// if (OnEnd != null) |
|
// { |
|
// track.Complete += delegate (TrackEntry entry) |
|
// { |
|
// OnEnd(); |
|
// }; |
|
// } |
|
|
|
// if (OnEvent != null) |
|
// { |
|
// track.Event += delegate (TrackEntry trackEntry, Spine.Event e) |
|
// { |
|
// OnEvent(e); |
|
// }; |
|
// } |
|
// } |
|
//} |
|
|
|
//표정 변경 |
|
//public List<SpineControl> controls_Emoji; |
|
//Dictionary<Emoji, SpineControl> dicControls_Emoji = new Dictionary<Emoji, SpineControl>(); |
|
//public void Play_Emoji(Motion.Emoji type) |
|
//{ |
|
// SpineControl control = dicControls_Emoji[type]; |
|
// spineState.SetAnimation(control.layer, control.name, control.loop); |
|
//} |
|
|
|
//public void ClearLayer(int layer) |
|
//{ |
|
// spineState.SetEmptyAnimation(layer, 0.2f); |
|
//} |
|
|
|
Vector3 scale = Vector3.one; |
|
/// <summary> |
|
/// 캐릭터가 바라볼 방향을 설정합니다. |
|
/// </summary> |
|
/// <param name="x"></param> |
|
public void LookSet(float x) |
|
{ |
|
scale.x = x == 0 ? 0 : (x < 0 ? -1 : 1); |
|
skeletonAnimation.transform.localScale = scale; |
|
} |
|
/// <summary> |
|
/// 바라보고 있는 방향을 확인합니다. |
|
/// </summary> |
|
/// <returns></returns> |
|
public Vector3 LookDir() |
|
{ |
|
return scale.x < 0 ? Vector3.right : Vector3.left; |
|
} |
|
|
|
[Space(10)] |
|
public List<SpineControl> values; |
|
[Space(10)] |
|
//public float spdMovePer; |
|
public float spdDevision = 2f; |
|
/// <summary> |
|
/// 변경된 이동속도 값을 반영합니다. |
|
/// </summary> |
|
/// <param name="spd"></param> |
|
public void OnMoveSpeedChanged(float spd) |
|
{ |
|
//spdMovePer = spd; |
|
//spdMovePer = 1 + (spd - (int)spd) * spdDevision; |
|
|
|
//values = new List<SpineControl>(dicControls.Values); |
|
List<SpineControl> list = values.FindAll(a => $"{a.type}".Contains("Run")); |
|
for (int i = 0; i < list.Count; i++) |
|
list[i].timeScale = timeScaleRun * spd; |
|
} |
|
/// <summary> |
|
/// 캐릭터의 모든 이동 애니메이션의 TimeSclae(재생 속도) 를 설정합니다. |
|
/// </summary> |
|
/// <param name="value"></param> |
|
public float timeScaleRun = 1; |
|
public void RunMotionTimeScaleChanged(float value) |
|
{ |
|
if (dicControls == null) |
|
Start(); |
|
|
|
SpineControl control = values.Find(a => a.type == Type.Run); |
|
control.timeScale = timeScaleRun = value; |
|
} |
|
|
|
public float spdAtkPer; |
|
/// <summary> |
|
/// 변경된 공격속도 값을 반영합니다. |
|
/// </summary> |
|
/// <param name="spd"></param> |
|
public void OnAttackSpeedChanged(float spd) |
|
{ |
|
spdAtkPer = spd; |
|
|
|
//values = new List<SpineControl>(dicControls.Values); |
|
List<SpineControl> list = values.FindAll(a => $"{a.type}".Contains("Attack")); |
|
for (int i = 0; i < list.Count; i++) |
|
list[i].timeScale = spdAtkPer; |
|
} |
|
}
|
|
|