유튜브를 쫓아가면서 나름의 해석과 chat gpt를 이용하여 내용을 이해한다.
유튜브는 보여주기만 할 뿐 설명은 없기 때문에 잘 모르는 부분은 찾아서 공부하고 설명을 추가한다.
작성자는 Macbook Pro M1 14(cto 32GB RAM)를 사용하지만 윈도와 차이가 없다(아마도)
작성자가 클론 게임 제작에 사용한 유니티 버전은 2022.3.47 f1(애플 실리콘)이다.
유튜브 영상 주소(클릭 시 재생목록으로 연결)
Assets + Scripts 주소(https://drive.google.com/file/d/1oFL88jUc7nv1NX6SovTO4HMd2mFTLVZj/view)
캐릭터와 배경 나무에 물리 컴포넌트를 추가한다.
만들어진 객체를 프리펩으로 만든다.
캡슐콜라이더 2D의 지오메트리 조정을 배운다.

 

Intro: 00:00
Player Physics: 00:25

3. 캐릭터와 나무에 물리속성 추가하기

프로젝트창에 에셋 - 세팅 폴더의 파일 3개 설정을 확인한다(이미지 참고)

두 번째 파일

Renderer 2D파일의 인스펙터에서 Custom Axis로 설정 변경한다.

스프라이트 폴더에 Objects and buildings, Rocks, Vegetation 스프라이트 에셋을 추가한다.

Vegetation 폴더에서 Bush와 spr_tree1 스프라이트를 선택, 인스펙터 창에서 설정을 변경한다.

스프라이트 모드 Single, 유닛 당 픽셀 크기 16, 필터 모드 Point, Compression -  None이다.

Bush를 계층창에 드래그로 추가하고 위치 x, y를 -2,-2로 변경한다.

나머지 나무 스프라이트를 선택, 인스펙터 창에서 스프라이트 에디터 실행

앵커 포인트를 조정한다.

나무를 하나 드래그해서 Scene으로 가져오면 계층창에 자동으로 추가된다. Tree로 이름을 변경한다.

적당한 위치로 이동해 본다.

계층창에 Bush 선택, 캡슐 콜라이더 2D 컴포넌트를 추가한다.

계층창에 Tree 선택, 캡슐 콜라이더 2D 컴포넌트를 추가한다.

다이렉션을 Horizontal로 변경한다.

Edit Collider 버튼을 이용하여 지오메트리를 크기를 변경한다. 나무의 밑동 크기로 원을 조정한다.

계층창에 Player 선택, 캡슐 콜라이더 2D 컴포넌트를 추가한다.

다이렉션을 Horizontal로 변경한다.

Edit Collider 버튼을 이용하여 지오메트리를 크기를 변경한다. 플레이어 크기에 맞게 변경한다.

이제 게임을 실행해 보면 캐릭터와 나무, 수풀에 물리값이 적용되어 캐릭터 이동에 장애물이 된다.

캐릭터의 중심이 맞지 않다면 스프라이트의 스프라이트 에디터를 실행한다. Custom Pivot 값을 조절하여 스프라이트의 중심축을 변경한다(슬라이스 된 모든 스프라이트를 수작업으로 조정해야 한다)

변경된 내용에 맞춰 캡슐 콜라이더의 지오메트리도 맞춰서 변경한다.

계층창에서 Tree 선택

스프라이트 Sort 포인트를 Pivot 으로 변경한다. Pivot으로 객체의 특정부분을 기준으로 정렬이 가능해진다.

(center는 스프라이트의 중앙을 기준으로 정렬되기 때문에, 객체의 크기나 형태에 따라 정령이 예상과 다르게 보일수 있다)

에셋 - Prefabs 폴더를 생성한다.

계층창에서 Tree를 드래그로 프리펩 폴더로 가져와 프리펩으로 만든다.

계층창에서 Tree를 두 개(Tree1, Tree2) 더 복사하고 이미지처럼 Unpack 한다.

Tree1, Tree2의 인스펙터 창에서 모두 각각 다른 나무 스프라이트를 적용한다.

Tree1, Tree2에 적용한 나무 스프라이트의 설정을 다음과 같이 한다.

(스프라이트 모드 Single, 유닛 당 픽셀 크기 16, 필터 모드 Point, Compression -  None)

각각의 나무 모양에 맞게 캡슐 콜라이더의 지오메트리도 맞춰서 변경한다.

Tree1, Tree2 프리펩으로 만든다.

배경색을 녹색으로 변경하고 몇 개의 오브젝트를 복사해서 위치를 변경시켰다. 나무의 캡슐콜라이더 크기에 만큼 플레이어 이동에 장애물로 작동하는 것을 볼 수 있다.

여기까지 작성한 패키지 파일

Make an 2D Top Down RPG in Unity (Part3_Player Physics).unitypackage
0.12MB

 



유튜브를 쫓아가면서 나름의 해석과 chat gpt를 이용하여 내용을 이해한다.
유튜브는 보여주기만 할 뿐 설명은 없기 때문에 잘 모르는 부분은 찾아서 공부하고 설명을 추가한다.
작성자는 Macbook Pro M1 14(cto 32GB RAM)를 사용하지만 윈도와 차이가 없다(아마도)
작성자가 클론 게임 제작에 사용한 유니티 버전은 2022.3.47 f1(애플 실리콘)이다.
유튜브 영상 주소(클릭 시 재생목록으로 연결)
Assets + Scripts 주소(https://drive.google.com/file/d/1oFL88jUc7nv1NX6SovTO4HMd2mFTLVZj/view)
유니티 프로젝트 준비, 레이아웃 정리
플레이어 입력 시스템 구성(상하좌우 키보드 입력, 마우스로 좌우 방향 구분)
플레이어 스프리트 적용
플레이어 애니메이션 만들기

 

Intro: 00:00
Project Setup: 03:00
Player Input System: 05:00

Intro: 00:00
Player Sprites: 00:25
Animating The Player: 03:00

1. 프로젝트 생성과 개발 준비

최신 버전 기준으로 Universal 2D 선택 후 생성한다.

UniversalRenderPipelineGlobalSettings 파일을 세팅 폴더 옮겨서 에셋 폴더를 정리한다.

게임 뷰. 화면 비율을 16:9로 변경한다.

레이아웃을 취향에 맞게 변경한 후 레이아웃 저장한다.

저장된 레이아웃은 언제든지 변경할 수 있다.

프로젝트를 저장한다.

2. 플레이어 상하좌우 이동 작성

Scripts, Sprites 폴더 생성한다. 

Scripts 폴더에서 - Player Controller(C# Script) 파일을 생성한다.

계층창에 2D 오브젝트 - 스프라이트 - 스퀘어를 추가한다.

스퀘어 오브젝트의 이름을 Player로 변경하고 컴포넌트를 추가한다.

Rigidbody 2D를 추가한다(이미지를 참고하여 다음 설정을 한다)

Gravity Scale 0 변경, Collision Detection - Continuous 설정, Constrains - Z에 체크한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
  [SerializeField] private float moveSpeed = 1f;
}

Player 스크립트 파일을 수정하고 저장한다.

콘솔 창에는 입력한 변수가 한번도 사용되지 않았다는 경고가 나온다.

패키지 매니져 윈도를 연다.

유니티 레지스트리로 변경한다.

input system 을 검색하여 설치한다. 설치가 완료되면 이 프로젝트에 적용을 위해 재시작한다.

input action을 스크립트 폴더에서 만들고 Player Controls로 이름 변경한다.

 

Player Controls 파일 선택 - 인스펙터 창에서 Generate C# Class 체크 - Apply

C# 파일이 생성된다.

Player Controls 파일 더블 클릭으로 열기(새로운 창이 뜬다)

이미지와 같이 Move 설정을 추가한다.

무브의 상하좌우 액션을 추가한다.

상하좌우에 wasd 키를 매칭시킨다.

Save Asset 으로 저장 후 창을 닫는다.

계층창에 Player 객체에 PlayerController 스크립트를 적용시킨다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Scripting.APIUpdating;

public class PlayerController : MonoBehaviour
{
  [SerializeField] private float moveSpeed = 1f;

  private PlayerControls playerControls;
  private Vector2 movement;
  private Rigidbody2D rb;

  private void Awake()
  {
      playerControls = new PlayerControls();
      rb = GetComponent<Rigidbody2D>();
  }

  private void OnEnable()
  {
      playerControls.Enable();
  }

  private void Update()
  {
      PlayerInput();
  }

  private void FixedUpdate()
  {
      Move();
  }

  private void PlayerInput()
  {
      movement = playerControls.Movement.Move.ReadValue<Vector2>();

  }

  private void Move()
  {
      rb.MovePosition(rb.position + movement * (moveSpeed * Time.deltaTime));
  }
}

PlayerController 스크립트 작성한다.

update 메서드에서 사용자 입력을 movement 변수에 저장한다.

FixedUpdate 메서드에서 고정된 물리 업데이트마다 Move 메서드를 실행하여 캐릭터를 이동시킨다.

객체 플레이어의 무브 스피드를 4로 변경하고 플레이해본다. 

wasd로 상자 움직여 본다.

3. 플레이어 스프라이트 추가하기

스프라이트 폴더에 플레이어 스프라이트 파일들을 드래그로 추가한다.

추가한 스프라이트에 사이드 애니메이션 폴더로 이동.

4개의 파일을 선택 - 인스펙터창에서 텍스쳐 타입을 Sprite(2D and UI)로 변경한다.

그 외 Sprite mode, Pixels Per Unit, Filter Mode를 이미지를 참고하여 변경하고 Apply 버튼으로 적용한다.

3번째 파일을 선택.

스프라이트 에디터를 열고, Grid By Cell Size 로 slice 한다.

스프라이트 세번째 파일을 펼친다.

계층창의 플레이어 객체를 선택한다.

스프라이트의 첫번째 애니메이션을 드래그하여 플레이어 객체의 인스펙터창에 Sprite Renderer-Sprite로 가져간다.

게임 뷰의 사각형이 캐릭터로 변경된다.

플레이 해보면 캐릭터가 움직인다. 애니메이션을 추가하지 않았기 때문에 모션은 없다.

4. 캐릭터 애니메이션 추가와 마우스로 캐릭터 방향 전환하기

Animations 폴더 생성 - Player 하위 폴더를 생성 - 애니메이션 컨트롤러를 만들고 Player로 이름 변경한다.

애니메이션을 생성하고 이름은 Idle로 변경한다.

애니메이션을 생성하고 이름은 Running로 변경한다.

애니메이션 창을 열고 편한 위치로 이동시킨다.

계층창의 플레이어 객체를 선택, Animator 컴포넌트를 추가한다. 애니메이션 컴포넌트와 혼동될 수 있다.

애니메이터 컨트롤러에 Player 애니메이션 컨트롤러 파일을 드래그로 추가한다.

idle, Running 애니메이션에 Loop Time을 체크한다. 게임 중에 반복 재생하기 위함이다.

플레이어 객체의 애니메이션 창을 연다.

Idle, Running 애니메이션 파일을 끌어서 추가한다.

왼쪽에 파라미터에서 Float 로 moveX, moveY를 추가한다.

애니메이션 창에서

Make Transition으로 Idle -> Running으로 연결한다. 4회 반복한다.

인스펙터 창에서 Transitions의 4개를 각각 클릭하여

Has Exit time 체크해제(앞에 애니메이션이 끝나는 것을 기다리지 않고 바로 이 애니메이션이 적용된다)

Transition Duration을 0 으로 변경한다. 2D 애니메이션이기 때문에 프레임 전환이 즉각 이뤄져도 상관없다.

애니메이션 창에서 Idle을 선택.

계층창에 플레이어 객체를 선택한 상태이다.

프로젝트의 스프라이트 폴더에 플레이어 Idle 에 해당하는 스프라이트를 모두 선택한다.

드래그로 애니메이션 창으로 가져온다.

프레임을 드래그로 전체 선택한 후 드래그하여 프레임 간격을 띄워서 30초쯤으로 변경한다.

플레이 버튼으로 프리뷰하면 캐릭터가 움직인다.

똑같은 방법으로 Running 애니메이션에도 스프라이트를 추가하여 만든다.



public class PlayerController : MonoBehaviour
{
  private Animator myAnimator;
  private SpriteRenderer mySpritRender;

  private void Awake()
  {
      myAnimator = GetComponent<Animator>();
      mySpritRender = GetComponent<SpriteRenderer>();
  }

  private void FixedUpdate()
  {
      AdjustPlayerFacingDirection();
  }

  private void PlayerInput()
  {
      myAnimator.SetFloat("moveX", movement.x);
      myAnimator.SetFloat("moveY", movement.y);

  }

  private void AdjustPlayerFacingDirection()
  {
      Vector3 mousePos = Input.mousePosition;
      Vector3 playerScreenPoint = Camera.main.WorldToScreenPoint(transform.position);

      if (mousePos.x < playerScreenPoint.x)
      {
          mySpritRender.flipX = true;
      }
      else
      {
          mySpritRender.flipX = false;
      }
  }
}

플레이어 컨트롤러 스크립트 파일에 코드를 추가한다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using UnityEngine.Scripting.APIUpdating;

public class PlayerController : MonoBehaviour
{
  [SerializeField] private float moveSpeed = 1f;

  private PlayerControls playerControls;
  private Vector2 movement;
  private Rigidbody2D rb;

  private Animator myAnimator;
  private SpriteRenderer mySpritRender;

  private void Awake()
  {
      playerControls = new PlayerControls();
      rb = GetComponent<Rigidbody2D>();

      myAnimator = GetComponent<Animator>();
      mySpritRender = GetComponent<SpriteRenderer>();

  }

  private void OnEnable()
  {
      playerControls.Enable();
  }

  private void Update()
  {
      PlayerInput();
  }

  private void FixedUpdate()
  {
      AdjustPlayerFacingDirection();
      Move();
  }

  private void PlayerInput()
  {
      movement = playerControls.Movement.Move.ReadValue<Vector2>();
      myAnimator.SetFloat("moveX", movement.x);
      myAnimator.SetFloat("moveY", movement.y);

  }

  private void Move()
  {
      rb.MovePosition(rb.position + movement * (moveSpeed * Time.deltaTime));
  }

  private void AdjustPlayerFacingDirection()
  {
      Vector3 mousePos = Input.mousePosition;
      Vector3 playerScreenPoint = Camera.main.WorldToScreenPoint(transform.position);

      if (mousePos.x < playerScreenPoint.x)
      {
          mySpritRender.flipX = true;
      }
      else
      {
          mySpritRender.flipX = false;
      }
  }
}

플레이어 컨트롤러 스크립트 파일 전체 코드이다.

애니메이터 창에서 Idle 선택.

인스펙터 창에 4개 트랜지션을 각각 선택하고 Conditions 설정을 변경한다.

moveX, Greater, 0.1

moveX, Less, -0.1

moveY, Greater, 0.1

moveY, Less, -0.1

애니메이션 창에서 Running->Idle 로 트랜지션을 하나 만든다.

인스펙터 창에 Conditions 를 4개 추가한다.

moveX, Less, 0.1

moveX, Greater, -0.1

moveY, Less, 0.1

moveY, Greater,- 0.1

반대로 설정한다.

추가로 Has Exit time 체크해제, Transition Duration을 0으로 변경한다.

여기까지 작성한 내용을 실행해본다.

wasd 입력에 따라 캐릭터가 움직여야 한다.

애니메이션이 키 입력에 따라 idle과 running 전환이 이뤄져야 한다.

마우스 위치에 따라 캐릭터가 방향이 좌우로 달라진다(상하전환은 아직 미구현이다) 

2D Top Down RPG_save_point_1(여기까지 작성한 패키지 파일)

2D Top Down RPG_save_point_1.unitypackage
0.07MB

+ Recent posts