본문 바로가기

유니티 2D 기본(Platformer Game)

3. 2D에서 플레이어 이동 구현

2D는 Vector2, 2D컴포넌트를 사용. (3D는 Vector3 등)

Rigidbody2D, Collider2D

Physics2D

스크립트 상에서 2D 예

RigidBody2D rigid = GetComponent<Rigidbody2D>();
Vector2 vec = new Vector2(x, y);

 

플레이어 기본 이동 & 최고 속도 제한 로직

why? : Addforce를 계속 사용하면 플레이어의 이동 속도가 점점 빨라지므로

public float maxSpeed;
    void FixedUpdate()
    {
        //Move speed
        float h = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector3.right * h, ForceMode2D.Impulse);

        //Max speed
        if (rigid.velocity.x > maxSpeed) //Right Move
        {
            rigid.velocity = new Vector2(maxSpeed, rigid.velocity.y);
        }
        else if (rigid.velocity.x < (-1 * maxSpeed)) { //Left Move
            rigid.velocity = new Vector2(( -1 * maxSpeed), rigid.velocity.y);
        }
    }
}

 

오르막길 지형 만들기

1. 바닥의 마찰력 없앤다.

2. 공기저항으로 플레이어 멈추기 구현

Physics2D 만들고 Friction(마찰력) 0으로 수정 후 모든 바닥 오브젝트에 적용.

플레이어에 공기저항도 없고, 바닥에 마찰력도 없으니 사실 상 우주처럼 한 방향으로 같은 속도로 죽 미끄러지겠네요.

 

플레이어 오브젝트에 Linear Drag 수정

너무 높게 주면 낙하 속도도 느려지기 때문에 1~2 주는게 좋습니다.

 

 

 

공기저항으로 멈추긴 하나 점점 느려지다 멈출 뿐 한 순간에 바로 멈추진 않습니다.

키보드에서 키를 떼자마자 플레이어가 즉시 멈추게 구현합니다.

 

키보드에서 키를 떼자마자 플레이어가 즉시 멈추게 구현하는 로직

    void Update()
    {
        //Stop speed
        if (Input.GetButtonUp("Horizontal"))
        {
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);

        }
    }

normalized : 벡터 크기를 1로 만든 상태(단위벡터), GetAxisRaw처럼 단위를 구할 때 사용합니다. 

 

 

Flip

왼쪽 오른쪽 움질일 때 스프라이트를 반전시켜보겠습니다.

Rigidbody2D rigid;
SpriteRenderer spriteRenderer;

    void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        anim = GetComponent<Animator>();
    }
    
    
    void Update()
    {
        //Stop speed
        if (Input.GetButtonUp("Horizontal"))
        {
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);

        }
        //Flip
        if (Input.GetButton("Horizontal")) {
            spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1;
        }
    }

SpriteRenderer 컴포넌트를 가져와 .flipX에 Bool 값 전달합니다.

오른쪽 이동 -> GetAxisRaw가 양수 -> flipX에 false값 전달

왼쪽 이동 -> GetAxisRaw가 음수 -> flipX에 true값 전달

 

애니메이션 변경

변경하고 싶은 애니메이션 끼리 Make Transition를 눌러 화살표로 연결해줍니다.

변경 조건이 될 수 있는 매개변수를 만들어줍니다.

Bool 타입의 isWalk라는 변수를 만들었습니다.

 

이제 화살표를 클릭해 변경 조건을 만들어 줍니다.

제일 밑 Conditions에서 +를 눌러 어떤 변수가 어떤 값일 때 애니메이션을 전환할 것인지 정해줍니다.

 

그리고 추가로 다음도 적용해줍시다.

has Exit Time : 애니메이션 전환 시 재생되고 있는 애니메이션이 다 재생된 후 전환하는 여부

체크 해제해줍니다.

타임라인 : 애니메이션 전환 시 부드럽게 넘어가게 합니다. 필요없으니 상단 파란 화살표를 처음으로 끌어다 놓읍시다. 

애니메이션 전환 로직

    public float maxSpeed;
    Rigidbody2D rigid;
    SpriteRenderer spriteRenderer;
    Animator anim;

   void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        anim = GetComponent<Animator>();
    }   
   
   void Update()
    {
        //Stop speed
        if (Input.GetButtonUp("Horizontal"))
        {
            rigid.velocity = new Vector2(rigid.velocity.normalized.x * 0.5f, rigid.velocity.y);

        }
        //Flip
        if (Input.GetButton("Horizontal")) {
            spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1;
        }
        //Animation change
        if (Mathf.Abs(rigid.velocity.x) < 0.5) //Mathf.Abs는 절댓값 함수
        {
            anim.SetBool("isWalk", false);
        }
        else {
            anim.SetBool("isWalk", true);
        }
    }

Animation 컴포넌트를 가져오고, .SetBool("변수 이름", bool)로 값을 전달합니다.

rigid.velocity.x의 값을 절댓값으로 만들고, 그 값이 0.5보다 작으면 Idle 애니메이션 재생, 아니라면 walk애니메이션 재생하게 만들었습니다.