Super Knight : Enter the Dungeon
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.

352 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;
}
}