Notice
Recent Posts
Recent Comments
05-18 01:37
«   2024/05   »
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 31
Archives
Today
Total
관리 메뉴

Byeol Lo

Unity - Essential of real-time 2D 본문

Unity

Unity - Essential of real-time 2D

알 수 없는 사용자 2023. 6. 22. 15:49

 2D 프로젝트를 하는데 있어 골드 메탈님의 https://www.youtube.com/playlist?list=PLO-mt5Iu5TeZGR_y6mHmTWyo0RyGgO0N_ 영상을 참고하여 어셋을 받은 후에 만들었다.

 

유니티 기초 2D 플랫포머 [BE2]

유니티의 물리엔진을 활용한 2D 플랫포머 기초 강좌 채널. 에셋 : http://u3d.as/2mvJ

www.youtube.com

 2D 프로젝트의 Unity강의는 부족한 감이 있기 때문에 실제 프로젝트를 만들어서 공부를 했다.

 

 3D 프로젝트와는 다르게 2D 오브젝트를 따로 계층창에서 볼 수 있다. 스프라이트는 납작하게 생긴 모양이며 Sprite Renderer라는 컴포넌트를 기본적으로 가지고 있다.

 

 스프라이트 렌더러는 영어 뜻 그대로 스프라이트를 보여주는 컴포넌트이다. Sprite 프로퍼티에서 모양에 대해 지정을 할 수 있다. 해당 InputFieldBackground를 선택하고 Color는 아무거나 선택한 후에 게임창으로 들어가 살펴보자.

 

 위에 보이는 것처럼 스프라이트를 볼 수 있다. 여기서 원근법으로 해당 스프라이트를 가까이 있거나 멀리 있도록 표현하고 싶을 수 있다. 이럴 때 오브젝트의 z축 위치를 바꾸면 되는데, 씬의 위쪽에 2D라고 체크되어 있는 부분을 클릭하여 씬 뷰를 3D로 볼 수 있도록 바꾸자.

 

 그런 후에 해당 스프라이트 의 z축에 해당하는 파란 축을 통해 z값을 바꿔보면, 카메라에 보이는 부분은 아무런 반응이 없을 수 있는데, 그것은 카메라가 비추고 있는 투영(Projection) 방법이 다르기 때문이다. 여기서 원근법이 없는 투영 방법은 Orthographic이고, 원근법이 있는 투영 방법이 Perspective이다. 따라서 Main Camera로 가서 Camera 컴포넌트의 Projection 프로퍼티를 Perspective로 바꾸자.

 

 Background는 뒤에 보이는 배경이며, Size는 카메라의 크기인데 이는 투영방법이 Orthographic일 때만 활성화가 된다. 이제 Projection을 Perspective로 바꾸면 3D Project 처럼 카메라의 시야 범위가 나오게 된다. 여기서는 Orthographic으로 작업을 하기 때문에 다시 Orthographic으로 바꿔준다. 여기서 Object들이 서로 같은 z값에 있을 때는 누가 우선 순위로 rendering이 되는지 의문이 들 수 있다. 스프라이트 Object에서 Sprite Render를 잘 살펴보자.

 

 Additional Settings에서 Order in Layer라는 값이 있다. 여기에 정수 값을 입력하여 순서를 정해줄 수 있거나, 아니면 그냥 z값을 설정해도 된다. 어쨋든 여기서 Sorting Layer도 보일텐데, 이는 Layer들을 만들어서 각각의 Layer들이 순서들만 나열 해주면 그에 맞는 렌더링을 할 수 있다.

 

 +를 통해 레이어 추가가 가능하며 -를 통해 삭제를 할 수 있다.

 

물리법칙

 3d project에서는 rigid component를 통해 중력을 넣고, Collision관련 컴포넌트를 넣어 충돌 범위를 관리했다. 2D도 똑같지만 컴포넌트의 이름에 2D가 붙을 뿐이다.

  • Rigidbody 2D: 중력 법칙
  • Box Collider 2D: 박스 형태의 충돌 범위 지정
  • Capsule Collider 2D: 캡슐 형태의 충돌 범위 지정
  • Circle Collider 2D: 원 형태의 충돌범위 지정
  • Composite Collider 2D: 여러 개의 충돌 범위를 합쳐서 하나의 충돌범위를 지정
  • Custom Collider 2D: 사용자가 직접 구현한 사용자 정의 충돌 처리를 위한 컴포넌트
  • Edge Collider 2D: 선 형태의 충돌범위 지정

위의 컴포넌트를 추가하여 물리법칙들을 구현할 수 있다.

 충돌을 구현할 때, 자세히 보면 오브젝트간의 거리가 살짝 있을 수 있는데, 이는 Edit > Project Setting > Physics 2D > Default Contact Offset을 0으로 만들면 된다.

 

도트 이미지 조정

 게임에 있어서 그래픽은 굉장히 중요한 요소이다. 각각의 이미지 파일들은 캐릭터들의 애니메이션도 될 수도 있고, 유저의 흥미를 돋을 수 있다. 어셋에서 Sprites에 Player.png를 들어가보자.

 Inspector창에 다음과 같이 보이는데, 여기서 Filter Mode를 먼저 볼 것이다. Filter Mode는 텍스처의 픽셀을 화면에 그릴 때 어떤 필터링 방법을 사용할지 정하는 프로퍼티이다. Pointer는 텍스처 필터링을 비활성화하는 옵션인데, 일반적으로 텍스처 필터링은 텍스처가 확대 또는 축소되거나 회전되었을 때 픽셀 간의 보간을 통해 부드럽고 고화질의 그림을 보여준다. 그러나, 텍스처를 정교한 픽셀 단위로 제어해야 하는 경우에는 텍스처 필터링을 비활성화하는 것이 유용하다.

 또한 Unit하나(1m * 1m 단위)에서 픽셀이 들어갈 수 있는 값을 정할 수도 있는데, 이 또한 Pixels Per Unit 프로퍼티를 설정하면 된다.

 

 하나의 플레이어가 동작을 하는데 있어 동작 하나하나에 다양한 그림들이 들어가는데, 전부 한 파일에 모여있다. 여기서 동작에 맞는 그림을 꺼내야하는데, 우선 그림 파일을 살펴볼 필요가 있다. Player에서 inspector 창에 sprite editor을 클릭해주자.

 위는 편집기를 연 상태인데, 여기선 각각의 모션이 16 픽셀로 되어 있기 때문에 간단하지만, 더 나아가 고화질의 그래픽을 열 때는 1024 * 1024 를 넘어가버리기 때문에 그때는 그래픽 디자이너가 아닌 이상 어디에 픽셀이 들어가 있는지 확인하기가 힘들다. 따라서 Automatic mode를 켜주어 어디에 픽셀이 들어가 있는지 확인할 수 있는데,  우측 상단에 rgb버튼을 클릭하자.

 

 이렇게 픽셀이 어디에 각각 들어가 있는지 한눈에 볼 수 있다. 이제 각각의 모션들을 잘라서 활용할 건데, 하나의 그림파일로 있으면 따로 활용할 수가 없다. 여기서 사용할 것은 좌측 상단의 Slice를 통해 그림을 격자에 맞게 자를 수 있다.

 

 위처럼 빨간색 격차로 표시된 것을 보면서 잘라주면된다. 이렇게 각각을 나누면 Project 창에 나눈 것 만큼 모션이 보이게 된다. 다른 그림 뭉치들도 똑같이 모션에 따라 나눠주자.

 

애니매이션

 나눈 모션들을 가지고 동작에 맞는 그림들을 넣어주면 애니매이션처럼 동작하게 된다. 애니메이션 또한 Unity Engine에서 지원해주는데, 만드는 방법은 해당 연속된 동작들을 Project 창에서 다중 클릭하여 Hierarchy 창에 드래그하여 넣어주면 된다(넣고 싶은 Object에 드래그해서 넣어줘도 된다).

 넣고 싶은 Object에 넣어주면 Inspector 창에 Animator라는 컴포넌트가 생기는데 이는 애니메이션을 관리하는 컴포넌트이다. 이제 실행시키면 다중 클릭했던 모션들이 연달아 보여지게 된다. 위의 애니메이션을 프레임마다 보려면 다음과 같이 애니메이션 창을 띄워주면 된다.

 

 Window > Animation > Animation 을 통해 창이 하나 나오는데, 해당 창의 탭을 Project 창에 넣어준다. 그리고 프레임마다 애니메이션 값을 클릭하여 프레임 시간에 따라 볼 수 있다.

 

플레이어 이동

 C# script를 통해서 이제 움직이는 것을 재현해보자.

using UnityEngine;

public class PlayerMove : MonoBehaviour {
    private float maxSpeed = 2f;
    
    
    private void Awake() { // 스크립트가 활성화될 때 호출함
        rigid = GetComponent<Rigidbody2D>(); // rigid2d 컴포넌트를 가져온다.
    }
    
    private void FixedUpdate() { // 물리 엔진의 업데이트 주기에 맞춰 호출되어 프레임이 아닌 시간 간격기준
        float h = Input.GetAxisRaw("Horizontal"); // 키보드 입력 축의 수평 움직임 값을 반환함.
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse); // ForceMode2D.Impulse는 단발성 힘의 형태
    }
}

 이렇게 하면 오브젝트에 right쪽으로 힘을 가할 수 있는데, 그 형태는 단발성 힘(충격, 짧은 시간에 작용하는 힘)의 형태이다. Vector2.right * h는 힘의 크기와 방향h을 나타내게 된다. 이를 오브젝트에 넣어 이제 키보드의 좌우를 움직여 본다면, 너무 빨라서 주체하기 힘들다. 그 이유는 누르는 동안에 충격을 계속 가하면 계속해서 빨라지기 때문이다. 따라서 최대 속도를 조절해줘야 한다.

using UnityEngine;

public class PlayerMove : MonoBehaviour {
    private float maxSpeed = 2f;
    
    
    private void Awake() { // 스크립트가 활성화될 때 호출함
        rigid = GetComponent<Rigidbody2D>(); // rigid2d 컴포넌트를 가져온다.
    }
    
    private void FixedUpdate() { // 물리 엔진의 업데이트 주기에 맞춰 호출되어 프레임이 아닌 시간 간격기준
        float h = Input.GetAxisRaw("Horizontal"); // 키보드 입력 축의 수평 움직임 값을 반환함.
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse); // ForceMode2D.Impulse는 단발성 힘의 형태
        
        if(rigid.velocity.x > maxSpeed) { // 만약 속도가 maxSpeed를 넘긴다면
            rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y);
        else if(rigid.velocity.x < -maxSpeed) { // 왼쪽으로의 속도가 -maxSpeed를 넘긴다면
            rigid.velocity = new Vector2(-maxSpeed, rigid.velocity.y);
    }
}

 마지막으로 이동에 있어서 공기, 바람, 재질의 미끄러운 정도 등이 있을 수 있다. 따라서 우선 미끄러운 정도를 표현해주기 위해 Material이라는 컴포넌트를 만들어준다.

 

마찰 계수

 여기서 바닥에 미끄러운 정도를 넣기 위한 Material을 만들어준다. 2D이기 때문에 2D에 있는 Physics Material을 만든다.

 Friction은 마찰계수를 뜻하는데 보통 0부터 양수의 값을 가지게 된다. 0에 가까운 값은 낮은 마찰을 나타내기 때문에 잘 미끄러지는 얼음을 상상하면 되고, 높은 값은 물체 간의 접촉이 강력하고 미끄러짐이 거의 없는 거친 표면을 뜻한다. 만든 Material을 땅에 넣어주자.

 

저항

 공기저항은 플레이어의 Rigidbody에 Linear Drag를 0~양수 값을 통해 넣을 수 있다. 클수록 저항이 강하고, 작을 수록 저항이 약해진다.

 직접 플레이를 해보면서 조정해가는 것이 좋다.

 

다양한 애니메이션 효과 넣기

 멈춰 있을 동안 동작되는 애니메이션만 넣어서는 걷기 중일 때의 동작을 볼 수 없다. 따라서 애니메이션을 수정해야 한다. Animator창을 켜서 Walk라는 동작을 넣어주자.

 Walk는 Stop동작에서 발생되므로 여기서 애니메이션 상태를 옮겨가야 한다. 따라서 Stop모션에서 Transition을 만들어 다음 애니메이션으로 이동시켜준다. 이제 걷는 모션을 동작시켜주기 위해 애니메이터 매개변수를 추가시켜준다.

 

 isWalking이라는 Bool형 매개변수를 추가했다면 만들었던 Transition에서 Condition에 +를 눌러 isWalking이 true라면 옮겨가도록 해준다.

반대의 방향은 isWalking이 False일 때 옮겨가도록 해준다. 이제 변수설정이 끝났다면, Script로 돌아와 이동 중일때 True, 아닐때는 False로 동작하도록 만들어 준다. 여기서 Has Exit Time 프로퍼티를 통해 해당 애니메이션이 끝나는 동안까지 애니메이션을 동작하게 하거나(체크) 아니면 애니메이션 파라미터가 활성화 안되었을때 바로 끝내게 해주는(unchecked) 용도이다.

'Unity' 카테고리의 다른 글

Unity - Player Controller  (0) 2023.06.27
Unity - The real-time industry  (0) 2023.06.22
Unity - Essentials of real-time audio  (0) 2023.06.20
Unity - Essentials of programming in Unity  (0) 2023.06.20
Unity - Project: Essentials of real-time 3D  (0) 2023.06.19
Comments