# Unity 디버깅 도구 사용법

로봇 시뮬레이션 프로젝트에서 발생할 수 있는 다양한 문제를 효과적으로 해결하기 위해서는 강력한 디버깅 도구의 활용이 필수적이다. Unity는 개발자가 오류를 식별하고 수정하며 성능을 최적화할 수 있도록 다양한 디버깅 도구를 제공한다. 이 절에서는 Unity의 주요 디버깅 도구와 그 사용법에 대해 상세히 살펴보겠다.

#### Unity Console 창

Unity의 **Console 창**은 디버깅의 핵심 도구 중 하나로, 오류 메시지, 경고, 일반 로그 등을 실시간으로 확인할 수 있다.

* **오류 메시지(Error Messages)**: 스크립트 오류나 예외가 발생하면 Console 창에 빨간색으로 표시된다. 오류 메시지를 클릭하면 관련 스크립트의 해당 줄로 즉시 이동할 수 있어 빠른 수정이 가능한다.
* **경고 메시지(Warnings)**: 잠재적인 문제를 경고하는 메시지로, 노란색으로 표시된다. 예를 들어, 사용되지 않는 변수나 비효율적인 코드 사용 시 경고가 나타날 수 있다.
* **일반 로그(Logs)**: `Debug.Log`를 통해 출력되는 정보로, 흰색으로 표시된다. 코드의 흐름을 추적하거나 변수의 값을 확인하는 데 유용하다.

**Console 창 사용 예제**

```csharp
using UnityEngine;

public class DebugExample : MonoBehaviour
{
    void Start()
    {
        Debug.Log("시뮬레이션이 시작되었다.");
        Debug.LogWarning("이것은 경고 메시지이다.");
        Debug.LogError("이것은 오류 메시지이다.");
    }
}
```

위의 스크립트를 실행하면 Console 창에 각각의 메시지가 다른 색상으로 표시된다. 이를 통해 개발자는 코드의 상태를 실시간으로 모니터링할 수 있다.

#### Debug.Log를 이용한 로그 출력

`Debug.Log`, `Debug.LogWarning`, `Debug.LogError`는 코드 실행 중에 정보를 출력하는 데 사용된다. 이를 통해 변수의 값, 함수의 호출 여부 등을 쉽게 추적할 수 있다.

**변수 값 추적 예제**

```csharp
using UnityEngine;

public class VariableTracker : MonoBehaviour
{
    public float speed = 5.0f;

    void Update()
    {
        Debug.Log("현재 속도: " + speed);
        // 속도 변경 로직
    }
}
```

이 스크립트는 매 프레임마다 현재 속도를 Console 창에 출력하여, 속도가 예상대로 변경되고 있는지 확인할 수 있다.

#### 브레이크포인트 설정 및 스크립트 디버깅

Unity는 Visual Studio와 같은 외부 IDE와의 연동을 통해 브레이크포인트를 설정하고, 코드 실행을 단계별로 추적할 수 있는 기능을 제공한다.

**브레이크포인트 설정 방법**

1. **Visual Studio 연동**: Unity 에디터에서 `Edit > Preferences > External Tools`로 이동하여 외부 스크립팅 IDE를 Visual Studio로 설정한다.
2. **브레이크포인트 추가**: Visual Studio에서 디버깅할 스크립트를 열고, 중단하고 싶은 줄의 왼쪽 여백을 클릭하여 브레이크포인트를 추가한다.
3. **디버깅 시작**: Unity 에디터에서 `Attach to Unity` 버튼을 클릭하여 디버거를 연결한다. 이후 게임을 실행하면 브레이크포인트에서 실행이 중단되며, 변수의 현재 상태를 확인하고 코드 흐름을 단계별로 분석할 수 있다.

**디버깅 예제**

```csharp
using UnityEngine;

public class DebuggingExample : MonoBehaviour
{
    void Start()
    {
        int a = 10;
        int b = 20;
        int sum = a + b; // 여기에서 브레이크포인트 설정
        Debug.Log("합계: " + sum);
    }
}
```

브레이크포인트를 `int sum = a + b;` 줄에 설정하면, 해당 줄에서 코드 실행이 중단되어 `a`와 `b`의 현재 값을 확인할 수 있다.

#### Unity Profiler를 이용한 성능 분석

**Profiler**는 Unity의 성능을 분석하고 최적화할 수 있는 강력한 도구이다. CPU, GPU, 메모리 사용량 등을 실시간으로 모니터링할 수 있으며, 병목 현상을 식별하는 데 유용하다.

**Profiler 창 열기**

`Window > Analysis > Profiler`를 통해 Profiler 창을 열 수 있다. Profiler 창에서는 다양한 탭을 통해 상세한 성능 정보를 확인할 수 있다.

**주요 Profiler 탭**

* **CPU Usage**: CPU의 사용량과 각 함수의 실행 시간을 분석할 수 있다.
* **GPU Usage**: GPU의 성능을 모니터링하고, 그래픽 렌더링과 관련된 병목을 식별할 수 있다.
* **Memory**: 메모리 사용량을 추적하여 메모리 누수나 과도한 메모리 사용을 방지할 수 있다.
* **Rendering**: 렌더링 파이프라인의 각 단계를 분석하여 그래픽 성능을 최적화할 수 있다.

**Profiler 사용 예제**

```csharp
using UnityEngine;

public class ProfilerExample : MonoBehaviour
{
    void Update()
    {
        // 무거운 연산 예제
        for(int i = 0; i < 1000000; i++)
        {
            // 연산
        }
    }
}
```

이 스크립트를 실행하고 Profiler의 CPU Usage 탭을 확인하면, `Update` 함수 내의 루프가 CPU 사용량에 미치는 영향을 상세히 분석할 수 있다. 이를 통해 성능 저하의 원인을 파악하고 최적화할 수 있다.

#### Gizmos를 이용한 시각적 디버깅

**Gizmos**는 에디터 내에서 오브젝트의 상태를 시각적으로 표시하는 도구로, 디버깅 시 유용하게 활용된다. 예를 들어, 로봇의 센서 범위나 경로를 시각적으로 표현할 수 있다.

**Gizmos 사용 예제**

```csharp
using UnityEngine;

public class GizmoExample : MonoBehaviour
{
    public float detectionRadius = 5.0f;

    void OnDrawGizmos()
    {
        Gizmos.color = Color.red;
        Gizmos.DrawWireSphere(transform.position, detectionRadius);
    }
}
```

이 스크립트는 오브젝트의 위치를 중심으로 반경이 `detectionRadius`인 빨간색 와이어 구를 그려, 센서의 탐지 범위를 시각적으로 확인할 수 있게 한다.

#### Frame Debugger를 이용한 렌더링 과정 분석

**Frame Debugger**는 각 프레임의 렌더링 과정을 단계별로 분석할 수 있는 도구로, 그래픽 관련 문제를 디버깅하는 데 유용하다.

**Frame Debugger 사용 방법**

1. **Frame Debugger 활성화**: `Window > Analysis > Frame Debugger`를 통해 Frame Debugger 창을 엽니다.
2. **디버깅할 프레임 선택**: `Enable` 버튼을 클릭하여 디버깅을 시작하고, 분석할 프레임을 선택한다.
3. **렌더링 단계 분석**: Frame Debugger는 렌더링 파이프라인의 각 단계를 단계별로 표시하며, 각 단계에서 어떤 드로우 콜이 발생했는지 확인할 수 있다.

**Frame Debugger 예제**

Frame Debugger를 사용하여 특정 프레임에서 발생하는 드로우 콜을 분석하면, 불필요한 드로우 콜을 줄이거나 최적화할 수 있는 부분을 식별할 수 있다. 예를 들어, 동일한 메시지가 여러 번 드로우 콜되는 경우, 인스턴싱을 통해 최적화할 수 있다.

#### Memory Profiler를 이용한 메모리 사용 분석

**Memory Profiler**는 Unity 애플리케이션의 메모리 사용량을 상세히 분석할 수 있는 도구이다. 메모리 누수나 불필요한 메모리 사용을 발견하고 최적화하는 데 유용하다.

**Memory Profiler 창 열기**

`Window > Analysis > Memory Profiler`를 통해 Memory Profiler 창을 열 수 있다. 이 도구는 현재 애플리케이션의 메모리 상태를 스냅샷 형태로 캡처하여 분석할 수 있게 한다.

**메모리 스냅샷 캡처**

1. **스냅샷 찍기**: Memory Profiler 창에서 `Take Snapshot` 버튼을 클릭하여 현재 메모리 상태를 캡처한다.
2. **스냅샷 비교**: 여러 개의 스냅샷을 찍어 비교함으로써 메모리 사용량의 변화를 추적할 수 있다.
3. **메모리 할당 분석**: 스냅샷을 분석하여 어떤 객체가 메모리를 많이 사용하고 있는지, 불필요하게 메모리를 할당하고 있는지를 확인할 수 있다.

**메모리 사용 예제**

```csharp
using UnityEngine;

public class MemoryExample : MonoBehaviour
{
    void Start()
    {
        // 큰 텍스처 로드
        Texture2D largeTexture = new Texture2D(4096, 4096);
        // 메모리 할당 확인을 위해 텍스처 생성
        for(int y = 0; y < largeTexture.height; y++)
        {
            for(int x = 0; x < largeTexture.width; x++)
            {
                largeTexture.SetPixel(x, y, Color.white);
            }
        }
        largeTexture.Apply();
    }
}
```

이 스크립트를 실행하고 Memory Profiler를 통해 메모리 사용량을 확인하면, `largeTexture` 객체가 상당한 양의 메모리를 할당하고 있음을 알 수 있다. 이를 통해 메모리 최적화가 필요한 부분을 식별할 수 있다.

#### Deep Profiling을 이용한 상세 성능 분석

**Deep Profiling**은 Unity Profiler의 고급 기능으로, 함수 호출과 메서드 내부의 세부적인 성능 데이터를 제공한다. 이를 통해 더욱 정밀한 성능 최적화가 가능한다.

**Deep Profiling 활성화**

1. **Profiler 창 열기**: `Window > Analysis > Profiler`에서 Profiler 창을 엽니다.
2. **Deep Profiling 활성화**: Profiler 창 상단의 `Deep Profile` 체크박스를 활성화한다. 이 설정을 통해 모든 함수 호출과 그 내부의 세부 데이터를 수집할 수 있다.

**Deep Profiling 사용 예제**

```csharp
using UnityEngine;

public class DeepProfilerExample : MonoBehaviour
{
    void Start()
    {
        PerformHeavyComputation();
    }

    void PerformHeavyComputation()
    {
        for(int i = 0; i < 10000; i++)
        {
            // 복잡한 계산
            float value = Mathf.Sqrt(i) * Mathf.Sin(i);
        }
    }
}
```

Deep Profiling을 활성화한 상태에서 이 스크립트를 실행하면, `PerformHeavyComputation` 함수 내부의 각 계산 단계별로 세부적인 성능 데이터를 Profiler에서 확인할 수 있다. 이를 통해 특정 연산이 전체 성능에 미치는 영향을 정확히 분석할 수 있다.

#### Physics Debugging 도구

로봇 시뮬레이션에서는 물리 엔진과의 상호작용이 중요하다. Unity는 물리 엔진 디버깅을 위한 다양한 도구를 제공한다.

**Physics Debugger 창 열기**

`Window > Analysis > Physics Debugger`를 통해 Physics Debugger 창을 열 수 있다. 이 도구는 물리 엔진의 상태를 시각적으로 표시하여 충돌, 힘, 제약 조건 등을 분석할 수 있게 한다.

**Physics Debugger 사용 예제**

1. **충돌체 시각화**: Physics Debugger를 통해 모든 충돌체(Colliders)를 시각적으로 확인할 수 있다. 이를 통해 로봇의 충돌 범위를 정확히 파악하고, 예상치 못한 충돌을 발견할 수 있다.
2. **힘 및 운동량 확인**: 로봇에 작용하는 힘과 운동량을 실시간으로 모니터링하여 물리적 상호작용을 분석할 수 있다.
3. **제약 조건 분석**: 조인트(Joints)나 기타 물리적 제약 조건의 동작 상태를 점검하여 올바르게 설정되었는지 확인할 수 있다.

```csharp
using UnityEngine;

public class PhysicsDebugExample : MonoBehaviour
{
    public Rigidbody rb;

    void Start()
    {
        // 힘을 가해 로봇을 움직임
        rb.AddForce(new Vector3(0, 10, 0), ForceMode.Impulse);
    }
}
```

이 스크립트를 실행하고 Physics Debugger를 활성화하면, `Rigidbody`에 가해진 힘과 그로 인한 운동을 시각적으로 확인할 수 있다. 이를 통해 물리 상호작용이 예상대로 작동하는지 검증할 수 있다.

#### 애니메이션 디버깅 도구

로봇의 움직임이 자연스럽게 구현되었는지 확인하기 위해 애니메이션 디버깅 도구를 활용할 수 있다.

**Animation Debugger 창 열기**

`Window > Animation > Animation Debugger`를 통해 Animation Debugger 창을 열 수 있다. 이 도구는 애니메이션의 상태, 전환, 파라미터 등을 실시간으로 분석할 수 있게 한다.

**Animation Debugger 사용 예제**

1. **애니메이션 상태 확인**: 현재 재생 중인 애니메이션 상태를 확인하고, 올바른 애니메이션이 재생되고 있는지 점검할 수 있다.
2. **애니메이션 전환 분석**: 애니메이션 간 전환이 원활하게 이루어지는지, 불필요한 지연이나 끊김이 없는지 분석할 수 있다.
3. **파라미터 모니터링**: 애니메이션 파라미터의 값을 실시간으로 확인하여, 애니메이션 로직이 올바르게 작동하는지 검증할 수 있다.

```csharp
using UnityEngine;

public class AnimationDebugExample : MonoBehaviour
{
    public Animator animator;

    void Update()
    {
        if(Input.GetKeyDown(KeyCode.Space))
        {
            animator.SetTrigger("Jump");
        }
    }
}
```

이 스크립트를 실행하고 Animation Debugger를 활성화하면, `Jump` 트리거가 활성화될 때 애니메이션 상태가 어떻게 변하는지 실시간으로 확인할 수 있다. 이를 통해 애니메이션 전환이 원활하게 이루어지는지 검증할 수 있다.

#### 네트워크 디버깅 도구

멀티 로봇 시뮬레이션이나 원격 제어 로봇 시뮬레이션에서는 네트워크 통신이 중요한 역할을 한다. Unity는 네트워크 통신을 디버깅할 수 있는 도구도 제공한다.

**Network Profiler 사용**

1. **Network Profiler 활성화**: `Window > Analysis > Profiler`에서 Profiler 창을 열고, `Network` 탭을 선택한다.
2. **네트워크 활동 모니터링**: 네트워크를 통해 주고받는 데이터 패킷의 크기, 빈도, 지연 시간 등을 실시간으로 모니터링할 수 있다.

**Network Debugging 예제**

```csharp
using UnityEngine;
using UnityEngine.Networking;

public class NetworkDebugExample : MonoBehaviour
{
    void Start()
    {
        StartCoroutine(GetRequest("https://example.com/data"));
    }

    IEnumerator GetRequest(string uri)
    {
        UnityWebRequest webRequest = UnityWebRequest.Get(uri);
        yield return webRequest.SendWebRequest();

        if(webRequest.result == UnityWebRequest.Result.ConnectionError)
        {
            Debug.LogError("네트워크 오류: " + webRequest.error);
        }
        else
        {
            Debug.Log("응답: " + webRequest.downloadHandler.text);
        }
    }
}
```

이 스크립트를 실행하고 Network Profiler를 활성화하면, `GetRequest` 함수가 보내는 HTTP 요청과 응답의 세부 정보를 실시간으로 확인할 수 있다. 이를 통해 네트워크 통신의 효율성과 신뢰성을 검증할 수 있다.

#### 커스텀 디버깅 도구 개발

특정 로봇 시뮬레이션 요구사항에 맞추어 커스텀 디버깅 도구를 개발하는 것도 유용하다. Unity는 확장성이 높아, 필요에 따라 자체적인 디버깅 도구를 구현할 수 있다.

**커스텀 디버깅 UI**

Unity의 UI 시스템을 활용하여 실시간으로 로봇의 상태를 표시하거나, 특정 이벤트를 모니터링하는 커스텀 디버깅 패널을 만들 수 있다.

```csharp
using UnityEngine;
using UnityEngine.UI;

public class CustomDebugUI : MonoBehaviour
{
    public Text debugText;
    private float runtime;

    void Update()
    {
        runtime += Time.deltaTime;
        debugText.text = "Runtime: " + runtime.ToString("F2") + " seconds";
    }
}
```

이 스크립트는 화면에 실시간으로 게임의 런타임을 표시하는 간단한 디버깅 UI를 구현한다. 이를 통해 시뮬레이션의 진행 상태를 직관적으로 파악할 수 있다.

**로그 파일 작성**

실행 중 발생하는 로그를 파일로 저장하여, 후속 분석을 위해 활용할 수 있다.

```csharp
using UnityEngine;
using System.IO;

public class FileLogger : MonoBehaviour
{
    private StreamWriter writer;

    void Start()
    {
        writer = new StreamWriter("log.txt", true);
        writer.WriteLine("시뮬레이션 시작: " + System.DateTime.Now);
    }

    void Update()
    {
        writer.WriteLine("현재 시간: " + Time.time);
    }

    void OnApplicationQuit()
    {
        writer.WriteLine("시뮬레이션 종료: " + System.DateTime.Now);
        writer.Close();
    }
}
```

이 스크립트는 시뮬레이션 시작과 종료 시점, 그리고 매 프레임마다 현재 시간을 `log.txt` 파일에 기록한다. 이를 통해 시뮬레이션의 동작 기록을 남기고, 이후 분석에 활용할 수 있다.
