일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 |
- working set
- Private Bytes
- URP로 변경
- Windows Build
- 3d
- 개인 바이트
- Rim Light
- ASW(Application SpaceWarp)
- OculusMotionVectorPass
- Cell Shader
- Specular
- 벡터
- URP
- Cartoon Rendering
- 작업 집합
- ColorGradingLutPass
- AppSW
- 게임 수학
- C언어
- VR
- 가상 바이트
- Cell Look
- 메모리 누수
- Virtual Byte
- 프로그래밍 기초
- Three(Two) Tone Shading
- Toon Shader
- Today
- Total
WinCNT
유니티 프로퍼티의 할당 체크를 == null외의 방법으로 해보기 본문
서론
유니티의 게임 오브젝트, 컴포넌트에 대한 == null 체크가 무겁다는 것은 Rider조차 알고 있는 사실
몰라도 Rider가 알려주는 사실이라도고 한다
그렇다고 Null 체크를 아예 안 할 수도 없고, 남의 코드를 최적화하는 상황에 처해서, 굳이 여기서 Null 체크 안 해도 같은데…라고 생각해도, 코드를 마음대로 고칠 수 없어서 대안책만 제시할 수 있는 상황일 수도 있다지금 필자의 상황
이번에는 그 대안책을 조사하다가 알게 된 내용을 정리하려고 한다
Fake Null, ReferenceEquals() 등의 이야기는 안 합니다
Fake Null 등에 대해서는 이미 좋은 글이 많아서 밑의 참고 사이트에 정리해봤다
알아두면 좋은 내용이었지만 아쉽게도 현재 필자의 상황과는 맞지 않았다
그래서 Fake Null, ReferenceEquals()에 대해서는 생략하기로 한다
문제의 코드
문제의 코드를 간단히 나타내면 다음과 같다
using UnityEngine;
public class UnityNullTest : MonoBehaviour
{
[SerializeField] public Transform target = null;
private Transform trans;
void Start()
{
trans = transform;
}
private void LateUpdate()
{
if (target == null)
return;
trans.position = target.position;
}
}
특정 게임 오브젝트의 Transform을 프로퍼티로 가지고 있고, 매 LateUpdate()마다 그 Transfrom이 있는지 체크하는 코드이다
이러한 경우, 참조하는 Transfrom이 할당되어 있는지 아닌지는 ReferenceEquals()나 is null로 체크할 수 없다
애초에 Transform 컴포넌트는 유니티에서 Destroy()로 파괴할 수도 없고, 프리팹으로 이미 할당(…)되어서 할당 안 됐을 때를 Update에서 고려할 필요가 없어 보였고, Target이란 게임 오브젝트는 기기의 카메라와 관련된 매우 중요한 오브젝트라 딱히 동적으로 지울 이유도 안 보여서, 이거 체크가 필요한가?라는 의문이 들기도 했다
UnassignedReferenceException와 MissingReferenceException
그래도 실제로 어떠한 일들이 일어지는지 궁금해서 게임 실행 중에 Target 게임 오브젝트를 빼거나 지우거나 해봤다
그러자 다음과 같은 에러들이 표시됐다
처음에는 어떻게 하지 고민했는데, 어렵게 생각할 거 없이 Exception이니 그냥 예외 처리를 하자는 결론에 도달했다
성능 비교
문제는 예외 처리를 해서 성능이 떨어진다면 본말전도라는 것
그래서 이번 기회에 비슷한 처리들의 속도를 비교해보고자 했다
(일단 ReferenceEquals()나 is null도 포함)
테스트에 사용한 코드는 다음과 같다
using System.Diagnostics;
using UnityEngine;
public class UnityNullTest : MonoBehaviour
{
[SerializeField] public Transform target = null;
private Stopwatch sw = null;
private Transform trans;
void Start()
{
trans = transform;
sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
if (!(target is { } && target))
{
return;
}
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("is { } && Check : " + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
if (!target)
{
return;
}
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("Implicit Null Check : " + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
if (target == null)
{
return;
}
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("== null : " + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
if (ReferenceEquals(target, null))
{
return;
}
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("ReferenceEquals() : " + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
if (target is null)
{
return;
}
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("is null : " + sw.Elapsed);
sw.Reset();
sw.Start();
try
{
for (int i = 0; i < 100000000; ++i)
{
trans.position = target.position;
}
}
catch (UnassignedReferenceException e)
{
return;
}
catch (MissingReferenceException e)
{
return;
}
sw.Stop();
UnityEngine.Debug.Log("Try Catch : " + sw.Elapsed);
sw.Reset();
sw.Start();
for (int i = 0; i < 100000000; ++i)
{
trans.position = target.position;
}
sw.Stop();
UnityEngine.Debug.Log("No Check : " + sw.Elapsed);
sw.Reset();
}
}
측정 결과
다행히 Try Catch가 == null 보다 좋게 나왔다만세!
이걸로 일을 저쪽에 넘길 수 있어…
마무리
참고 사이트의 말대로 은탄환은 없다는 말은 사실인 것 같다
좀 있으면 좋겠다 진짜로
그리고 해당 글은 어디까지나 발버둥에 가까웠으며, 실제 릴리스로 빌드했을 때 최적화가 이루어질 수도 있으므로, 이러한 삽질은 필요 없다는 이야기도 들었다(...진짜?)
이래저래 부족한 것이 많지만, 아무튼 이번 글은 이정도로 마무리 지으려고 한다
참고 사이트
Unity C# > 유니티 오브젝트의 fake null
Unity C# > 유니티 오브젝트의 fake null
🚀 Destroy
ansohxxn.github.io
유니티 오브젝트의 null 비교 시 유의사항
다음글: 유니티 오브젝트의 null 비교 시 유의사항 2
overworks.github.io
유니티 오브젝트의 null 비교 시 유의사항 2
이전글: 유니티 오브젝트의 null 비교 시 유의사항
overworks.github.io
Unity에서의 Null Comparison
Comparison to 'null' is expensive Rider 에디터에서 유니티 오브젝트의 Null 비교 '=='연산자를 통해 수행하려 하면 다음과 같은 안내가 나온다. 단순히 null을 비교하는데 왜 이런 안내가 뜰까?? 이유는 UnityE
tsyang.tistory.com
Rider's new way to check for null object
Rider's new way to check for null object
Let's say we are building a game in Unity, and every single frame we want to check whether or not the player is null. I know this is NOT optimal, but I just want to show an example to state my ques...
stackoverflow.com
UnassignedReferenceException and Null-Check - Unity Answers
UnassignedReferenceException and Null-Check
I often check in Start()-method, if all needed references are set in inspector. So i wrote a utility method, for this like this: public static void WarnIfNull(object o, string name) { if (o == null) { Debug.LogWarning(name + " is NULL"); ... so i can use i
discussions.unity.com
'Unity > Unity 관련' 카테고리의 다른 글
Unity Assembly Definition를 설정해보기 (0) | 2023.08.21 |
---|---|
유니티 간단 팁) 빌드 리포트(Build Report) 보는 법! (0) | 2023.08.08 |
Unity에서 Slack으로 파일 업로드 해보기 (0) | 2023.07.27 |
유니티의 UI 시스템(uGUI)에 대해 조금 알아보기 (0) | 2023.07.24 |
유니티의 Bakery(라이트 맵 생성 에셋) 적용기 (0) | 2023.06.20 |