Unity Engine

Player Dash, Skill CoolTime(Cooldown)

SB_J00N 2023. 4. 10. 17:41
///////////////////////// 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이 바뀌거나, 실행 된 순간, 실행 종료 후 등의 능력 구현등이 있을 것 같다. 참 산넘어 산인데 재밌긴하다. 뭔가 겹겹이 쌓아올리는 느낌이 나쁘지많은 않다.