# Profiler 모듈 세부 정보 패널 생성

> Customize the module details panel to display specific data about your application.

모듈을 선택하면 모듈 세부 정보 패널이 [프로파일러 창](/engine/6000.0/manual/analysis/profiler/window-reference.md) 하단에 표시됩니다. 이 섹션을 커스터마이즈하여 모듈과 관련된 추가 세부 정보를 표시하거나 성능 데이터의 커스텀 시각화를 표시할 수 있습니다.

Profiler 모듈에 대한 모듈 세부 정보 패널을 생성하려면 다음을 수행합니다.

* [모듈 세부 정보 패널 컨트롤러 스크립트를 생성](#create-details-view-controller)하여 커스텀 모듈 세부 정보 패널을 렌더링합니다.
* [Profiler 모듈 스크립트를 생성](#connect-details-view-controller)하여 컨트롤러를 Profiler 모듈에 연결합니다.

## 모듈 세부 정보 패널을 제어하는 스크립트 생성

[`ProfilerModuleViewController`](/engine/6000.0/script-reference/unity-profiling-editor/profiler-module-view-controller.md) 기본 클래스를 사용하여 프로파일러 창의 모듈 세부 정보 패널을 커스터마이즈합니다. 이렇게 하려면 특정 모듈을 선택할 때 모듈 세부 정보 패널에 표시되는 사항을 제어하는 스크립트를 생성합니다.

스크립트는 다음을 수행해야 합니다.

* 기본 생성자 `base(profilerWindow)`를 호출하는 뷰 컨트롤러에 대한 공용 생성자를 정의합니다.
* `CreateView`를 오버라이드하여 커스텀 모듈 세부 정보 패널을 빌드합니다.

예시:

```lang-csharp

 public class CustomDetailsViewController : ProfilerModuleViewController
 {   
    public CustomDetailsViewController(ProfilerWindow profilerWindow) : base(profilerWindow) { }

    protected override VisualElement CreateView()
    {
        // Create your UI.
    }
}
```

### 모듈 세부 정보 패널 컨트롤러 스크립트 예

다음 스크립트 예시는 텍스트를 표시하는 모듈 세부 정보 패널에 단일 레이블을 렌더링하는 모듈 세부 정보 패널 컨트롤러를 생성합니다.


**Frame:**
![](/api/media?file=/engine/6000.0/media/images/Profiler_tank_details_basic.png)

스크립트 예시는 다음을 수행합니다.

* 캡처하려는 값을 표시할 레이블을 정의하고 생성하며 이 레이블을 모듈 세부 정보 패널에 추가합니다.
* 모듈 세부 정보 패널을 제어하는 생성자를 정의하고 `CreateView`를 사용하여 커스텀 모듈 세부 정보 패널을 빌드합니다.
* 레이블을 현재 프레임의 데이터로 채우고 각 프레임 이후에 레이블을 업데이트합니다.
* 모듈 세부 정보 패널에 표시할 수 있는 문자열로 카운터 값을 가져옵니다.
* 모듈 세부 정보 패널에 표시할 텍스트를 지정하고 각 프레임마다 자동으로 업데이트하도록 프로파일러에 지시합니다.

```lang-csharp
 using UnityEditor;
 using UnityEditorInternal;
 using Unity.Profiling.Editor;
 using UnityEngine.UIElements;
 
 public class TankEffectsDetailsViewController : ProfilerModuleViewController
 {
    // Define a label, which will display the total particle count for tank trails in the selected frame.
    Label m_TankTrailParticleCountLabel;

    // Define a constructor for the view controller, which calls the base constructor with the Profiler Window passed from the module.
    public TankEffectsDetailsViewController(ProfilerWindow profilerWindow) : base(profilerWindow) { }
    {
        var view = CreateView();

        // Populate the view with the current data for the selected frame. 
        ReloadData();

        // Be notified when the selected frame index in the Profiler Window changes, so we can update the label.
        ProfilerWindow.SelectedFrameIndexChanged += OnSelectedFrameIndexChanged;

        return view;
    }
	
    protected virtual VisualElement CreateView()
    {
        var view = new VisualElement();
		
        // Create the label and add it to the view.
        m_TankTrailParticleCountLabel = new Label() { style = { paddingTop = 8, paddingLeft = 8 } };
        view.Add(m_TankTrailParticleCountLabel);
    }
	

    // Override Dispose to do any cleanup of the view when it is destroyed. This is a standard C# Dispose pattern.
    protected override void Dispose(bool disposing)
    {
        if (!disposing)
            return;

        // Unsubscribe from the Profiler window event that we previously subscribed to.
        ProfilerWindow.SelectedFrameIndexChanged -= OnSelectedFrameIndexChanged;

        base.Dispose(disposing);
    }

    protected virtual void ReloadData()
    {
        // Retrieve the TankTrailParticleCount counter value from the Profiler as a formatted string.
        var selectedFrameIndexInt32 = System.Convert.ToInt32(ProfilerWindow.selectedFrameIndex);
        var value = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndexInt32, GameStatistics.TanksCategory.Name, GameStatistics.TankTrailParticleCountName);

        // Update the label's text with the value.
        m_TankTrailParticleCountLabel.text = $"The value of '{GameStatistics.TankTrailParticleCountName}' in the selected frame is {value}.";
    }

    void OnSelectedFrameIndexChanged(long selectedFrameIndex)
    {
        // Update the label with the current data for the newly selected frame.
        ReloadData();
    }
}
```

**팁:** Unity의 UI 툴킷을 사용하여 모듈 세부 정보 패널에 대한 커스텀 UI를 빌드할 수 있습니다. 자세한 내용은 [UI 툴킷](/engine/6000.0/manual/working-in-unity/uitoolkits/uielements.md)을 참조하십시오.

다음 예시 이미지는 커스텀 [Adaptive Performance](https://docs.unity3d.com/Packages/com.unity.adaptiveperformance@latest?subfolder=/manual/index.html) 모듈에 속한 커스텀 모듈 세부 정보 패널을 보여 줍니다.


**Frame:**
![](/api/media?file=/engine/6000.0/media/images/Adaptive_performance_Profiler.png)

## Profiler 모듈에 커스텀 모듈 세부 정보 패널 연결

커스텀 모듈 세부 정보 패널을 표시하려면 Profiler 모듈을 선택할 때 모듈 세부 정보 패널 컨트롤러를 인스턴스화해야 합니다. 이렇게 하려면 `CreateDetailsViewController`를 오버라이드하여 새 모듈 세부 정보 패널 컨트롤러를 생성하고 렌더링합니다. 그런 다음 Unity는 모듈의 세부 정보 패널을 표시할 때 이 메서드를 호출합니다.

다음 코드 예시는 `TankEffectsProfilerModule`이라는 모듈에 대한 커스텀 모듈 세부 정보 패널을 인스턴스화합니다.

```lang-csharp

using Unity.Profiling.Editor;

[System.Serializable]
[ProfilerModuleMetadata("Tank Effects")]
public class TankEffectsProfilerModule : ProfilerModule
{
   static readonly ProfilerCounterDescriptor[] k_Counters = new ProfilerCounterDescriptor[]
   {
       new ProfilerCounterDescriptor(GameStatistics.TankTrailParticleCountName, GameStatistics.TanksCategory),
       new ProfilerCounterDescriptor(GameStatistics.ShellExplosionParticleCountName, GameStatistics.TanksCategory),
       new ProfilerCounterDescriptor(GameStatistics.TankExplosionParticleCountName, GameStatistics.TanksCategory),
   };

   public TankEffectsProfilerModule() : base(k_Counters) { }

   public override ProfilerModuleViewController CreateDetailsViewController()
   {
       return new TankEffectsDetailsViewController(ProfilerWindow);
   }
}
```

## 모듈 세부 정보 패널에서 추가 카운터 시각화

모듈의 차트 뷰에 포함되지 않은 추가 [프로파일러 카운터](/engine/6000.0/manual/analysis/profiler/adding-information-code/intro.md)를 표시할 수 있습니다. 선택한 프레임에 대한 추가 데이터를 표시하려는 경우에 유용합니다.

프로파일러는 모듈이 활성화되면 모듈의 차트 뷰에 속하는 모든 카운터의 카테고리를 자동으로 캡처합니다. 추가 카운터를 캡처하려면 모듈이 활성화될 때 프로파일러에 특정 카테고리를 캡처하도록 지시하는 스크립트를 작성합니다.

예를 들어 다음 스크립트는 `autoEnabledCategoryNames` 생성자 인자를 사용하여 `Scripts` 및 `Memory` 카테고리를 지정합니다. 이 스크립트는 모듈이 활성화된 경우 다음 카테고리를 활성화합니다.

```lang-csharp

using Unity.Profiling;
using Unity.Profiling.Editor;

[System.Serializable]
[ProfilerModuleMetadata("Tank Effects & Memory")]
public class TankEffectsAndMemoryProfilerModule : ProfilerModule
{
  static readonly ProfilerCounterDescriptor[] k_Counters = new ProfilerCounterDescriptor[]
  {
      new ProfilerCounterDescriptor(GameStatistics.TankTrailParticleCountName, ProfilerCategory.Scripts),
      new ProfilerCounterDescriptor(GameStatistics.ShellExplosionParticleCountName, ProfilerCategory.Scripts),
      new ProfilerCounterDescriptor(GameStatistics.TankExplosionParticleCountName, ProfilerCategory.Scripts),
  };

  // Enable the ProfilerCategory.Scripts and ProfilerCategory.Memory categories when the module is active.
  static readonly string[] k_AutoEnabledCategoryNames = new string[]
  {
      ProfilerCategory.Scripts.Name,
      ProfilerCategory.Memory.Name
  };

  public override ProfilerModuleViewController CreateDetailsViewController()
  {
      return new TankEffectsAndMemoryDetailsViewController(ProfilerWindow);
  }
  
  // Pass the auto-enabled category names to the base constructor.
  public TankEffectsProfilerModule() : base(k_Counters, autoEnabledCategoryNames: k_AutoEnabledCategoryNames) { }
}
```

다음 예시 코드는 빌트인 [메시 메모리 프로파일러 카운터](/engine/6000.0/manual/analysis/profiler/counters-reference.md#memory)를 `TankTrailParticleCount`와 함께 표시합니다.

```lang-csharp
using UnityEditor;
using UnityEditorInternal;
using Unity.Profiling.Editor;
using UnityEngine.UIElements;

public class TankEffectsAndMemoryDetailsViewController : TankEffectsDetailsViewController
{
   // Define a label, which will display the total mesh memory in the selected frame
   Label m_MeshMemoryLabel;
   
   protected override VisualElement CreateView()
   {
       var view = base.CreateView();
   	
       // Create the label and add it to the view.
       m_MeshMemoryLabel = new Label() { style = { paddingTop = 8, paddingLeft = 8 } };
       view.Add(m_MeshMemoryLabel);
   }
   
   protected override void ReloadData()
   {
       base.ReloadData();
   	
       // Retrieve the Mesh Memory counter value from the Profiler as a formatted string.
       var selectedFrameIndexInt32 = System.Convert.ToInt32(ProfilerWindow.selectedFrameIndex);
       var value = ProfilerDriver.GetFormattedCounterValue(selectedFrameIndexInt32, ProfilerArea.Memory, "Mesh Memory");

       // Update the label's text with the value.
       m_MeshMemoryLabel.text = $"The value of 'Mesh Memory' in the selected frame is {value}.";
   }
}
```

## 추가 리소스

* [Profiler 모듈 소개](/engine/6000.0/manual/analysis/profiler/collect-data/visualizing-data/modules-introduction.md)
* [Profiler 모듈 에디터 레퍼런스](/engine/6000.0/manual/analysis/profiler/collect-data/visualizing-data/customizing/module-editor.md)
* [Profiler 모듈 세부 정보 패널 생성](/engine/6000.0/manual/analysis/profiler/collect-data/visualizing-data/customizing/details-view.md)
* [코드에 프로파일링 정보 추가](/engine/6000.0/manual/analysis/profiler/adding-information-code.md)
