Unity 2D RPG - 2. 쯔꾸르식 액션 구현하기

2023. 8. 10. 02:38C# & Unity 공부

오늘은 플레이어를 상하좌우 이동하게 것을 구현해 볼 것이다. (쯔꾸르 식으로)

 

우선 시작하기에 앞서 저번에 맵을 대충 만들어보았는데, 좀 더 있어보이게 꾸며보자.

 

 

위 사진처럼 꾸미면 된다. 캐릭터에게는 애니메이션도 넣어주자.

 

 

플레이어 십자 이동

 

우리가 저번 시간에는 코드를 대충 짜보았다.

하지만 우리의 코드대로 작성하여 실행 시킨다면 대각선도 이동하게 된다.

하지만 쯔꾸르에서는 대각선 이동을 허용하지 않는다.

 

 bool hDown = Input.GetButtonDown("Horizontal");
 bool vDown = Input.GetButtonDown("Vertical");
 bool hUp = Input.GetButtonUp("Horizontal");
 bool vUp = Input.GetButtonUp("Vertical");

 

if (hDown)
     isHorizonMove = true;
else if (vDown)
     isHorizonMove = false;

 

바로 위에 있는 코드처럼 작성을 한다면

왼쪽을 눌렀다가 위 키를 누르고, 다시 위쪽 키를 떼면

왼쪽으로 이동하지 않는다.

 

if (hDown || vUp)
     isHorizonMove = true;
else if (vDown || hUp)
     isHorizonMove = false;

 

위와 같이 수평키나 수직키를 올린 경우도 생각하면 된다.

 

속도는 삼항 연산자를 이용해서 써주면 된다.

Vector2 moveVec=isHorizonMove?new Vector2(h,0):new Vector2(0,v);
rigid.velocity = moveVec * Speed;

 

애니메이션 설정

 

우선 플레이어에 대한 상하좌우 대기 모션과 걷는 모션에 대한 애니메이션 파일을 만들자.

그러면 아래와 같을 것이다.

 

 

다음은 Down_Idle을 기준으로 하고, 애니메이터 창의 내용물들을 연결시켜보자.

 

 

Make Transition을 통해 화살표들을 연결해 주었다.

그리고 애니메이션 시간은 Transition Duration을 0으로 설정하여 바꾸어주었다.

(원래는 오른쪽에 있던 표를 다 왼쪽으로 끌어서 했었음)

 

그리고 Parameters에서 hAxisRaw와 vAxisRaw를 변수를 Int로 만들었다.

각각은 수평과 수직상태인지를 나타내주었다.

상하좌우에서 각각의 애니메이션으로 가는 길을 클릭하여 Conditions에서 알맞은 변수를 넣고

그 값에 따라 바뀌게끔 설정하였다.

 

Animator anim;

//Awake 함수에 넣을 것
anim=GetComponent<Animator>();

//Update 함수에 넣을 것
anim.SetInteger("hAxisRaw", (int)h);
anim.SetInteger("vAxisRaw", (int)v);

 

코드는 위와 같다.

 

하지만 이대로 실행한다면 걷는 모션이 나오지 않는다.

그 이유는 Update 함수가 계속 돌면서 SetInteger() 함수를 통해 계속 값이 설정되면서

애니메이션을 다시 시작하는 것이 반복되는 것이다.

 

그래서 다음과 같이 코드를 짜볼 것이다.

 

 //Animation
        if (anim.GetInteger("hAxisRaw") != h)
        {
            anim.SetBool("isChange", true);
            anim.SetInteger("hAxisRaw", (int)h);
        }

        else if (anim.GetInteger("vAxisRaw") != v)
        {
            anim.SetBool("isChange", true);
            anim.SetInteger("vAxisRaw", (int)v);
        }

        else
            anim.SetBool("isChange", false);

 

isChange라는 Bool 변수를 Parameters에서 생성 후, Conditions에서 True로 추가해준다.

위 코드대로라면 현재 hAxisRaw나 vAxisRaw의 값과 다른 값이 h나 v를 통하여 들어올 떄만

isChange가 true가 되는데 잠깐 되는 것이기 때문에 그 잠깐 동안만 화살표가 실행이 되는 것이고,

반복되지 않아 애니메이션이 실행되는 순간만 반복 되는 문제를 해결한 것이다.

 

하지만 마지막 오류를 찾아냈는데,

좌측 키를 꾹 누르고 있는 도중에 우측 키를 눌렀다 떼면, 좌측으로 이동하지 않는다는 점이다.

(좌우나 상하 모든 경우 발생함)

 

코드를 다음과 같이 수정하자.

 

if (hDown)
      isHorizonMove = true;
else if (vDown)
      isHorizonMove = false;
else if (hUp)
      isHorizonMove = h != 0;

 

그러면 잘 움직이게 된다.

 

(2023.08.13 오류 찾음 =>수직 방향키 누른채로 수평 방향키를 누르면 이동은 되나 애니메이션 방향이 옳지 않음)

 

조사 액션

 

이번에는 플레이어 앞에 있는 물건을 스캔할 수 있도록 구현해볼 것이다.

Ray를 사용할 것이다.

 

우선 Ray를 만들어주어야 한다.

 

//FixedUpdate()-Draw Ray
Debug.DrawRay(rigid.position, 벡터값, new Color(0,1,0));

 

근데 캐릭터가 상하좌우로 이동하면서 이 Ray의 방향 값은 바뀌게 된다.

(벡터가 다르다는 뜻)

 

그래서 단위벡터인데 입력하는 값에 따라 바뀌는 벡터 변수를 만들 것이다.

 

//변수 선언
Vector3 dirVec;

//Update()- 벡터의 Direction(방향)을 결정하는 코드
if (vDown && v == 1)
    dirVec = Vector3.up;
else if (vDown && v == -1)
    dirVec = Vector3.down;
else if (hDown && h == -1)
    dirVec = Vector3.left;
else if (hDown && h == 1)
    dirVec = Vector3.right;

 

그리고 FixedUpdate에 dirVec 변수를 사용하여 벡터값을 넣은 DrawRay 함수를 써주면  된다.

 

//Ray
Debug.DrawRay(rigid.position, dirVec * 0.7f, new Color(0, 1, 0));

 

생긴 초록선 (Ray), 방향을 바꿀 시에도 알맞게 바뀐다.

 

그리고 Npc들이나 Box, Desk 같은 오브젝트들에게 Object라는 이름의 Layer을 만들어준다.

이유는 Raycast 함수를 쓸 때, 빔이 Player의 collider에 닿는 것을 방지하기 위해 LayerMask.GetMask()를 쓸것이다.

무튼 Layer을 만든 뒤 적용시킨 다음 코드를 작성한다.

 

 RaycastHit2D rayhit=Physics2D.Raycast(rigid.position, dirVec, 0.7f, LayerMask.GetMask("Object"));

 

이러면 빔을 쏴서 Object에 해당 되는 사물들만 정보를 가지고 온다.

그리고 GameObject 변수를 만든 뒤 저장할 것이다.

 

//GameObject 변수 선언
GameObject scanObject;

//FixedUpdate()-scanObject에 저장하기
if(rayhit.collider!=null)
{
    scanObject=rayhit.collider.gameObject;
}
else
    scanObject=null;

 

그리고 마지막으로 spcaebar을 눌렀을 때 Console창에 물체의 정보가 뜨게 끔 작성할 것이다.

Unity에서 Jump를 spacebar로 지정했기 때문에 Jump를 사용한다.

( Edit > Project Settings > Input Manager을 통해 확인가능)

 

//Scan Object
if(Input.GetButtonDown("Jump")&&scanObject!=null)
{
     Debug.Log("This is : " + scanObject.name);
}

 

실행하면

 

 

 

잘 실행되는 것을 확인할 수 있다.