9/30 TIL 2D Platfomer게임 제작(1)

Cheorii·2024년 9월 30일
post-thumbnail

Platfomer Game의 예로 들자면 "슈퍼마리오" 가 가장 유명하다고 할 수 있다.

타일맵의 종류는 Rectangle, Hexagon, Isometric 세가지가 있다.
오늘 제작할 게임은 Rectangle로 제작할 예정이다.

시작.

Pixel Per Unit

Pixel Per Unit을 사용하는 목적을 간단하게 설명하자면, 게임 내에서 픽셀 기반의 에셋이 정확한 비율로 표시되도록 하기 위해서 사용.

Tilmap Collider2D , Composite Collider2D

Tilmap Collider2D

타일맵의 각 타일마다 개별 콜라이더를 생성한다.

그래서 기본적으로 많은 타일이 있으면 그만큼 많은 콜라이더가 생겨나고, 복잡한 콜리전 경계가 만들어진다.

그래서 Composite Collder2D를 사용하고 아래의 사진과 같이 설정 했다.

Composite Collider2D

타일맵의 개별 콜라이더들을 합쳐 하나의 큰 콜라이더로 만들어줍니다. 이 과정에서 콜라이더의 형태가 단순화되거나 타일맵에 맞게 병합 된다.

그래서 콜라이더를 하나로 사용하기 위해서,
Tilemap Collider2D 설정의 Composite Operation를 merge로 변경한다.

GetAxisRaw(), GetAxis()

GetAxisRaw

  • GetAxisRaw는 눌리자마자 -1 ~ 1까지 값이 바뀌는 과정에서 즉시 변경, 버튼을 떼면 즉시 0으로 변경됨

GetAxis

  • GetAxis는 누르고 있을 때 -1 ~ 1까지 값이 바뀌는 과정이 있기에 즉시 변경이 안되고, 약간의 가속도가 생기며 변경되고, 떼고 있을 때도 동일하게 변경됨.


(위에서 부터 왼쪽으로 움직였을 때, 오른쪽으로 움직였을 때)

버그?


벽에 붙어서 점프 누르고 있으면 하면 벽에 걸침

방법 1)

이렇게 하니 해결

방법 2)

Physical Material2D를 사용해서 마찰계수를 아얘 0으로 설정

Cinemachine Camera

Cinmeachine Camera를 사용 하기 위한 제작 과정

  • 빈 오브젝트(create empty)를 생성
  • Polygon Collider2D를 생성
  • 오각형 폴리건의 꼭짓점 하나를 제거 해서 사각형 폴리건으로 제작 (Ctrl키를 누르고 한 변을 선택하면 제거 가능)
  • Cinemachine Camera 오브젝트에 Target을 플레이어로 설정
  • Bounding Shpae 2D 에 생성한 오브젝트 설정

Animation


에셋을 통해 애니메이션을 제작해서 Animator에서 제작

AnyState

  • AnyState는 어느 상태에서든지 특정 애니메이션으로 바로 전환 해주는 특수한 상태이다.
  • 조건이 맞다면 언제든지 실행될 수 있다.

Entry

  • 첫 시작 지점을 나타냄
  • 애니메이션이 시작될 때 어느 상태로 진입할지 결정

AnyState / Entry 차이점

  • Any State는 현재 상태와 관계없이 특정 조건이 만족되면 언제든지 특정 애니메이션으로 전환할 수 있습니다.
  • Entry는 애니메이터가 시작될 때 처음으로 어느 상태로 진입할지를 결정하는 용도로 사용됩니다.

애니메이션의 transition Duration, Transition Offset, Can Transition To Self,condition을 위와 같이 수정.

Transition Duration : 현재 상태의 지속 시간을 기준으로 한 상대적인 전환 지속 시간
Transition Offset: 전환될 도착 상태에서의 플레이를 시작할 시간의 오프셋
Can Transition To Self : 자기 자신의 State로도 전이가 가능한지를 체크하는 옵션

Player.cs

오늘 사용한 부분의 코드 주석 추가

using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float Speed = 10; // 캐릭터의 이동 속도
    public float JumpSpeed = 12; // 캐릭터의 점프 속도
    public Collider2D BottomCollider; // 캐릭터 발 부분의 콜라이더, 바닥과의 충돌을 감지
    public CompositeCollider2D TerrainCollider; // 타일맵이나 지형을 나타내는 콜라이더

    // 멤버 변수
    float vx = 0; // 가로 방향 이동 속도
    bool grounded; // 캐릭터가 바닥에 붙어 있는지 여부를 저장하는 변수
    float preVx = 0; // 이전 프레임에서의 가로 속도

    void Start()
    {
        
    }

    void Update()
    {
        // 좌,우 화살표 키 또는 A, D 키
        vx = Input.GetAxisRaw("Horizontal") * Speed;

        // Rigidbody2D의 현재 y축 속도를 가져옴 (중력에 의한 하강 포함)
        float vy = GetComponent<Rigidbody2D>().velocity.y;

        // 캐릭터가 왼쪽으로 이동할 때, 스프라이트를 좌우 반전하여 왼쪽을 바라보도록 함
        if(vx < 0)
        {
            GetComponent<SpriteRenderer>().flipX = true;
        }

        // 캐릭터가 오른쪽으로 이동할 때, 스프라이트를 원래 상태로 돌려 오른쪽을 바라보도록 함
        if(vx > 0)
        {
            GetComponent<SpriteRenderer>().flipX = false;
        }

        // 캐릭터의 애니메이션 상태 업데이트 (땅에 붙어 있는지에 따라 애니메이션 전환)
        if(BottomCollider.IsTouching(TerrainCollider)) // 바닥과 접촉하고 있는지 확인
        {   
            if (!grounded) // 이전 프레임에서 땅에 붙어있지 않았다면
            {
                if(vx == 0) // 이동 속도가 0일 경우 (가만히 있을 때)
                {
                    GetComponent<Animator>().SetTrigger("Idle"); // Idle 애니메이션 트리거
                }
                else // 이동 속도가 0이 아닐 경우 (이동 중일 때)
                {
                    GetComponent<Animator>().SetTrigger("Run"); // Run 애니메이션 트리거
                }
            }
            else // 이전 프레임에서도 땅에 붙어있었다면
            {
                if(vx != preVx) // 현재 속도가 이전 속도와 다를 경우 (속도 변화가 있을 때)
                {
                    if (vx == 0) // 이동 속도가 0일 경우 (정지 상태)
                    {
                        GetComponent<Animator>().SetTrigger("Idle"); // Idle 애니메이션 트리거
                    }
                    else // 이동 중일 경우
                    {
                        GetComponent<Animator>().SetTrigger("Run"); // Run 
                    }
                }
            }
        }
        else // 캐릭터가 땅에 붙어있지 않은 경우 (점프 중이거나 공중에 있을 때)
        {   
            if(grounded) // 이전 프레임에서 땅에 붙어있었지만, 현재는 붙어있지 않은 경우
            {
                GetComponent<Animator>().SetTrigger("Jump"); 
            }
        }

        // 바닥 접촉 여부를 현재 프레임 기준으로 업데이트
        grounded = BottomCollider.IsTouching(TerrainCollider);

        // 점프 입력 처리 (바닥에 붙어 있을 때만 점프 가능)
        if (Input.GetButtonDown("Jump") && grounded)
        {
            vy = JumpSpeed; // 점프 시 Y축 속도를 점프 속도로 설정
        }

        // 현재 프레임의 속도를 이전 속도로 저장
        preVx = vx;

        // Rigidbody2D의 가로, 세로 속도를 업데이트 (vx: 가로 이동 속도, vy: 세로 속도)
        GetComponent<Rigidbody2D>().velocity = new Vector2(vx, vy);
    }
}
profile
코딩테스트는 진짜 못하겠어요 ㅠㅠ

0개의 댓글