왜.... 오셨나요?

부끄러워요

유니티개발 TIL

4주차 3일 TIL_유니티 입문(유사 2D메타버스 만들기_캐릭터 이동+추가편)

와피했는데 2025. 7. 24. 21:19

들어가기 앞서

이전 10일차 부터 시작한 나혼자메타버스 혼자버스를 개발 착수하기 시작했다 맵과 매니저등 기본적인 세팅이후 해야할것은 무엇인가 바로 캐릭터를 만들고 움직여 보는것이다 그래서 이번엔 케릭터 이동을 구현하고 카메라까지 따라다니는 기능을 구현하도록 한다


프로젝트 구현 단계


<InputSystem>

● 캐릭터의 이동 키맵핑은 유니티에서 제공하는 Inputsystem으로 맵핑해주었다

 

InputAction은 새로 커스텀하지 않고 기본제공하는 Action을 사용하였다

*InputSystem에 대한 설명은 구글링 해보시길 이곳은 유니티 강의블로그가 아닙니다 서칭도 능력이야!!!


<케릭터 이동 +추가>

● 이전글에서 이동구현중 부족한 내용을 추가적으로 기입해주겠다 

● 개발과정중 테스트를 위한 직렬화 변수로 구현

 

>직렬화변수<

    [Header("플레이어 이동속도")]
    [SerializeField] float speed;

    [Header("플레이어 이미지")]
    [SerializeField] SpriteRenderer spriteRenderer;
    [SerializeField] Sprite sRender;
    [SerializeField] Sprite bRender;
    [SerializeField] Sprite fRender;
    [SerializeField] float shadowMinSize;
    [SerializeField] float sizeSpeed;

 

 SerializeField로 한 이유
다른 클래스에서 공유할 변수가 아니지만 에디터상에서 변수 수정이 가능한 접근자로써 선택함
'변수의 접근성을 제한하면서 에디터에서 값을 설정할 수 있게 하여 캡슐화를 유지하면서 유연성을 확보합니다.'
라고 설명이 있는데 우리가 그걸 몸소느낄 방도는 직접 써봐야 알지 안을까요?

 

 

 이동로직에 .velocity을 사용한 이유
탑-다운 2d의 경우 이동할때 한번에 일정 속도를 유지하면서 움직이는게 답답함이 없고 오히려 자연스럽게 보인다 마치 3d 탑다운 게임의 유명사 디아블로 또한 그러하다 그래서 일정속도를 유지해주는 Rigidbody 함수인 .velocity 사용하게됨

디아블로4

 


<점프>

● Vector2.y축의 움직임만 변동시킨다

Rigidbody의 Gravity Scale이 '0'이므로 코드상 중력을 별도로 구현할 필요가 있음

 

>변수<

    [Header("플레이어 점프")]
    [SerializeField] float jumpPower;
    [SerializeField] float gravity;
    [SerializeField] int maxJumpCount;
    
    //====[Jump]====
    private int jumpCount = 0; // 점프 카운터

    private float curJumpP; // 점프 파워
    private float groundOffset = 0.0f;  // 바닥감지 기준수치

    private bool isMinSize = false;
    private bool isGround = true; // 점프 가능 상태

 

변수들의 수만 봐도 점프 라는 기능이 얼마나 머리아픈 기능인지를 알수있습니다

*점프는 해당글을 참고하여 구현함 https://nimble-riverside.tistory.com/40?category=1076884

 //=======================[Jump]=======================
 private void Update()
 {
     JumpHandling();
 }

 void OnJump()
 {
     Jump(jumpPower);
 }

 void Jump(float jumpPower)
 {
     if (jumpCount >= maxJumpCount) return;
          curJumpP = jumpPower;
          isGround = false;
          jumpCount++;
 }

 void JumpHandling()
 {
     if (isGround==true)
         return;

     body.transform.position += new Vector3 (0.0f, curJumpP * Time.deltaTime, 0.0f);
     curJumpP -= gravity * Time.deltaTime;

     if (shadow.transform.localScale.x > shadowMinSize&& isMinSize==false || shadow.transform.localScale.y > shadowMinSize&& isMinSize== false)
             shadow.transform.localScale -= new Vector3(shadowMinSize * Time.deltaTime, shadowMinSize * Time.deltaTime, 0.0f);
     else
     {
         isMinSize = true;
         shadow.transform.localScale += new Vector3(sizeSpeed * Time.deltaTime, sizeSpeed * Time.deltaTime, 0.0f);
     }

     if (body.transform.position.y <= shadow.position.y+ groundOffset&&curJumpP <= 0.0f)
     {
         shadow.transform.localScale = new Vector3(1f, 1f, 0.0f);
         isMinSize = false;
         curJumpP = 0.0f;
         isGround = true;
         jumpCount = 0;
         body.transform.position = new Vector2(body.transform.position.x, shadow.position.y + groundOffset);
     }
 }
  로직설명
1. InputSystem에 키맵핑한 OnJump 발동시 jumpCount 조건 확인 -> 점프파워 대입, isGround 대입, jumpCount++
2. .transform.position에 y축으로 '파워* Time.deltaTime'만큼 Update마다 더해준다
3. 동시에 점프파워를 gravity * Time.deltaTime; 만큼 빼준다(중력)
4. 이후 '그림자 위치(y)보다 작거나 같은시 점프의 모든 변수를 초기화 한다

<카메라 무빙>

카메라는 플레이어를 따라다녀야함(위치를 움직임에 맞게 변경)

public class CamaraMove : MonoBehaviour
{
    [SerializeField] Transform player;
    [SerializeField] float followSpeed;

    Vector3 offset;
    Vector3 targetPos;

    void Start()
    {
        offset = transform.position - player.transform.position;
    }

    void LateUpdate()       // late는 다른 작업이 전부 완료된뒤 마지막에 업데이트된다
    {
        targetPos = player.transform.position + offset;
        this.transform.position = Vector3.Lerp(transform.position, targetPos, followSpeed * Time.deltaTime); // Larp 두 물체사이의 거리를 주어진 수만큼 보간
    }
}
LateUpdate에 구현한 이유
카메라의 경우 케릭터가 움직인 다음 위치를 받아야 하기 때문에 나중에 업데이트 되는 LateUpdate에 연산로직을 써야함
따라가기 속도를 준이유
움직임에 살짝 늦은 딜레이로 카메라가 이동하는건 게임적인 효과을 줄수있다

카메라를 특정영역 설정하여 케릭터가 특정영역안에서 카메라가 따라다니게 하는 기능은 추후에 맵과 미니게임이 완성되면 추가 하도록 하겠다


버그수정


 

점프시 그림자가 작아지는데 착지할때 커지는 로직이 작동을 안함
= 업데이트시 작아지는거 반복하면서 조건문을 반복중 계속 충족해서 사실상 조건문안에 단한번 작동하여 무용지물

>수정전 코드<

shadow.transform.localScale -= new Vector3(shadowMinSize * Time.deltaTime, shadowMinSize * Time.deltaTime, 0.0f);
if (shadow.transform.localScale .x<= shadowMinSize || shadow.transform.localScale.y <= shadowMinSize)
{
    shadow.transform.localScale += new Vector3(sizeSpeed * Time.deltaTime, sizeSpeed * Time.deltaTime, 0.0f);
}

조건문은 언제나 한번만!


마치며.


 

카메라의 경우 플레이어 따라다니기 기능만 있다면? 그냥 플레이어 자식오브젝트로 두면 따라다닌다 하지만 추가적으로 딜레이, 영역등 설정하려면 코딩이 필요하다 그리고 이후에 Cinemachine 기능을 이용하면 에디터를 통해 구현이 가능해진다