GetComponent와 캐싱
`GetComponent`를 어디서 호출하고 언제 캐싱해야 하는지, 가장 자주 쓰는 참조 패턴을 정리합니다.
private Rigidbody body;
private void Awake()
{
body = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
body.AddForce(Vector3.forward * 4f);
}Category
Preparing references and filters for this topic. 이 주제의 레퍼런스와 필터를 준비하고 있습니다.
Category Reference
컴포넌트, 실행 순서, 물리, 프리팹, 씬 관리부터 Addressables, NavMesh, Input System, Cinemachine, Timeline, UI Toolkit, Shader Graph까지 Unity 핵심 흐름을 정리합니다.
Search titles, summaries, tags, and subcategories.
Showing 68 cards.
Subcategory
6 cards
`GetComponent`를 어디서 호출하고 언제 캐싱해야 하는지, 가장 자주 쓰는 참조 패턴을 정리합니다.
private Rigidbody body;
private void Awake()
{
body = GetComponent<Rigidbody>();
}
private void FixedUpdate()
{
body.AddForce(Vector3.forward * 4f);
}필드를 `public`으로 열지 않고 인스펙터에서 연결하는 `SerializeField` 기본 패턴을 정리합니다.
[SerializeField] private float moveSpeed = 5f;
[SerializeField] private Transform target;부모 기준 좌표와 월드 기준 좌표가 어떻게 다른지, `position`과 `localPosition` 중심으로 정리합니다.
transform.position = new Vector3(0f, 1f, 0f);
transform.localPosition = new Vector3(0f, 0f, 2f);Unity Editor에서 가장 자주 쓰는 도구 전환, Scene view 이동, 정렬 shortcut을 한 카드에 묶어 정리합니다.
자주 쓰는 기본 shortcut
Q Pan tool
W Move tool
E Rotate tool
R Scale tool
T Rect tool
F Frame Selected
Shift+F Lock View to Selected
Ctrl/Cmd+Shift+N New Empty GameObjectUnity에서 GameObject와 Component, Transform이 어떤 관계로 묶여 있는지와 왜 이 구분이 중요한지 정리합니다.
GameObject player = gameObject;
Transform tr = player.transform;
Rigidbody body = player.GetComponent<Rigidbody>();GameObject 비활성화와 Component 비활성화, active 상태 속성들이 어떻게 다른지 Unity 활성화 모델 기준으로 정리합니다.
gameObject.SetActive(false);
renderer.enabled = false;
bool self = gameObject.activeSelf;
bool active = gameObject.activeInHierarchy;6 cards
Awake, OnEnable, Start, Update, FixedUpdate, LateUpdate, OnDisable, OnDestroy가 어떤 순서와 역할로 이어지는지 Unity 라이프사이클 핵심 흐름을 정리합니다.
// 초기화 단계 (오브젝트 활성화 시 1회)
private void Awake() { _rb = GetComponent<Rigidbody>(); } // 로컬 컴포넌트 캐싱
private void OnEnable() { GameEvents.OnPause += HandlePause; } // 이벤트 등록
private void Start() { _manager = GameManager.Instance; } // 외부 참조 연결
// 프레임 루프 (매 프레임 반복)
private void Update() { ReadInput(); } // 입력, 일반 로직
private void FixedUpdate() { ApplyMovement(); } // 물리 이동, 힘 적용
private void LateUpdate() { TrackCamera(); } // 카메라 추적, 후처리 보정
// 비활성화/파괴
private void OnDisable() { GameEvents.OnPause -= HandlePause; } // 이벤트 해제
private void OnDestroy() { /* 최종 리소스 해제 */ }`StartCoroutine`의 yield 패턴, `WaitForSeconds` 계열 구분, `Update` 타이머 및 async/await와의 차이를 정리합니다.
private IEnumerator FlashDamage()
{
indicator.SetActive(true);
yield return new WaitForSeconds(0.15f);
indicator.SetActive(false);
}
// 시작 — Coroutine 핸들을 저장하면 나중에 중단할 수 있음
private Coroutine _flashHandle;
private void OnHit()
{
if (_flashHandle != null) StopCoroutine(_flashHandle);
_flashHandle = StartCoroutine(FlashDamage());
}
private void OnDisable()
{
if (_flashHandle != null)
{
StopCoroutine(_flashHandle);
_flashHandle = null;
}
}`Update`, `FixedUpdate`, `LateUpdate`를 어떤 기준으로 나누고, 입력·물리·카메라 로직을 어떻게 분리할지 정리합니다.
private Vector2 _moveInput;
private void Update()
{
// 입력은 Update에서 캡처
_moveInput = new Vector2(
Input.GetAxisRaw("Horizontal"),
Input.GetAxisRaw("Vertical")
);
}
private void FixedUpdate()
{
// 물리 이동은 FixedUpdate에서 소비
Vector3 velocity = new Vector3(_moveInput.x, 0f, _moveInput.y) * moveSpeed;
_rb.MovePosition(_rb.position + velocity * Time.fixedDeltaTime);
}
private void LateUpdate()
{
// 카메라는 플레이어가 움직인 뒤
_cameraRig.position = target.position + offset;
}컴포넌트가 활성화/비활성화될 때마다 반복 호출되는 `OnEnable`/`OnDisable`로 이벤트 구독·해제, 코루틴 관리, Input Action 연동을 안전하게 처리하는 패턴을 정리합니다.
private void OnEnable()
{
GameEvents.OnEnemyDied += HandleEnemyDied;
GameEvents.OnLevelUp += HandleLevelUp;
}
private void OnDisable()
{
GameEvents.OnEnemyDied -= HandleEnemyDied;
GameEvents.OnLevelUp -= HandleLevelUp;
}프레임 속도와 무관하게 이동·타이머·쿨다운을 만들기 위한 `Time.deltaTime`, `fixedDeltaTime`, `smoothDeltaTime` 패턴과 함정을 정리합니다.
// Update — 프레임 독립적 이동
transform.Translate(Vector3.forward * speed * Time.deltaTime);
// Update — 타이머 누적
elapsed += Time.deltaTime;
// FixedUpdate — 물리 기반 이동 (fixedDeltaTime 사용)
rb.MovePosition(rb.position + direction * speed * Time.fixedDeltaTime);일시정지·슬로모션 구현 시 `timeScale`, `unscaledDeltaTime`, `WaitForSecondsRealtime`을 어떻게 구분하고, 게임플레이와 UI 타이머를 어떤 시간 축에 놓을지 정리합니다.
// 일시정지
Time.timeScale = 0f;
// 재개
Time.timeScale = 1f;
// 슬로모션
Time.timeScale = 0.3f;
// pause 중에도 계속 도는 UI 타이머
pauseTimer += Time.unscaledDeltaTime;
// pause 중에도 기다리는 코루틴
yield return new WaitForSecondsRealtime(1f);9 cards
`OnCollision`과 `OnTrigger`를 언제 고르고, Rigidbody/Collider/Is Trigger 조합이 어떻게 콜백 동작을 바꾸는지 정리합니다.
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Player"))
{
Debug.Log("Player entered");
}
}Legacy Input Manager와 새 Input System의 차이, polling 위치, 입력 버퍼링 기준을 함께 정리합니다.
private void Update()
{
float x = Input.GetAxisRaw("Horizontal");
float z = Input.GetAxisRaw("Vertical");
moveDirection = new Vector3(x, 0f, z).normalized;
if (Input.GetButtonDown("Jump"))
{
Jump();
}
}물리 객체를 직접 Transform으로 옮기지 않고 `Rigidbody`를 통해 다루는 기본 이동 패턴을 정리합니다.
private void FixedUpdate()
{
body.MovePosition(body.position + moveDirection * moveSpeed * Time.fixedDeltaTime);
}시선, 클릭, 거리 감지처럼 직선 방향 검사에 자주 쓰는 `Physics.Raycast` 기본 흐름을 정리합니다.
if (Physics.Raycast(origin, direction, out RaycastHit hit, distance))
{
Debug.Log(hit.collider.name);
}플레이어 이동을 만들 때 CharacterController와 Rigidbody 중 무엇을 기준으로 설계할지 비교합니다.
controller.Move(moveDirection * moveSpeed * Time.deltaTime);충돌과 레이캐스트를 정확하고 싸게 만들기 위한 Unity LayerMask와 Collision Matrix의 역할을 정리합니다.
[SerializeField] private LayerMask targetMask;
if (Physics.Raycast(origin, direction, out RaycastHit hit, 100f, targetMask))
{
Debug.Log(hit.collider.name);
}`NavMeshSurface`, `NavMeshAgent`, obstacle, link를 기준으로 Unity 내비게이션의 핵심 구조를 정리합니다.
using UnityEngine.AI;
agent.SetDestination(target.position);Unity Input System의 핵심 구조인 Action, Action Map, Input Action Asset, `PlayerInput` 관계를 정리합니다.
Input Action Asset
-> Action Map
-> Action
PlayerInput
-> 어떤 액션 자산을 현재 플레이어에 연결할지 관리`Tap`, `Hold` 같은 Interaction, control scheme, composite binding, rebinding을 Input System 실전 관점에서 정리합니다.
같은 Jump 액션이라도
- Tap: 짧게 눌렀을 때
- Hold: 일정 시간 눌렀을 때
를 다르게 해석할 수 있다3 cards
`Instantiate`, `Destroy`, parent 지정, pooling 선택까지 오브젝트 생성 수명주기를 한 흐름으로 정리합니다.
[SerializeField] private GameObject bulletPrefab;
[SerializeField] private Transform firePoint;
private void Fire()
{
GameObject bullet = Instantiate(bulletPrefab, firePoint.position, firePoint.rotation, firePoint.parent);
Destroy(bullet, 3f);
}Prefab asset과 scene instance의 차이, override/variant 구조, 런타임 생성 흐름을 함께 정리합니다.
Prefab asset
-> Scene instance
-> 필요하면 instance override
-> 다른 공통 설정이 필요하면 Prefab Variant총알, 이펙트처럼 자주 생성과 제거가 반복되는 오브젝트를 재사용하는 Unity 풀링 기본 패턴입니다.
GameObject item = pool[index];
item.SetActive(true);8 cards
`LoadScene`, `LoadSceneAsync`, `Additive`, bootstrap scene, data handoff까지 씬 로딩 전략을 함께 정리합니다.
using UnityEngine.SceneManagement;
public void LoadGameScene()
{
SceneManager.LoadScene("Game", LoadSceneMode.Single);
}씬이 바뀌어도 유지되어야 하는 매니저나 음악 오브젝트를 다룰 때 쓰는 `DontDestroyOnLoad` 기본 패턴입니다.
private void Awake()
{
DontDestroyOnLoad(gameObject);
}설정값, 공유 데이터, 프리팹 값 복제 문제를 `ScriptableObject`로 어떻게 분리할지 데이터 구조 관점에서 정리합니다.
[CreateAssetMenu(menuName = "Data/Weapon Data")]
public class WeaponData : ScriptableObject
{
public string weaponName;
public int damage;
}간단한 설정값과 진행 상태를 저장할 때 자주 쓰는 `PlayerPrefs` 기본 패턴과 한계를 정리합니다.
PlayerPrefs.SetFloat("music_volume", 0.8f);
float volume = PlayerPrefs.GetFloat("music_volume", 1f);
PlayerPrefs.Save();Unity에서 데이터를 씬 사이에 어떻게 넘기고 보존할지, `DontDestroyOnLoad`, `ScriptableObject`, `PlayerPrefs`, JSON 저장을 비교합니다.
씬 사이 임시 공유:
- ScriptableObject
- DontDestroyOnLoad
앱 재실행 뒤에도 유지:
- PlayerPrefs
- JSON save fileAddressables가 무엇을 해결하는지, `AssetReference`, 주소, 라벨, 비동기 로드의 핵심 mental model을 정리합니다.
[SerializeField] private AssetReferenceGameObject enemyRef;`LoadAssetAsync`, `InstantiateAsync`, `AsyncOperationHandle`, release 시점을 Addressables 수명주기 관점에서 정리합니다.
AsyncOperationHandle<GameObject> handle = enemyRef.LoadAssetAsync<GameObject>();Addressables를 로컬 로더가 아니라 배포 시스템으로 볼 때 필요한 profile, group, 원격 콘텐츠 흐름을 정리합니다.
Addressables group
-> local build path / remote build path
-> local load path / remote load path
-> profile로 환경별 값 전환15 cards
메뉴와 팝업 UI에서 자주 쓰는 `Button.onClick` 연결과 버튼 이벤트 처리 기본 흐름을 정리합니다.
[SerializeField] private Button startButton;
private void Awake()
{
startButton.onClick.AddListener(HandleStartClicked);
}상태 전환을 코드에서 제어하기 위해 `Animator`의 Bool, Float, Trigger 파라미터를 다루는 기본 패턴입니다.
animator.SetBool("IsRunning", true);
animator.SetTrigger("Attack");UGUI rebuild 범위를 줄이기 위해 static UI와 dynamic UI를 어떻게 나누는지 Canvas 분리 기준을 정리합니다.
Canvas
Static HUD Canvas
Dynamic Popup Canvas클릭 대상이 아닌 UI를 입력 검사에서 빼고, 보이지 않는 blocker를 줄이는 Graphic Raycaster 정리 카드입니다.
클릭 불필요 이미지:
- Raycast Target 해제Layout Group, Content Size Fitter, 수동 배치 중 무엇을 선택할지 UGUI 비용과 유지보수 기준으로 정리합니다.
VerticalLayoutGroup
ContentSizeFitter`SetActive`, `CanvasGroup`, alpha, `Canvas.enabled`를 언제 선택해야 하는지 UI 숨김 전략 기준을 정리합니다.
canvasGroup.alpha = visible ? 1f : 0f;
canvasGroup.interactable = visible;
canvasGroup.blocksRaycasts = visible;UGUI 배치의 핵심인 `RectTransform`, anchor, pivot, stretch, `Canvas Scaler`를 화면 대응 관점에서 정리합니다.
앵커가 기준점
피벗이 회전/스케일 중심
Canvas Scaler가 해상도 대응 규칙Cinemachine의 핵심 구조인 `Cinemachine Brain`, Virtual Camera, priority, blend를 카메라 시스템 관점에서 정리합니다.
Main Camera + Cinemachine Brain
<- 현재 live 상태인 Virtual Camera가 제어Cinemachine에서 Follow, Aim, damping, 화면 구도를 어떻게 잡는지 실제 카메라 감각 중심으로 정리합니다.
Body가 위치감을 만든다
Aim이 시선 구도를 만든다
damping이 카메라 반응 속도를 만든다Timeline Asset, Timeline instance, track, clip, binding, `PlayableDirector` 관계를 Unity 연출 시스템 관점에서 정리합니다.
Timeline Asset
-> track + clip 정의 저장
Playable Director
-> 씬 안에서 Timeline Asset을 재생하고 binding 관리Animation Track, Activation Track, Signal, Control Track을 중심으로 Timeline 컷신 구조를 어떻게 나누는지 정리합니다.
Animation Track -> 캐릭터 움직임
Audio Track -> 대사/효과음
Activation Track -> 오브젝트 on/off
Signal -> 코드나 이벤트 트리거UI Toolkit의 핵심 구조인 `VisualElement`, visual tree, UXML, USS, UI Builder 관계를 한 카드로 정리합니다.
UXML -> 구조
USS -> 스타일
C# -> 로직과 이벤트 연결새 UI를 만들 때 UI Toolkit과 uGUI 중 무엇이 더 잘 맞는지 구조, 워크플로우, 사용 사례 기준으로 비교합니다.
데이터 중심, 스타일 분리, 새 UI 설계
-> UI Toolkit
기존 프로젝트, 월드 스페이스 UI, 익숙한 워크플로우
-> uGUIShader Graph가 무엇을 해결하는지, URP/HDRP 전제, graph, node, property, material 흐름을 정리합니다.
Graph asset
-> node 연결
-> property 노출
-> material에서 값 조절Shader Graph에서 property와 keyword를 어떻게 노출하고, material 단위 변형을 어떻게 관리할지 정리합니다.
property를 Exposed로 열면
-> material inspector에서 조절 가능
keyword를 쓰면
-> 표현 분기를 material 단위로 제어 가능10 cards
CPU, GPU, 메모리, 렌더링 병목을 찾기 위한 Unity Profiler의 가장 기본적인 읽는 법을 정리합니다.
Window > Analysis > Profiler메모리 사용량, 스냅샷 비교, 메모리 예산 관점으로 Unity Memory Profiler를 읽는 기본 흐름입니다.
Window > Analysis > Memory Profiler
스냅샷 캡처 -> 비교변경 전후 프로파일 데이터를 나란히 비교해 성능 회귀를 잡는 Unity Profile Analyzer 기본 카드입니다.
프로파일 캡처 A
프로파일 캡처 B
Profile Analyzer에서 비교드로우콜과 오버드로우를 눈으로 추적하기 위한 Unity Frame Debugger의 핵심 사용 흐름을 정리합니다.
Window > Analysis > Frame Debugger
Enable목표 프레임 시간과 플랫폼 메모리 한도를 기준으로 성능 예산을 잡는 Unity 최적화 출발점을 정리합니다.
60 fps 목표 -> 프레임 예산 약 16.67 ms
30 fps 목표 -> 프레임 예산 약 33.33 ms물리 시뮬레이션 빈도와 스터터를 함께 고려해 `Fixed Timestep`과 `Maximum Allowed Timestep`을 조정하는 기본 카드입니다.
Edit > Project Settings > Time
Fixed Timestep = 0.02
Maximum Allowed Timestep = 0.3333333반복적인 Overlap과 Raycast 결과 수집에서 GC 할당을 줄이기 위한 Unity NonAlloc 쿼리 패턴입니다.
private readonly Collider[] results = new Collider[16];
int hitCount = Physics.OverlapSphereNonAlloc(transform.position, radius, results);소량 쿼리, NonAlloc, 대량 배치 `RaycastCommand` 중 무엇을 고를지 물리 쿼리 성능 관점에서 정리합니다.
NativeArray<RaycastCommand> commands = new(count, Allocator.TempJob);
NativeArray<RaycastHit> hits = new(count, Allocator.TempJob);
JobHandle handle = RaycastCommand.ScheduleBatch(commands, hits, 1);프레임 저하가 CPU-bound인지 GPU-bound인지 구분하고, draw call, SetPass, SRP Batcher, GPU Instancing을 어떻게 읽을지 정리합니다.
Profiler로 CPU 프레임 비용 확인
Frame Debugger로 draw call 흐름 확인빈 `Update`, `FixedUpdate`, `LateUpdate` 같은 Unity 메시지 함수도 비용이 될 수 있다는 점과, 이벤트·매니저·코루틴 대안을 정리합니다.
매 frame 필요 없으면
-> Update를 만들지 않는다
상태 변화 시에만 필요하면
-> event / callback
대상이 아주 많으면
-> 중앙 Update Manager
순차 대기 흐름이면
-> Coroutine11 cards
Unity 프로젝트를 오래 유지하기 쉽게 만드는 폴더 구조, 이름 규칙, 내부 자산 분리 원칙을 정리합니다.
Assets/
ProjectName/
Art/
Audio/
Materials/
Prefabs/
Scenes/
Scripts/
UI/
ThirdParty/Unity 프로젝트에서 `.meta` 파일을 왜 함께 관리해야 하는지, Preset으로 설정을 표준화하는 방법을 정리합니다.
Player.prefab
Player.prefab.meta수많은 `Update` 호출을 그대로 두지 않고 갱신 대상을 중앙에서 제어하는 Unity Update Manager 패턴입니다.
public interface IUpdatable
{
void Tick();
}`GetComponent`, 검색, 문자열 기반 lookup, 불필요한 할당을 어떻게 줄일지 핫패스 최적화 관점에서 정리합니다.
private Renderer cachedRenderer;
private void Awake()
{
cachedRenderer = GetComponent<Renderer>();
}개발 중에는 로그를 유지하되, 릴리스 빌드에서는 과도한 `Debug.Log` 비용을 줄이는 Unity 기본 전략입니다.
[System.Diagnostics.Conditional("ENABLE_LOG")]
public static void Log(object message)
{
Debug.Log(message);
}Animator, Material, Shader 속성 접근에서 문자열 대신 해시 ID를 캐싱해 쓰는 Unity 기본 패턴입니다.
private static readonly int SpeedId = Animator.StringToHash("Speed");
private static readonly int ColorId = Shader.PropertyToID("_BaseColor");스크립트 컴파일 범위를 줄이고 의존성을 분리하기 위한 Unity Assembly Definition 기본 개념을 정리합니다.
Runtime.asmdef
Editor.asmdef
Tests.asmdefUnity Test Framework의 역할과 함께 EditMode, PlayMode, 테스트 우선순위를 한 흐름으로 정리합니다.
using NUnit.Framework;
[Test]
public void AddScore_Increases_Total()
{
int score = 0;
score += 10;
Assert.AreEqual(10, score);
}오브젝트끼리 직접 참조하지 않고 메시지를 연결하기 위한 ScriptableObject 기반 이벤트 채널 패턴을 정리합니다.
[CreateAssetMenu(menuName = "Events/Game Event")]
public class GameEvent : ScriptableObject
{
public Action Raised;
public void Raise() => Raised?.Invoke();
}Unity 의존 코드는 얇게 두고, 핵심 로직은 순수 C#으로 분리해 테스트 가능성을 높이는 구조를 정리합니다.
MonoBehaviour
-> 입력, lifecycle, scene wiring
순수 C# class
-> 규칙, 계산, 상태 전이Unity 자동화를 붙일 때 공식 command line, `unity-cli`, `unity-mcp` 중 어떤 접근이 잘 맞는지 비교합니다.
공식 batchmode:
- CI 빌드, 테스트, executeMethod
unity-cli:
- 상태 확인, 콘솔 읽기, 짧은 에디터 제어
unity-mcp:
- 구조화된 tool call 기반 에이전트 워크플로우