[Unity] 2. 스크립트 & Life Cycle & 쓰레드

치치·2025년 2월 14일
0

Unity

목록 보기
2/27
post-thumbnail

비쥬얼 스튜디오

  • 만약 유니티 내 비쥬얼 스튜디오가 연동이 되어있지 않을 경우
    -> 스크립트가 활성화 되지 않는 상태가 발생한다
    -> 직접 할당해주자!



쓰레드

유니티는 단일 쓰레드

단일 쓰레드 : 작업을 처리하는 단위가 1개
-> 씬을 넘어갈때 불러오는 작업을 마치지 못하면 씬은 넘어가더라도 움직일 수 없음

  • 이걸 로딩을 사용하여 감추는 것을 페이크 로딩이라 함

  • 페이크 로딩 : 로딩이 99까지 찬 뒤 씬을 멈추는 기능
    -> 99이후로는 서서히 로딩하는 방식
    -> 컴퓨터마다의 성능차이를 동일 시 하기 위해 사용한다

  • 이전 씬에서 새로운 씬으로 이동할 때, 비동기적으로 씬을 로딩할 수 있다

멀티 쓰레드 : 작업을 병렬적으로 처리 가능



스레드 교착 상태(DeadLock)

둘 이상의 스레드가 서로의 작업이 끝나기만을 기다리며 작업을 더 이상 진행하지 못하는 상태

  • 멀티 스레드한 번에 하나의 스레드만 리소스에 접근할 수 있다
    -> 접근하고 잠금(Lock)을 한다는 것

  • 아래의 예시에서 B가 key를 가지고 리소스에 접근하면 잠구기 때문에 다른 A가 접근할 수 없다
    -> 근데 만약 점유하고 그대로 쭉 대기한다면?
    -> 다른 스레드가 계속 접근할 수 없기 때문에 교착상태 발생



스크립트 기본 구조

구조 : 접근 지정자 + 클래스 + 클래스 이름 : 상속받는 클래스
public class NewBehaviourScript : MonoBehaviour

MonoBehaviour을 상속받아야만 게임 오브젝트에 스크립트를 넣어줄 수 있다

-> MonoBehaviourBehaviour을 상속받은 상태
-> BehaviourComponent 클래스를 상속받은 상태

유니티는 컴포넌트 패턴을 따르기 때문에, 컴포넌트여야 게임 오브젝트에 넣을 수 있다
-> 즉, 이 스크립트가 Monobehavior를 상속받아야만 게임 오브젝트에 넣을 수 있는 것

즉,MonoBehaviour를 상속받지 않는 스크립트라면 게임 오브젝트에 넣을 수 없음


스크립트 이름 변경

유니티 내에서 스크립트 이름을 변경한 뒤 스크립트 내부의 이름도 바꿔줘야함



스크립트 기본 네임스페이스

UnityEngine : 유니티에서 제공하는 다양한 함수 클래스들을 사용할 수 있다
Collections : C#의 컬렉션 클래스들이 포함된 네임스페이스
-> 리스트, 큐, 스택, 딕셔너리와 같은 일반적인 자료구조 사용가능


생명 주기 (Life Cycle)

생명주기 실행 순서 (공식 사이트)

생명주기는 순서대로 진행되지만, 우리는 크게 볼 것이다
Awake -> OnEnable -> Start -> FixedUpdate -> Update -> LateUpdate -> OnDisable -> OnDestroy

  • 초기화
    Awake / OnEnable / Start

  • 물리
    FixedUpdate / OnTrigger / OnCollision

  • 업데이트
    Update / LateUpdate

  • 소멸
    OnDisable / OnDestroy

<모두 게임 오브젝트에 해당 스크립트가 부착되어야 그 게임 오브젝트에 적용되는 것이다>

1. 생성되었을 때 (초기화)

  • Awake

Awake 함수란?
게임 오브젝트가 생성되었을 때, 단 한번만 호출되며,
컴포넌트가 비활성화된 상태에서도 호출되는 이벤트 함수입니다.

: 생성자 역할 (값 초기화나, 미리 정의해두는 것)

: 모든 생명 주기 함수에서 가장 먼저 실행된다

: 두 게임 오브젝트에 같은 스크립트를 넣었을 경우, 어떤 오브젝트에 Awake가 먼저 호출되는지는 알 수 없다
-> 실제 실행할때마다 매번 바뀜
-> 스크립트 우선순위를 바꾸면 되지만 선호하지 않는 방법임

이러한 문제를 해결하는 방법은 Awake와 Start를 이용해 초기화 단계를 분리하는 것이다



  • OnEnable

OnEnable 함수란?
게임 오브젝트가 활성화될 때마다 호출되는 이벤트 함수입니다.

: 게임 오브젝트가 활성화 될때마다 호출된다

유니티 가비지 컬렉터는 C#가비지 컬렉터와 달라서 메모리 파편화가 남아있게 되어 메모리 낭비 (C#가비지 컬렉터는 세대별 가비지 컬렉터로 압축이 가능하다)
-> 게임 오브젝트를 생성, 파괴, 생성, 파괴 하지말고 비활성화 시키고 -> 다시 생성할때 다른 위치에서 생성되게 한다

-> 다시 활성화 했을때, 그 위치 그대로 다시 활성화 되기 때문에 다른 위치로 이동 후 활성화

게임 오브젝트 비활성화



  • Start

Start 함수란?
게임 오브젝트가 활성화되었을 때 호출되며, 단 한번만 호출되는 함수로,
컴포넌트가 비활성화 되었을 땐 호출되지 않는 이벤트 함수입니다.

: 스크립트가 비활성화 -> 활성화 하더라도 start는 호출되지 않는다
: 맨 처음부터 활성화되어야만 호출되는 것
(컴포넌트와 게임오브젝트는 다른 말이야.)
: 즉, 컴포넌트가 활성화 된 상태에서 한번 호출되는 것
-> 처음부터 컴포넌트가 비활성화되었다면 호출되지 않는다


예시)

  • 게임 오브젝트에 부착된 '스크립트'가 비활성화 된 상태인 경우
    Awake, OnEnable, Start 중에서 Awake만 호출된다
    Awake는 비활성화 상태에서도 호출되기 때문이다

2. 실행중 일 때 (프레임 단위로)

  • FixedUpdate

FixedUpdate 함수란?
게임 오브젝트가 활성화되었을 때 호출되며, Time Step에 설정된 값에 따라
일정한 주기로 호출되는 이벤트 함수입니다.

: 정교한 체크가 필요한 (고정된 단위로) 작업에서 사용
-> 물리 관련들에서 사용
-> time step에 지정된 값에 따라 일정한 주기로 호출
-> 이 값은 건드리지 않는 편을 선호한다(알아만 두자)


  • Update

Update 함수란?
게임 오브젝트가 활성화되었을 때 호출되며, 프레임 간격으로 호출되는 이벤트 함수입니다.

: 입력받을때 주로 사용, 물리적인 내용이 없다면 Update문에서 작성해도 상관없다


  • LateUpdate

LateUpdate 함수란?
게임 오브젝트가 활성화되었을 때 호출되며, Update가 끝난 뒤에 호출되는 이벤트 함수입니다.

: 카메라가 오브젝트를 따라다니는 연출 같은거
-> FixedUpdate를 사용하는 게임 오브젝트는 카메라도 Fixed에 해야함
-> LateUpdate는 업데이트 함수가 끝난뒤에 호출되기 때문에, 정교하게 움직이는 오브젝트라면 fixed에


3. 소멸되었을 때 (파괴)

  • OnDisable

OnDisable 함수란?
게임 오브젝트가 비활성화되었을 때 호출되는 이벤트 함수입니다.

  • OnDestroy

OnDestroy 함수란?
게임 오브젝트가 소멸되었을 때 단 한번만 호출되는 이벤트 함수입니다.


내 에셋 찾는 법

Package Manager -> my Assets



Awake() Start() 차이점

두 함수의 차이점이 헷갈려서 더 알아보았다

다른 객체의 컴포넌트를 참조하고 싶을 경우를 예시로 들어보자

  • 위에서 봤듯이 두 객체의 Awake함수를 호출하더라도 어떤 것이 먼저 실행될지는 알 수 없다 (매번 호출 순서가 다름)
    -> 운이 좋아서 B객체의 Awake 먼저 호출되면 괜찮겠지만, 만약 A객체의 Awake가 먼저 호출된다면?

  • B객체의 컴포넌트가 초기화되지 않은 상태기 때문에 A객체가 B객체의 컴포넌트를 참조하려고 할 경우 NullReferenceException 오류가 발생!


그럼 AwakeStart는 주로 어떻게 사용하는가?

  • Awake에서는 자기 자신의 컴포넌트를 초기화하거나 참조한다

  • Start에서는 다른 객체의 컴포넌트를 참조한다
    -> 컴포넌트는 초기화 된 상태여야지만 사용이 가능하다

  • Awake는 무조건 Start보다 먼저 실행되기 때문에, 이렇게 초기화를 나눠서 작성하게 되면 초기화 순서 문제를 해결할 수 있다



OnEnable() Start() 차이점

OnEnable, Start 모두 컴포넌트가 활성화 되었을 때 호출된다

  1. OnEnable은 게임 오브젝트가 활성화 될때마다 호출됨
  2. Start는 게임 오브젝트가 활성화 되있다면 딱 한번 호출됨

라이프 사이클 호출 순서에 따르면 OnEnable이 먼저 실행되고 Start가 실행된다

  • OnEnable은 게임 오브젝트가 활성화 될때마다 호출되기 때문에, 한번만 발생해야하는 초기화 작업에는 적합하지 않다
  • Start에서 초기화 작업이 이루어지는게 효율적


OnDisable() OnDestroy() 이벤트 구독 취소

  • OnDisable은 게임 오브젝트가 비활성화 되었을때 & 컴포넌트가 비활성화 될때 호출된다

  • OnDestroy는 게임 오브젝트가 소멸될때 호출된다

  • 라이프 사이클 실행 순서를 보면 OnDisableOnDestroy보다 먼저 실행된다

OnDisable은 이벤트 구독 취소를 할 수 있다
-> 게임 오브젝트가 비활성화 되었어도, 이벤트 구독이 유효할 수도 있음

만약, 이벤트가 등록된 상태에서 OnDestroy()로 게임 오브젝트가 파괴 될 경우 이벤트 구독자로써 메모리에 남게된다 <메모리낭비>

  • 구독 취소를 하기 위해서는 게임 오브젝트를 비활성화 시켜서 OnDisable을 호출해야만 한다

그러니 메모리 누수 방지를 위해서라도
게임 오브젝트를 비활성화 한 뒤 OnDisable을 호출하여 구독을 취소하고, 게임 오브젝트를 파괴하여 OnDestroy를 호출하고 리소스 해제 및 정리를 해주는 것이 좋다



FixedUpdate() Update() 차이점

  • Update : 스크립트(컴포넌트)가 활성화 상태일 때, 프레임마다 한번씩 호출된다
    -> 주기가 일정하지 않아 물리효과가 적용되지 않은 오브젝트의 움직임이나 단순 타이머, 키입력 등을 받을 때 사용한다

  • FixedUpdate : Time Step에 설정된 값에 따라 일정한 주기로 호출된다
    물리 효과가 적용된(Rigidbody) 오브젝트를 조정할 때 사용된다. Update는 불규칙한 호출임으로 물리충돌 검사로는 상대적으로 부적합하다.
    참고 자료
    https://kukuta.tistory.com/406

profile
뉴비 개발자

0개의 댓글