0407 - Unity 부트캠프 TIL [1일차] 유니티 기초 강의 1~2주차

Hyeon O·2025년 4월 7일

Unity_BootCamp 1주차

목록 보기
1/5
post-thumbnail

📚 오늘의 학습

  • Unity 게임 개발 1주차 강의: [빗물 받는 르탄이]
  • Unity 게임 개발 2주차 강의: [풍선을 지켜라]

위 강의 수강 중 새롭거나 다시 떠올린 개념을 정리하였다.
1. Instantiate()
2. ToString()
3. PlayerPrefabs.HasKey()
4. Invoke()
5. 애니머이터 Settings

🧠 오늘 새롭게 배운 것 & 다시 떠올린 개념들

Instantiate();

원본 오브젝트(prefab)의 데이터를 바탕으로 새로운 인스턴스를 위한 메모리 공간을 할당하는 함수!

오늘 개발 예제에서는 내려가는 사각형을 생성하는데 사용하였다.

하지만 단순히 '오브젝트를 생성한다'는 수준에서 벗어나, 메모리 내부 동작까지도 궁금해졌고, 이에 대해 좀 더 깊이 정리해보고자 한다

이 함수는 native(Unity C++) 영역에서 이루어지며, Unity는 C#에서 호출된 Instantiate()를 C++ 쪽으로 바인딩해서 처리한다.

이 과정은 GC(가비지 컬렉션)의 대상이 되는 관리 메모리와는 분리된 네이티브 힙 영역에서 대부분 수행된다.

  • 저게 무슨 소리? Unity의 메모리 구조는 크게 두 가지로 나뉜다.
    1. 관리 메모리 : C#에서 사용하는 일반적인 메모리, new 키워드로 만든 클래스, 리스트 등

    2. 네이티브 메모리 : Unity 엔진 자체가 사용하는 메모리, GameObject나 Transform 같은 것들(C++언어)

      즉, Instantiate()는 단순히 new MyClass()처럼 C# 객체를 생성하는 것과는 다르다. Unity는 대부분의 오브젝트(GameObject, Component, Transform 등)를 C++ 엔진 코드가 다루는 ‘네이티브 힙(Native Heap)’에 생성한다.

      그래서 C#의 가비지 컬렉션(GC)이 이 오브젝트를 관리하거나 제거하지 않는다.

그렇다는 것은 GC에서 처리를 하는 것이 아니라서, 메모리 누수(memory leak)현상이 발생할 수 있기에 Destroy() 를 명확하게 호출해야 메모리 회수가 가능하다.

다른 방법으로는 풀링(Pooling) 기법이 있다. 간단히 설명하면 자료구조를 통해 회수와 생성을 반복하여 오브젝트를 재사용하는 방식이다.

또한 얕은 복사가 아닌 깊은 복사를 한다.
Unity는 내부적으로 오브젝트의 Transform, Renderer, Collider, Script 컴포넌트 등 모든 요소를 재귀적으로 복사한다.

오브젝트 계층 또한 전체 구조를 재귀적으로 복제해버린다.

Script 컴포넌트를 복사할 떄도 필드 값도 같이 복사된다.

단,[NonSerialized]나 static 필드는 제외.

위 함수 호츨을 통해 생성된 오브젝트는 기본적으로

비활성화 상태에서 시작 후 자동 활성화된다.

이해가 잘 안되니 한번 실험을 해보자

InvokeRepeat ing("MakeSquare", 0f, 1f); 로 사각형을 0~1초 간격으로 호출하는 코드와

MakeSquare() 함수가 호출되면 Instantiate(squrae); 코드로 사각형 오브젝트를 생성하는 코드를 만들었다고 가정하고 로그를 출력하는 코드를 넣어 실행시켜보면,

  • 참고 : InvokeRepeat() Unity에서 지정한 시간 간격으로 특정 함수를 반복 호출할 수 있게 해주는 함수! 비슷한 함수로 StartCoroutine() 가 있지만 보다 더 간단하게 주기적인 호출을 처리할 때 유용하다. 함수 시그니처는 다음과 같다.
    InvokeRepeating(string methodName, float time, float repeatRate);
    //호출한 함수 이름, 첫 호출까지 지연 시간, 이후 반복 호출 간격

약 16초동안 18번의 Awake()와 OnEnable() 함수가 실행되는 것을 볼 수 있다.

또한 순서도

  1. 복제 직후 Awake() 호출 → 초기 세팅, 인스턴스가 메모리에 생성될 때 1번만
  2. 자동 활성화 이후 OnEnable() 호출 → 오브젝트가 활성화 될 떄마다
  3. 프레임 시작 후 Start() 호출이 된다. → 위 두 함수가 끝난 다음 프레임 1회

갑자기 다른 함수 살펴보는 것 같아서 돌아오면, Instantiate() 함수는 게임 로직 초기화와 밀접한 관계가 있다고 볼 수 있고, 여러 오브젝트가 동시에 인스턴스화 될 때 실행 순서에 주의가 필요할 수 있다.

time.ToString("N2");

여기서 ToString("N2")은 C#의 표준 숫자 형식 지정자(Standard Numeric Format String) 중 하나이다.

N2는 소수점 2 자리까지 출력하라는 것이다.

소수점 없이 표현하고 싶다면 아무것도 넣으면 된다.

PlayerPrefabs.HasKey()

위 함수는 Unity에서 로컬 저장소에 특정 키가 존재하는지 확인하는 데 사용하는 함수이다.

PlayerPrefs는 주로 간단한 데이터(점수, 설정값 등)를 저장/불러오기 위한 기능이고, HasKey()는 그 중에서도 값이 존재하는지 확인하는 용도이다

간단한 로컬 저장소로 이해하면 된다. 키-값 구조로 데이터를 로컬에 저장한다

단, string, int, float만 저장 가능하다.

bool PlayerPrefabs.HasKey(string key);

key에 들어가는 문자열에 해당하는 키가 저장소에 있는 확인하여 bool 형태로 반환한다.

있다면 true, 없다면 false.

지엽적인 내용이지만 Windows는 레지스트리에 저장하고,

안드로이드는 SharePreference에,

iOS는 NSUserDefaults에 저장한다.

관련 함수는 다음과 같다.

함수기능
SetInt(string key, int value)정수 저장
SetFloat(string key, float value)실수 저장
SetString(string key, string value)문자열 저장
GetInt(string key)정수 가져오기
DeleteKey(string key)특정 키 삭제
DeleteAll()모든 키 삭제 (테스트 초기화용)

주의사항으로 저장 용량에 제한이 있어 가벼운 데이터만 가능하고

보안성이 낮다.

또한 키 이름이 중복되면 덮어쓰므로 키 이름 관리를 명확하게 해야한다.

위 함수를 통해 최고점수를 기록하는 기능을 구현하였는데

자꾸 최고 점수가 갱신이 안돼서 살펴보았더니

변수를 잘 못 작성했다… 아래는 문제가 발생한 코드다.

 bestScore.text = **best**.ToString("N2"); //best를 time으로 오타 -> 최고점수 갱신 안됨

Invoke()

위 함수는 특정 함수를 지정된 시간 후에 한 번만 호출하는 기능을 제공한다.

위에서 짧게 작성한 InvokeRepeating() 과는 다르게, 단일 지연 호출에 특화되어 있어

타이머나 연출 타이밍 제어에 자주 사용된다.

Invoke(string methodName, float time);

파라미터는 호출할 함수 이름(문자열이다), 몇 초 후에 호출에 대한 시간 값이다.

이 때 시간은 Time.timeScale의 영향을 받는다.

즉, timeScale = 0 이면 Invoke()도 지연된다.

추가적으로 주의할 점은

문자열 기반이기에 오타에 민감하고

파라미터가 없는 메소드만 호출 가능하다.

파라미터가 필요한 경우네는 람다 또는 코루틴의 사용을 고려해야한다.

애니메이터 Settings 인스펙터 창

  1. Has Exit Time

    • 체크 시: 현재 애니메이션이 일정 시간만큼 재생된 후에만 전이 가능
    • 체크 해제 시: 조건만 만족하면 언제든 즉시 전이 가능
    • 지금은 해제되어 있으므로, 전이 조건만 맞으면 언제든 상태 전환이 일어납니다.
  2. Exit Time = 0.625

  • 애니메이션 클립의 재생 시간 기준으로 전이 시점을 설정함 예: 애니메이션이 1초라면 0.625초일 때 전이 가능
  • 하지만 Has Exit Time이 꺼져 있으므로 현재는 이 값이 무시됨
  1. Fixed Duration (✔️ 체크됨)
  • 전이 시간이 클립 길이에 비례하지 않고, 고정된 초 단위로 적용됨
  • 체크 해제 시에는 전이 시간이 애니메이션 클립의 비율(%)로 작동
  1. Transition Duration = 0.25
  • 전이가 부드럽게 이어지는 시간 (0.25초 동안 두 애니메이션이 블렌딩됨)
  • 즉, 이전 상태에서 새 상태로 0.25초 동안 자연스럽게 이어지게 만듬
  1. Transition Offset = 0
  • 새 애니메이션의 시작 위치 (0.0 = 처음부터)
  • 예: 0.3이면 새 애니메이션을 30% 지점부터 시작
  1. Interruption Source = None
  • 전이 중 다른 전이가 개입(Interrupt) 가능한지 여부 설정
  • None이면 → 전이 중에는 다른 전이 조건이 있어도 무시
  • 일반적으로 공격 중 피격이나 캔슬 동작을 넣고 싶다면 여기서 Current StateNext State를 선택
  1. Ordered Interruption (✔️ 체크됨)
  • Interruption SourceCurrent StateNext State일 때만 유효
  • 전이가 일어나는 순서를 정해진 순서대로 처리할지 여부
  • 지금은 None이므로 실질적으로는 영향 없음!

💭 오늘의 회고

오늘은 Instantiate()가 단순한 복제 함수가 아니라, Unity 엔진 내부 메모리 구조 및 객체 생명주기와 깊이 연결되어 있다는 점을 알게 되었다.
또한 PlayerPrefs를 사용한 로컬 저장 기능과 Animator의 트랜지션 설정까지 실제 게임 연출에 영향을 주는 요소들을 정리해보며, 실수와 이해를 동시에 기록할 수 있었다.

실험과 정리 과정을 블로그에 남기면서 점점 코드와 시스템을 더 깊이 이해하게 되는 느낌이 든다.
아직 두서없는 정리이긴 하지만...하다 보면 이 또한 향상될 것이라 확신한다.

profile
천천히, 꾸준하게, 끝까지

0개의 댓글