Notice
Recent Posts
Recent Comments
Link
«   2026/06   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

개발일기

유니티#10 점프 로직 변경, switch문 본문

Unity

유니티#10 점프 로직 변경, switch문

kimjw7815 2024. 12. 30. 19:38
//PlayerMove.cs
private bool isJumping;
private bool direction;
private bool onGround;
private bool hasDoubleJumped;
private float hInput, vInput;

public Vector2 GetInput() {return new Vector2(hInput, vInput);}
public bool GetHasDoubleJumped() {return hasDoubleJumped;}
public void SetHasDoubleJumped(bool value) {hasDoubleJumped=value;}
public bool GetIsJumping() {return isJumping;}
public bool GetDirection() {return direction;}
public bool GetOnGround() {return onGround;}

void Update()
{
    hInput=Input.GetAxisRaw("Horizontal");
    vInput=Input.GetAxisRaw("Vertical");
    
    // 생략 ...
}

PlayerMove.cs에 hasDoubleJumped와 hInput, vInput을 선언해준다.

다른 스크립트에서 쓸 변수들은 게터와 세터도 설정해준다.

isJumping과 hasDoubleJumped를 점프 관련 로직에 활용해줄 거다.

 

//SkillHandler.cs
void RushFunc() {
    float xRush=15f*(playerMove.GetDirection()?1:-1);
    float yRush=5f;
    if (playerMove.GetInput().y>0) {
        xRush=0.75f*playerObject.GetComponent<Rigidbody2D>().linearVelocity.x;
        yRush=15f;
        this.gameObject.transform.parent.rotation=Quaternion.Euler(0f, 0f, 90f*(playerMove.GetDirection()?1:-1));
    }
    rb.linearVelocity=new Vector2 (xRush,yRush);
    playerMove.SetHasDoubleJumped(true);
}
//PlayerMove.cs
private void OnCollisionEnter2D(Collision2D other) {
    if (other.gameObject.CompareTag("Ground") && IsFullyOnGround(other)) {
        isJumping=false;
        onGround=true;
        hasDoubleJumped=false;
    }
}

더블 점프 대용으로 써줄 스킬도 설정해준다.

참고로 this.gameObject.transform.parent라고 하면 부모 오브젝트의 transform을 말하는 건데, 할당되는 오브젝트가 colliderObject이니, 저건 skillObject의 transform을 말한다.

스킬 오브젝트를 회전시켜 주기 위해 Quaternion.Euler를 쓰는데, rotation은 Vector3이 아니기 때문이다.

젠장 또 오일러야

 

hasDoubleJumped는 조건문으로 써주기 위해서 설정해 주는데, 처음엔 SkillHandler에서 설정하고자 했다.

근데 SkillHandler는 콜라이더 오브젝트에서 소환하다 보니까, 값을 일관되게 유지하는 게 근본적으로 불가능했다.

스킬할 때마다 오브젝트는 다 따로 생기고, SkillHandler 컴포넌트와 그 속의 hasDoubleJumped도 다 따로 있는 거니까..

그래서 어쩔 수 없이 PlayerMove.cs에 저장해주었다. 스킬 변수 관련 스크립트를 따로 만들어줘도 될지도...

 

//SkillHandler.cs
public bool CanActivateSkill(string skillName)
{
    switch (skillName)
    {
        case "rush":
            return !playerMove.GetHasDoubleJumped() && !playerMove.GetOnGround(); // !(hasDoubleJumped || playerMove.GetOnGround())
        case "slash":
        case "boom":
            return true; // 다른 스킬은 조건 없이 항상 실행 가능
        default:
            return false;
    }
}

더블 점프는 발동 조건이 여럿 있다보니 스킬이 발동되기 전 그 조건을 만족하는지 확인해주어야 하는데, 여기서 사용한 것이 switch문이다.

특정 변수에 대하여 각각의 case에 따라 다른 코드를 실행시키게 해주는 구문인데, if문을 더 보기 좋게 한다는 것이라고 볼 수 있다.

 

이런 식으로 모든 로직들을 다 만들어줬었는데, 땅에 붙어있는 상태로 점프를 했는데도 스킬이 발동 되는 버그가 있었다.

이건 PlayerSkill.cs에서 스킬을 발동시키는 로직에 관한 문제였다.

//PlayerSkill.cs
void UseSkill(SkillData skillData) {
    // 스킬 사용
    // Debug.Log("Skill triggered!");

    // skillObject 생성
    bool direction = playerMove.GetDirection();
    Vector3 skillPosition = transform.position + skillData.skillPositionOffset*(direction?1:-1);

    GameObject skillObject = new GameObject(skillData.skillName);
    skillObject.transform.position = skillPosition;
    // skillObject에 관련한 각종 설정들...
    
    // colliderObject
    GameObject colliderObject = new GameObject(skillData.skillName+" collider");
    // colliderObject에 관련한 각종 설정들...
    
    // 이거!!!!!!!!!!!!!!!!!!
    SkillHandler skillHandler=colliderObject.AddComponent<SkillHandler>();
    skillHandler.ActivateSkill(skillData.skillName);

    // 스킬 자동 삭제
    Destroy(skillObject, skillData.skillVanishmentTime); // n초 뒤 삭제
    Destroy(colliderObject, skillData.skillVanishmentTime); // n초 뒤 삭제
}

보다시피 ActivateSkill(skillData.skillName)을 실행시키는 건 이미 skillObject를 생성한 이후이므로, 스킬 발동을 제어한다고 해도 이미 이펙트가 생성된 이후이다. 그래서 스킬 제어를 UseSkill()이 호출되기 전에 시행해주어야 한다.

 

//PlayerSkill.cs
void Update()
{
    for (int i = 0; i < skillDataArray.Length; i++)
    {
        // 키다운 감지
        // 시간 계산

        GameObject tempSkillHandlerObj = new GameObject("TempSkillHandler");
        SkillHandler tempSkillHandler = tempSkillHandlerObj.AddComponent<SkillHandler>();
        if (!tempSkillHandler.CanActivateSkill(skillDataArray[i].skillName))
        {
            Debug.Log($"Skill '{skillDataArray[i].skillName}' cannot be activated due to conditions.");
            Destroy(tempSkillHandlerObj);
            return;
        }
        Destroy(tempSkillHandlerObj);

        lastSkillTimes[i]=Time.time;
        UseSkill(skillDataArray[i]);
    }
}

일시적으로 tempSkillHandlerObj를 만들어서 스킬 시행이 가능한지 확인한 후 UseSkill()을 호출한다.

 

 

디버깅의 흔적들

'Unity' 카테고리의 다른 글

유니티#12 Hierarchy 정리, Tilemap 활용  (0) 2025.01.01
유니티#11 Tilemap  (0) 2024.12.31
유니티#9 델리게이트 리스트, Awake, OverlapBoxAll  (1) 2024.12.28
유니티#8 스프라이트 반복  (0) 2024.12.27
유니티#7 colliderObject  (0) 2024.12.27