[TIL] FixedUpdate, 기즈모
📕학습 개요
유니티 캠프 22일차.
다시 팀 프로젝트의 시간이 찾아왔다. 유니티로 유명한 게임의 레퍼런스 작품을 만드는 것이 이번 과제인데, 우리 조는 “궁수의 전설” 을 모작 게임을 만들기로 하였다.
📖학습 내용
FixedUpdate
오늘 들은 유니티 특강 내용 중, Unity Life Cycle에 대한 내용이 나왔다. Awake -> OnEnable -> Start 같이 주로 사용하는 함수들의 진행 순서는 대략적으로 알고 있었지만, FixedUpdate가 Update처럼 프레임률에 직접적으로 동기화되지 않고, 따로 관리된다는 사실을 처음 알게 되었다. 즉, FixedUpdate는 Update처럼 1번의 Life Cycle 마다 1번 호출되는 함수가 아니라 경우에 따라서는 0번, 혹은 2번 이상 호출될 수도 있다는 뜻이다.
이런 이유는 FixedUpdate가 Unity 엔젠의 내부 루프에 의해 관리되는 고정된 시간 간격으로 실행되는 함수 이기 때문이다. 이러한 이유 때문에 물리적인 계산을 처리해야 하는 코드는 Update 가 아닌 FixedUpdate에 작성하는 것이 정석이다. 프레임률에 따라 변하는 Time.delataTime 마다 적용하면 물리효과가 일정하지 않게 적용될 수도 있지만, Time.fixedDelataTime은 언제나 고정된 시간 간격을 사용하기 때문이다.
기즈모(Gizmo)
게임을 만들다 보면 투명한 오브젝트를 만드는 경우가 많다. 무기의 투사체 발사 지점이나, 몬스터의 스폰 지점을 만드는 경우가 이에 해당한다. 이때, 씬 뷰에서 투명한 오브젝트를 육안으로 쉽게 확인하고 싶을 때 기즈모(Gizmo)를 사용하면 매우 편리하다. 해당 오브젝트의 스크립트에 OnDrawGizmos 또는 OnDrawGizmosSelected 함수를 추가해주면 된다. 기즈모의 모양, 색깔, 크기 등 또한 간단하게 관리할 수 있다.
OnDrawGizmos
- 게임 오브젝트가 선택되었는지 여부와 관계없이 항상 씬 뷰에 기즈모를 그린다.
OnDrawGizmosSelected
- 해당 게임 오브젝트가 에디터에서 선택되었을 때만 기즈모를 그린다.
아래 코드는 몬스터의 스폰 반경을 구 모양으로 표시해주는 예제 코드이다.
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor; // Handles.Label을 사용하기 위해 필요
#endif
public class MonsterSpawnPoint : MonoBehaviour
{
// 인스펙터에서 설정할 수 있는 변수들
public Color gizmoColor = Color.red;
public float gizmoRadius = 0.5f;
public string iconName = "MonsterIcon.png"; // 예시 아이콘, 실제 파일이 있어야 함
// OnDrawGizmos는 항상 호출됨
void OnDrawGizmos()
{
// 기본 위치 기즈모
Gizmos.color = gizmoColor;
Gizmos.DrawSphere(transform.position, gizmoRadius);
//아이콘도 표시 가능
Gizmos.DrawIcon(transform.position, iconName, true); // true는 아이콘이 카메라를 향하도록 함
// 스폰 지점 이름 표시 (에디터 전용)
#if UNITY_EDITOR
Handles.color = gizmoColor;
// 이름이 너무 길면 잘릴 수 있으니 게임오브젝트 이름을 간결하게 하는 것이 좋습니다.
Handles.Label(transform.position + Vector3.up * (gizmoRadius + 0.2f), gameObject.name);
#endif
}
// OnDrawGizmosSelected는 이 오브젝트가 선택되었을 때만 호출됨
void OnDrawGizmosSelected()
{
Gizmos.color = Color.yellow; // 선택되었을 때는 노란색으로 강조
Gizmos.DrawWireSphere(transform.position, gizmoRadius * 1.2f); // 약간 더 큰 와이어 스피어
}
}
그런데 기즈모가 그려주는 도형은 입체적인 모양이라 2D 뷰에서는 조금 어색하게 보이는 문제가 생겼다. 이를 해결하기 위해 UnityEditor.Handles 네임스페이스에 있는 2D 도형 그리기 기능을 사용해 보았다.
#if UNITY_EDITOR
using UnityEditor;
#endif
public class MonsterSpawnPoint : MonoBehaviour
{
[Header("Spawn Point Settings")]
[SerializeField] private float spawnAreaRadius = 3f;
private Color spawnAreaColor = Color.red;
public GameObject SpawnMonster(GameObject monsterPrefab)
{
// 스폰 영역 내 랜덤 위치에서 몬스터 생성
Vector2 randomCirclePoint = Random.insideUnitCircle * spawnAreaRadius;
Vector3 spawnPoint = new Vector3(
transform.position.x + randomCirclePoint.x,
transform.position.y + randomCirclePoint.y,
transform.position.z);
return Instantiate(monsterPrefab, spawnPoint, Quaternion.identity);
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
Handles.color = new Color(spawnAreaColor.r, spawnAreaColor.g, spawnAreaColor.b, 0.2f); ;
Handles.DrawSolidDisc(transform.position, Vector3.forward, spawnAreaRadius);
}
#endif
}
주의 : UnityEditor.Handles 를 사용하는 코드는 에디터 전용이므로, 스크립트 상단에 using UnityEditor;를 추가하고, 해당 코드를 #if UNITY_EDITOR와 #endif 전처리기로 감싸야 빌드 시 오류가 발생하지 않는다고 한다.
몬스터 스폰 영역에 빨간 원이 잘 표시되는 모습이다.
🏁오늘 배운 핵심 내용 정리
FixedUpdate함수는Update함수와 별개의 고정된 실행 주기를 가진다.- 따라서 물리적 연산은
FixedUpdate에서 해주는 것이 정석. - 씬 뷰의 가독성을 높이기 위해 기즈모를 적극적으로 활용해보자.
댓글남기기