chyam

[unity]- 2d 기초 [충돌, slice, 애니메이터 기초] 본문

unity

[unity]- 2d 기초 [충돌, slice, 애니메이터 기초]

chyam_eun 2024. 6. 25. 12:33

골드메탈님의 2d 플랫포머 기초 영상을 보고 모르는것을 기록.

 

>충돌 여백

충돌여백이란 저 캐릭터의 아래와 바닥 사이의 공간이다. 

이를 고치기 위해서 default contact offset을 0에 가까운 수로하면 붙어있게된다.

 

>충돌 범위 설정

collider을 사용해야한다. 2D이면 2D가 붙은것을 사용해야한다.

만약 땅과 사람이있는데 collider을 속성에 넣지 않으면 그대로 떨어지게 된다. 

 

>중력 적용

rigidbody를 사용해야한다. 이것도 2D이면 붙은것을 사용해야한다.

이것을 만약 사용하지 않으면 중력이 적용되지 않아서, 사람이 위에 떠있는채로 시작되면 그냥 그곳에 고정이 되어있게된다. 

이걸 사용하게 된다면 위에서 시작되면 아래로 떨어지게된다. 

물체가 움직일때 회전안하기 위해서는 freeze rotation을 눌러야한다. 

 

>스프라이트 slice하기. sprite Editor 사용

single모드 - 하나의 그림을 다 쓴다

multiple모드 - 잘라서 쓴다.

위의 사진은 automatic 상태이다. 이미지를 분석해서 자동으로 잡아주는것이다.

위의 사진은 grid by cell size는 입력한 사이즈대로 균일하게 잘라준다. 나는 16 16으로 잘라주었다.

위의 사진은 grid by cell count 는 입력한 갯수대로 균일하게 자른다.

하고나서 slice를 누르면된다.

 

>애니메이터

transition은 애니메이션 상태를 옮겨갈수있다.

저 화살표모양이 transition이다.

애니메이터 매개변수는 상태를 바꿀때 필요한 변수이다.

conditions는 아래의 상태(ex. isWalking)이면 다음 상태로 넘어갈수있다.

has exit time은 애니메이션이 끝날때까지 상태를 유지하는가 이다. 

idle이랑 walk 이런것들이 겹치는 구간이 없도록 하는것이좋다.

animator controller에서 애니메이션을 반복 안하고싶으면 loop time을 끄면된다.

 

>마찰력

오르막길을 하려면 마찰력을 건들여야한다. 마찰력이 0이면 조금만 건들여도 계속 나아간다.

create->2d-> physics material 2d를 누르면 생성된다.

이때 공기저항( Linear Drag)을 설정하면 이동 시 속도를 느리게해준다. 

만약 공기저항이 크다면 위에서 내려올때도 영향을 미치기 때문에 느리게 떨어진다. 1~2를 하는것이 좋다.

처음에 내가 캐릭터에 box collider를 넣었었는데 이로 인해 움직이다가 멈추는 현상이 일어났다. 이를 하면 바닥의 미세한 경계에 걸려서 멈추는것이라고 한다. capsule collider로 바꾸면 해결된다.

또한 sprite renderer에서 filp를 X 를 누르면 물체가 보는 방향이 달라진다.

 

>스크립트

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

컴포넌트에 있는 것을 사용하기 위해서는 클래스 내에 객체?로 선언되어야한다.

 

Awake는 초기화를 해주는 부분이다. 

예를 들어 rigid 객체변수?를 GetComponent의 Rigidbody2D부분이라고 초기화를 해준다.

void Awake()
    {
        rigid = GetComponent<Rigidbody2D>();
        spriteRenderer = GetComponent<SpriteRenderer>();
        anim=GetComponent<Animator>();
    }

-지속적인 키 입력 : FixedUpdate() 사용. 단발적인 키 입력을 한다면 가끔씩 씹힐수도있다.

-단발적인 키 입력 : Update() 사용. 

normalized는 단위벡터로, 벡터크기 1을 말한다. 

void Update()
    {//키를 손에서 뗏을때
        if (Input.GetButtonUp("Horizontal")) { 
            //단위벡터를 해줘야한다. 
            rigid.velocity = new Vector2(rigid.velocity.normalized.x*0.5f, rigid.velocity.y);
        }
        //방향 전환
        if (Input.GetButton("Horizontal"))
            spriteRenderer.flipX = Input.GetAxisRaw("Horizontal") == -1;

        //멈췄을때
        if (Mathf.Abs( rigid.velocity.x) < 0.3)
        {
            anim.SetBool("isWalking", false);
        }
        else
        {
            anim.SetBool("isWalking", true);
        }
    }

GetAxisRaw는 -1,0,1 값을 반환한다. 즉각적인 반응을 위해 사용한다.

GetAxis는 -1~1 범위의 값을 반환한다. 부드러운 이동을 위해 사용한다.

 

절댓값은 Mathf.Abs()로 사용할수있다.

 

void FixedUpdate()
    {
        //move by key control
        float h = Input.GetAxisRaw("Horizontal");
        rigid.AddForce(Vector2.right * h, ForceMode2D.Impulse);
        if (rigid.velocity.x > maxSpeed) //오른쪽
        {
            rigid.velocity = new Vector2(maxSpeed,rigid.velocity.y);
        }
        else if(rigid.velocity.x < -maxSpeed) //왼쪽
        {
            rigid.velocity = new Vector2(-maxSpeed, rigid.velocity.y);
        }
    }

AddForce는 꾹 누를수록 빨라진다. 가속을 무한으로 받게된다. 

ForceMode에 Impulse는 질량을 사용하고 순간적으로 힘을 가한다. 

Vector2.right는 오른쪽 방향이며 h는 왼쪽 키를 누르면 -1, 아무것도 안누르면 0, 오른쪽 키를 누르면 1이라서 이에따라 (-1,0), (0,0), (1,0) 이 나온다.

 

무한으로 받지 않으려면 Max값을 if문으로 걸어줘야한다. 

 

velocity는 rigidbody의 현재 속도로, 직접 속도를 바꿀수있다. 

maxSpeed는 public이라서 Inspector창에서 조절할수있다. 기본은 0으로 초기화된다.

rigid.velocity.x이 최대 속도보다 빠르면 rigid.velocity.x의 값을 최대속도로 바꾼다.