[Unity] 게임 따라 만들기(3)

정회민·2023년 4월 17일

유니티

Script

이동 같은 기능을 구현하기 위해선 C# 언어로 구현된 파일을 객체에 주입해야한다.
C# 파일을 만든 후 객체에 drag & drop 하면 해당 객체의 "Inspector"에서 확인할 수 있다.

코딩

Inspector의 컴포넌트를 코드에서 사용하고 싶다면 아래와 같이 class 변수로 선언하고 Awake() 함수에서 초기화해주면 된다.

using UnityEngine;

public class PlayerMove : MonoBehaviour
{
	Rigidbody2D rigid;
    
    void Awake()
    {
    	rigid = GetComponent<Rigidbody2D>();
    }
}

Update() vs FixedUpdate()

Update() 함수는 매 프레임마다 호출되어, 주로 입력받은 키에 대해 즉각적인 반응이 필요할 때 사용하고

FixedUpdate() 함수는 Fixed Timestep에 설정된 값에 따라 일정한 간격으로 호출되어, 지속적인 키입력 또는 물리효과가 적용된 오브젝트를 조정할 때 사용한다.

캐릭터 이동

maxSpeed라는 public 변수를 선언하면 객체의 "Inspector"의 해당 변수를 선언한 "Script" 컴포넌트에서 변수에 값을 설정할 수 있다.

아래 코드는 나의 코딩스타일을 적용했기 때문에 영상과는 코드가 좀 다르다.

public class PlayerMove : MonoBehaviour
{
	public float maxSpeed;
    Rigidbody2D rigid;
    
	void Awake()
    {
    	rigid = GetComponent<Rigidbody2D>();
    }
	void Update()
	{
    	// Stop Speed
        if (Input.GetButtonUp("Horizontal"))
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);
	}
    
    void FixedUpdate()
    {
    	// Move Speed
        float h = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
        
        // Max Speed
        if (rigid.velocity.x > maxSpeed)    // Right Max Speed
            rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y);
        else if (rigid.velocity.x < maxSpeed * (-1))    // Left Max Speed
            rigid.velocity = new Vector2(maxSpeed * (-1), rigid.velocity.y);
    }
}

이미지 좌우반전

캐릭터가 문워크하는 것을 해결하기위해 이미지 좌우반전을 사용하는데 영상에서 나온 방법을 사용해도 간헐적으로 문워크를 한다. 예를들어 왼쪽키를 눌렀다가 떼기전에 오른쪽키를 누르고나서 왼쪽키를 떼면 캐릭터가 뒤로 걷고있다.

그래서 영상의 코드를 조금 바꿨다.

public class PlayerMove : MonoBehaviour
{
	void Update()
	{
		// 좌우반전 설정
		spriteRenderer.flipX = rigid.velocity.normalized.x < 0;
	}
}

애니메이션 변경

캐릭터가 멈춰있을 때와 움직일 때의 애니메이션을 바꿔주기위해 "Animator" 탭에서 바꿔줄 State와 기존 State를 "Make Transition"을 이용해 화살표로 이어주고 State를 제어하기 위해 "Parameters"에 제어변수를 추가해주고 아까 연결한 화살표를 클릭하면 "Inspector"에 "Conditions"에서 제어변수와 값을 지정해준다. 마찬가지로 반대로도 화살표를 연결해서 아까와 반대로 설정해준다.

그리고 아래 코드를 작성. 마찬가지로 내 코딩스타일을 적용했다.

public class PlayerMove : MonoBehaviour
{
	void Update()
	{
		// Animation
        animator.SetBool("isWalking", Mathf.Abs(rigid.velocity.x) >= 0.3);
	}
}

추가적인 설정

마찰력, 공기저항

마찰력과 공기저항을 적절히 부여해주어야 사용자가 캐릭터를 원하는 대로 조종할 수 있다.
마찰력은 "Box Collider 2D" 컴포넌트에 "Material"을 설정해서 부여할 수 있는데 "Physics Material 2D"를 생성해서 적용하면 된다.

공기저항은 객체의 "Inspector"에서 "Rigidbody 2D" 컴포넌트에 "Linear Drag" 속성 값을 변경해서 부여할 수 있다.

굴러다님

캐릭터를 이동하다보면 지형에 걸려서 넘어지고 굴러다니는 현상이 발생하는데 캐릭터의 "Inspector"에서 "Rigidbody 2D" 컴포넌트에 "Constraints" > "Freeze Rotation Z"에 체크해주면 넘어지지 않는다.

이동중에 멈춤

캐릭터를 이동하다보면 지형에 걸려서 멈추는 현상이 발생한다. 자세히 보니까 캐릭터가 다음 블록과 충돌했을 때 앞으로 더 이상 이동하지 못해서 뒤로 좀 뺐다가 다시 가야하는 현상이었는데 왜 충돌하는지도 모르겠고 방법을 아무리 찾아봐도 완벽하게 해결할 수 없었다.

그나마 멈춤 현상을 막은 방법은 캐릭터의 충돌효과를 담당하고 있는 "Inspector"에 "Box Collider 2D" 컴포넌트에 "Edge Radius"를 0.01로 설정하는 방법이었다. 다만 이 방법에는 문제가 한 가지 있는데 캐릭터와 지형이 충돌하는 순간에 캐릭터가 통통 튀는 현상이 생겼다.
다른 버그현상이 생겼으나 움직임자체에 큰 문제는 사라졌기 때문에 일단 넘긴다.

출처: 골드메탈 유트브

profile
Nest.js, Delphi 개발자

0개의 댓글