Player Dash, Skill CoolTime(Cooldown)
///////////////////////// Player Action /////////////////////////
public PlayerInput input;
[NonSerialized] public Vector3 moveVec;
private InputAction _normalMoveAction;
// private InputAction _specialMoveAction;
public bool disableMove;
public bool disableAction;
public float moveSpeed;
public float defaultSpeed = 30.0f;
private float defaultDashTime = 0.2f;
[NonSerialized] public float moveSpeedMultiplier = 1;
private GameObject skillContainer;
///////////////////////// Dash and Coroutine /////////////////////////
private float dashTime;
private bool isDash = false;
private float dashSpeed = 70.0f;
private float dashCoolTime = 5.0f;
WaitForSeconds _delay50 = new WaitForSeconds(5.0f);
private bool isSkillOnCooldown = false;
WaitForFixedUpdate wait;
Rigidbody2D rigid;
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space) && !isSkillOnCooldown && currentStateName == "IdleState")
{
Dash();
dashTime = 0;
StartCoroutine(SkillCooldown());
}
dashTime += Time.deltaTime;
if (dashTime > dashCoolTime)
{
dashTime = 5;
}
UpdateIcon(dashTime);
}
#region Dash(Special Move), KnockBack
private void Dash()
{
moveSpeed = dashSpeed;
Invoke("FinishDash", defaultDashTime);
}
private void FinishDash()
{
moveSpeed = defaultSpeed;
}
private IEnumerator SkillCooldown()
{
isSkillOnCooldown = true;
yield return _delay50;
isSkillOnCooldown = false;
}
private void UpdateIcon(float currentTime)
{
spaceSkillIcon.fillAmount = currentTime / dashCoolTime;
}
#endregion
https://www.youtube.com/watch?v=ONNjyFuf0Tk
기존에 위에 영상을 참고해서 코드를 만들고, 조금 수정을 하다 보니깐 코루틴, Update, Invoke까지 쓰게됐다. 복잡해보여도 어찌저찌 잘 작동은 한다. 그래서 혹시 나중에 쓸 지 몰라 저장용으로 올려놓는다.
하지만 PlayerController.cs에 너무 많은 Method이 있어서 분리하기로 했고, 생각해보니깐 Coroutine 하나만 쓰면 구현할 수 있을 것 같아서, 코드를 수정하기로 했다.
수정하면서 추가로 작업한 것은
1. Dash를 비롯한 여러 스킬들을 위한 부모 Class를 테스트로 만들어보고
2. 최대한 간단하게 구현 이였다.
public abstract class SkillAction : MonoBehaviour
{
[SerializeField] private InputActionAsset inputs;
[SerializeField] private float coolDown;
private InputAction _skillAction;
private float coolDownTimer;
private void Start()
{
this._skillAction = this.inputs.FindActionMap("Player", false).FindAction("Skill", false);
this._skillAction.performed += this.UseSkillInputAction;
this.Init();
}
private void Update()
{
if (this.coolDownTimer > 0f)
{
this.coolDownTimer -= Time.deltaTime;
}
}
private void OnDestroy()
{
this._skillAction.performed -= this.UseSkillInputAction;
}
private void UseSkillInputAction(InputAction.CallbackContext context)
{
if (this.coolDownTimer <= 0f && !PauseManager.Inst.isPause)
{
this.coolDownTimer += this.coolDown;
this.UseSkill();
}
}
protected abstract void UseSkill();
protected virtual void Init()
{
}
}
추상 class를 만들어, Dash외에도 다른 스킬에서도 쓸 수 있게 구조를 만들었다.
자식 class에서 구현할 내용은 UseSkill, Init Method이다.
Start 문에서는, Input Action Asset의 "Player"라는 이름을 가진 ActionMap을 찾고, 만약에 있으면 "Skill" Action을 들고와
InputAction(skillAction)에 넣는다. (없으면 그냥 null)
그 후에, InputAction(skillAction)이 performed 되면, UseSkillInputAction Method가 실행된다.
그외에 Update 문은 쿨다운(쿨타임) 문이다. 예를들어 쿨다운이 5초면 5초동안은 실행안되게 하는 것이다.
public class Dash : SkillAction
{
private float dashSpeed = 90.0f;
private float dashDuration = 0.3f;
private float defaultSpeed;
protected override void Init()
{
}
protected override void UseSkill()
{
StartCoroutine(this.DashCoroutine());
}
private IEnumerator DashCoroutine()
{
PlayerController.Inst.canNothing.ToggleOn();
this.defaultSpeed = PlayerController.Inst.defaultSpeed;
PlayerController.Inst.moveSpeed = this.dashSpeed;
yield return new WaitForSeconds(this.dashDuration);
PlayerController.Inst.canNothing.ToggleOff();
PlayerController.Inst.moveSpeed = this.defaultSpeed;
yield break;
}
}
따로 Init 할 부분은 없어서 만들진 않았고, UseSkill에서는 DashCoroutine을 시작한다.
DashCoroutine은 곰곰히 생각해봤는데, 결국 "대쉬하는 시간"동안 "이동속도가 증가한다" 이 두개면 구현 완료라,
코루틴 메소드 하나로 깔끔하게 구현했다.
여기서 더 할 수 있는 것은 이제, 다른 skill들 처럼, stat이 바뀌거나, 실행 된 순간, 실행 종료 후 등의 능력 구현등이 있을 것 같다. 참 산넘어 산인데 재밌긴하다. 뭔가 겹겹이 쌓아올리는 느낌이 나쁘지많은 않다.