공부/Unity

[Unity] 유니런 중요 스크립트 및 기능 정리

굴러다니다니 2023. 4. 4. 21:55
728x90

Rigidbody 2D & Box Collider 2D & Circle Collider 2D

플레이어와 땅의 충돌을 처리하는 방법 -> collider2D & Rigidbody2D 사용하기!

 

물체에게 중력을 작용하게 만들기 위해 Rigidbody 2D를 넣어준다.

실행시켜보면 플레이어가 계속 떨어져서 화면에 안잡히게 된다.

 

Rigidbody 2D에서 Collision Detection을 Continuous로 해줘야 충돌 감지를 끊기지 않고 계속 할 수 있다.

이전의 설정은 Discrete (이산)이었다.

* Rigidbody: 중력과 동일한 효과

또한 Constraints에서 혹시 모를 Z축으로의 회전을 방지하기 위해 Freeze Rotation을 걸어준다.

 

boxcollider를 추가할 시, 생긴 모양에 따라 이를 포함하는 box collider 형태가 연두색으로 (잘 안보임) 미묘하게 잡힌다.

Player에게 Circle collider 2D를 넣어주면

 

 이렇게 플레이어를 둘러싸는 형태로 크게 원이 잡힌다.

 

이 상태로 만일 게임을 시작하면 충돌 처리에 의해

플레이어는 땅 위에서 공중부양을 동동 하고있겠지?

 

충돌 범위를 수동으로 바꿔봅시다

 

 

 

 

 Edit Collider를 누르고 초록색 원의 크기를 줄여주면 된다!

 

Box Collider를 응용해 낙사 판정을 해보자.

 

빈 오브젝트 생성 후 Box Collider 2D를 넣어 Edit Collider로 크기를 지정해줬다.

플레이어가 올바르게 착지하지 못한다면 해당 구역으로 떨어져 충돌을 감지할 것이고, 그렇다면 사망판정을 해줄 것이다.

여기서 그냥 설정을 놔둔다면 플레이어가 낙사하지 않고 그냥 저 초록 네모위에 선다. 우뚝

 

열심히 달리는 우리의 주인공

요런 이상한 부분을 방지하기 위해 우측에 Is Trigger를 꼭 체크해주자.

충돌함은 확인하고 플레이어는 그대로 떨어지게 된다.

 

*Is Trigger : 충돌 여부는 판단하고(배열에 저장됨), 통과하게 만듦.


Audio Source: 게임 오브젝트에 소리를 낼 수 있는 능력 부여

Play on Awake: 불러오자마자 한번 실행 할지 말지 결정

Audio Listener: 소리를 내는 오디오 소스가 있다면, 이를 들을 수 있게 만드는 오디오 리스너 컴포넌트가 존재해야 한다.

-> 한 씬당 하나만 존재해야 하며 보통 Main Camera에 이미 추가되어 있다 (한번 더 추가한다면 오류 발생)

 

이미지를 Sprite Editor를 통해 잘라주고 애니메이션으로 만들어보자.

Player를 누른 상태로 Animation Window를 켜서 Create하며 Run.anim을 만들어주자.

달리는 이미지에 해당되는 이미지들(8개)를 끌어와 키프레임을 조정하면 애니메이션 생성 완료!

* Animation Sample Rate: 초당 프레임 값을 조정, 기본은 60 (기본설정으로 꺼져있지만 켜서 수정하자)

Die는 Sample Rate를 6으로 설정해 천천히 작동

-> Run, Jump, Die 만들기

만들기 끝!

 

*Animator vs Animation

애니메이션을 모아서 제어를 하기위해 사용, 어떤 상태에 따라 애니메이션을 변경시켜주기 위해 애니메이터를 사용

Animator Cotnroller를 눌러 애니메이터를 만들고, Controller(동작하려는 대상)에 Player를 넣어주자

 

Animator창을 열어 우클릭 -> Make Transition으로 상호 연결해주자

Entry: 현재 상태가 진입하는 입구

Exit: 상태 머신의 동작이 종료되는 출구

Any State: 현재 상태가 무엇이든 상관없이 특정 상태로 즉시 전이하게 허용하는 상태 

(부딪히거나 하면 어떤 상황이든 죽어야 함 -> Any State에서 Die로 연결)

Animator창에서 Parameter 추가

Bool로 Grounded를, Trigger로 Die를 추가한다. (발판에 닿았는지 확인, 트리거는 특정 값 할당이 불가, set하면true, 그 후 바로 false, 어떤 사건이 발생했을 때 전이가 일어나게 하는 조건에 많이 사용)

 

 Run -> Jump

종료까지 걸리는 Has Exit Time 해제, 바뀌는 시간인 Transtion Duration 0, 조건 (Conditions list)에 Grounded 추가 후 false 설정 (false일 때 동작함)

 

 Jump -> Run

 Has Exit Time 해제, Transition Duration 0, Grounded가 true인 경우에 하게

 

 Any State -> Die

 Transition Duration 0, 조건에 Die추가

 

Player Control 스크립트의 설명

public class PlayerControl : MonoBehaviour
{

    public AudioClip deathClip;

    private int jump_count = 0;
    private bool isGrounded = false;
    private bool isDead = false;

    [SerializeField] private float jump_Force = 500f;

    private Rigidbody2D playerRigid;
    private Animator animator;
    private AudioSource audio;

AudioClip이 원래 점프소리로 들어가있는데, 이를 바꿔주기 위해 따로 AudioClip 타입의 deathClip을 선언해준다.

플레이어는 점프를 두 번까지 할 수 있게 할 것이므로, jump 횟수를 세어주는 변수를 0으로 초기화를 해준다.

땅에 붙어있는지, 죽었는지를 확인하는 bool 변수들과 점프할 때 순간적인 힘의 정도를 결정하는 float를 선언해준다.

Rigidbody2D, Animator, AudioSource를 받을 수 있는 변수도 선언해준다.

 

    void Start()
    {
        playerRigid = transform.GetComponent<Rigidbody2D>();
        animator = transform.GetComponent<Animator>();
        audio = transform.GetComponent<AudioSource>();
    }

유니티에서는 컴포넌트 방식을 사용하는데, 게임 오브젝트의 컴포넌트를 가져올 때 사용하는 함수이다.

컴포넌트 패턴을 사용한다.

받아서 하나씩 변수에 넣고 초기화를 해준다.

 

    void Update()
    {
        if (isDead)
        {
            return;
        }

        if (Input.GetMouseButtonDown(0) && jump_count < 2) //왼쪽 0, 오른쪽 1
        {
            isGrounded = false;
            jump_count++;
            //점프 직전의 속도를 순간적으로 0으로 변경
            playerRigid.velocity = Vector2.zero;
            //플레이어 리지드바디의 위쪽으로 힘주기
            playerRigid.AddForce(new Vector2(0, jump_Force));
            //점프할 때 소리 재생
            audio.Play();
        }
        //마우스 왼쪽 클릭을 떼고, 속도의 y값이 양수면 (위로 상승중이라면)
        else if (Input.GetMouseButtonUp(0) && playerRigid.velocity.y > 0)
        {
            //현재의 속도를 절반으로 줄이기
            playerRigid.velocity *= 0.5f; //나누기보다 곱하기가 연산이 빠르다
        }
        animator.SetBool("Grounded", isGrounded);
    }

void Update문을 통해          

 1. 사용자의 입력(마우스 왼쪽 클릭)을 감지하고 점프 처리
 2. 점프 카운트는 2번까지만 가능, 확인
 3. 플레이어가 죽으면 더이상 실행 불가하게
를 구현한다.

 

isDead가 true이면 -> 죽었으면 return해 Update문의 실행을 마친다.

마우스의 0, 즉 왼쪽 버튼이 클릭되었고 && jump를 2번보다 적게했다면 점프가 가능하다.

점프하고 있으니 isGrounded 땅에 붙어있는지를 false로 바꾸고, 점프 카운트를 증가한다.

점프 직전의 속도를 0으로 바꾸고 리지드바디의 y값으로 힘을 주며 소리를 재생시킨다.

만일 왼쪽 클릭을 떼고, 속도가 양수, 즉 아직도 올라가는 중이라면 속도를 반으로 줄인다.

그 다음 animator에 접근해 Grounded라는 애니메이터 변수를 isGrounded 변수의 bool값과 동일하게 써준다.

 

    private void Die()
    {
        //사망처리 
        animator.SetTrigger("Die");
        //현재 audioclip 을 deathclip으로 변경
        audio.clip = deathClip;
        audio.Play();

        playerRigid.velocity = Vector2.zero;
        isDead = true;

        GameManager._instance.PlayerDead();
    }

Die함수를 작성해준다.

animator의 Die 애니메이션을 재생하고, audio clip (점프소리)를 죽는 소리로 바꿔준 뒤 재생한다.

속도를 0으로 만들어 즉시 이동을 멈추고 isDead bool값을 true로 바꿔준 다음 싱글톤 선언한 GameManager의 PlayerDead 함수를 재생해준다.

 

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.CompareTag("Dead") && !isDead) //연산자 사용보다 builtin method사용이 더 빠르다
        {
            Die();
        }
    }
    private void OnCollisionEnter2D(Collision2D collision)
    {
        //바닥에 닿았음을 감지하는 처리
        //어떠한 콜라이더가 닿았으며, 충돌표면이 위쪽을 보고 있다면 -> 땅에 올라와있다
        if (collision.contacts[0].normal.y > 0.7f) //지금은 플레이어 하나밖에 닿을 수 없으니까 닿아서 넣은 것들중에 첫번째꺼
        {
            isGrounded = true;
            jump_count = 0;
        }
    }
    private void OnCollisionExit2D(Collision2D collision)
    {
        isGrounded = false;
    }
}

OnTriggerEnter2D (트리거 부분에 들어왔을 때 실행된다)

부딪힌 물체의 태그가 Dead고 isDead가 false이면 Die함수를 실행시킨다.

OnCollisonEnter2D (콜라이더에 닿았을 때 실행)

부딪힌 물체의 0번째의 충돌 표면이 위쪽이면 땅 위에 존재하고, jump 카운트를 초기화해준다.

CollisionExit 땅에서 나갔을 때 is Grounded를 false로 바꾼다.

 

 


Local vs Global

  엔진 내의 기준이 되는 좌표: global 좌표

  부모 오브젝트를 기준으로 하는 좌표: local 좌표 (local에 Position, Rotation, Scale 다 있음)

 

GetComponent: 유니티는 컴포넌트 방식을 사용, 컴포넌트를 가져올 때 사용하는 Method

 

Trigger vs Collider

   Rigidbody 불필요 vs 필요, 둘 다 이벤트함수를 가지고 있다.

 

Audio Listener > Audio Source > Audio Clip

메인 카메라에 한개씩 달려있고, 한 씬에 한개씩 가질 수 있다 > 오디오 리스너에게 가고, 오디오 클립을 재생시키기 위한 역할 > 재생당하는 클립

 

Game Object Active: setactive 메소드를 통해 bool값을 매개변수로 활성화 / 비활성화

 

Tag: 찾기 편하게 특정한 오브젝트를 빨리 찾게 도움

 

Sort Layer: 2D에서 원근법은 필요없다, 오브젝트 두개가 겹친다면 보이고 싶은 거에 맞게 정렬을 해야함, 레이어의 순서에 따라 그림의 순서를 정해주는 레이어

 

Instantiate vs Destroy: 오브젝트를 안전하게 생성 및 삭제ㅎ 메소드

 

Object Pooling: 오브젝트의 생성과 삭제를 지속적으로 하면 메모리 누수, 활성화 / 비활성화 기능으로 이를 대신하며 오브젝트를 재사용

728x90