로그인게임하기
Unity C# 강좌

[Unity C# 9] partial, namespace, 에디터 메뉴, 코드를 나누고 정리하기

2026.10.14

Unity C# 강좌 · 9편

코드가 커지면 한 파일에 다 넣기 어렵고, 남이 만든 코드와 이름이 겹치기도 합니다. 이번 편에서는 클래스를 여러 파일로 나누는 partial, 같은 이름을 구분하는 namespace 와 using 별칭, 그리고 반복 작업을 줄이는 에디터 메뉴를 봅니다.

수업 정보

2024년 부산 콘텐츠 아카데미 퍼스널 트레이닝 수업에서 MyLesson Unity 실습 프로젝트의 Strategy_09_Partial.cs · Strategy_11_Namespace.cs · ContextMenu.cs 로 가르친 내용입니다. 수업은 다섯 단계로 나뉘고, 단계마다 코드가 조금씩 바뀝니다.

PARTIAL

한 클래스를 두 파일에

LobbyScene_1.cs수업 자료 최종3–26줄
public partial class LobbyScene : MonoBehaviour
{
    public LobbyScene()
    {
        OnConstruction();
    }

    public override string ToString()
    {
        string ret = GetName();
        return ret;
    }

    public void Destroy()
    {
        Program.WriteLine("Before OnLobbyDestroyed()");
        OnLobbyDestroyed();
        Program.WriteLine("After OnLobbyDestroyed()");
    }

    private partial void OnConstruction();

    partial void OnLobbyDestroyed();
}
LobbyScene_2.cs수업 자료 최종3–14줄
public partial class LobbyScene : MonoBehaviour
{
    private partial void OnConstruction()
    {
        Program.WriteLine("Lobby scene has been created.");
    }

    private string GetName()
    {
        return "LobbyScene";
    }
}

두 파일 모두 public partial class LobbyScene 입니다. 컴파일러는 둘을 합쳐 한 클래스로 만듭니다. 첫 파일의 ToString 이 둘째 파일의 GetName() 을 부를 수 있는 이유입니다. 자동으로 만들어지는 코드(UI 바인딩, 직렬화 코드)와 사람이 쓰는 코드를 나눌 때 많이 씁니다.

Strategy_09_Partial.cs수업 자료 최종3–8줄
public void Run()
{
    LobbyScene lobbyScene = new LobbyScene();
    Program.WriteLine("Scene Name: {0}", lobbyScene);
    lobbyScene.Destroy();
}
실행 결과게임 화면의 출력 창
Lobby scene has been created.
Scene Name: LobbyScene
Before OnLobbyDestroyed()
After OnLobbyDestroyed()
partial 메서드구현이 없으면
partial void OnLobbyDestroyed(); (접근 제한자 없음)호출 자체가 컴파일에서 지워진다. 그래서 Before 와 After 사이에 아무것도 없다
private partial void OnConstruction(); (C# 9, 접근 제한자 있음)구현이 반드시 있어야 한다. 없으면 컴파일 오류
MonoBehaviour 를 new 로

LobbyScene 은 MonoBehaviour 를 상속하는데 new LobbyScene() 으로 만들었습니다. 수업에서 partial 만 보여 주려고 그렇게 했고, Unity 는 이때 경고를 냅니다. 실제 컴포넌트는 AddComponent<LobbyScene>() 로 만들어야 합니다.

NAMESPACE

같은 이름의 GameObject 가 둘

NameSP1.csAssets/Source/FakeNamespace/NameSP1.cs1–10줄
namespace NameSP1
{
    public class GameObject
    {
        public override string ToString()
        {
            return "Fake GameObject";
        }
    }
}
Strategy_11_Namespace.cs수업 자료 1단계1–10줄
using NameSP1;
using UnityEngine;

public class Strategy_11_Namespace : Strategy
{
    public void Run()
    {
        // Error
        GameObject error = new GameObject();
    }

NameSP1 에도, UnityEngine 에도 GameObject 가 있습니다. 두 namespace 를 모두 using 하면, 컴파일러는 GameObject 가 어느 쪽인지 알 수 없어 오류(CS0104)를 냅니다.

Strategy_11_Namespace.cs수업 자료 2단계1–24줄#if 줄 생략
using FakeGameObject = NameSP1.GameObject;
using RealGameObject = UnityEngine.GameObject;

public class Strategy_11_Namespace : Strategy
{
    public void Run()
    {
        NameSP1.GameObject go1 = new NameSP1.GameObject();
        UnityEngine.GameObject ugo1 = new UnityEngine.GameObject();

        Program.WriteLine(go1);
        Program.WriteLine(ugo1);

        Program.WriteLine();

        FakeGameObject go2 = new FakeGameObject();
        RealGameObject ugo2 = new RealGameObject();

        Program.WriteLine(go2);
        Program.WriteLine(ugo2);
실행 결과게임 화면의 출력 창
Fake GameObject
New Game Object (UnityEngine.GameObject)

Fake GameObject
New Game Object (UnityEngine.GameObject)
방법 1

완전한 이름

NameSP1.GameObject, UnityEngine.GameObject 처럼 namespace 까지 적는다

방법 2

using 별칭

using FakeGameObject = NameSP1.GameObject; 로 이름을 따로 붙인다

PRAGMA

필요 없는 경고 끄기

Strategy_11_Namespace.cs수업 자료 3단계6–14줄#if 줄 생략
#pragma warning disable CS0414

public class Strategy_11_Namespace : Strategy
{
    private int noAffectedValue = 0;

쓰지 않는 private 필드에 값을 넣으면 컴파일러가 경고(CS0414)를 냅니다. #pragma warning disable CS0414 는 그 파일에서 이 경고를 끕니다. 경고는 대개 실수를 알려 주는 것이니, 끄는 범위는 좁게 잡고 이유를 주석으로 남기는 편이 좋습니다.

MENUITEM

에디터 메뉴로 경로 복사하기

수업 코드에는 Program.FindObject("/Canvas/Game/Start/Button (Play)") 처럼 오브젝트 경로가 자주 나옵니다. 손으로 적으면 틀리기 쉽습니다. 그래서 하이어라키에서 오브젝트를 고르고 메뉴를 누르면 경로를 클립보드에 복사하는 에디터 기능을 만들었습니다.

ContextMenu.cs수업 자료 최종7–29줄
[MenuItem("GameObject/*Copy Object Path", false, 0)]
static void CopyObjectPath()
{
    if (UnityEditor.Selection.activeGameObject == null) return;

    string path = "";
    Transform trans = UnityEditor.Selection.activeGameObject.transform;
    while (trans != null)
    {
        if (trans.gameObject.name != "Canvas(Environment)")
            if (path != "")
               path = trans.gameObject.name + "/" + path;
            else
               path = trans.gameObject.name;

        trans = trans.parent;

        if (trans != null && trans.parent != null && trans.parent.gameObject.name == "Canvas(Environment)")
            break;
    }

    GUIUtility.systemCopyBuffer = "/" + path;
}
ContextMenu.cs수업 자료 최종31–46줄
[MenuItem("Assets/*Copy Asset Path", false, 0)]
static void CopyAssetPath()
{
    if (UnityEditor.Selection.activeObject == null) return;

    string path = AssetDatabase.GUIDToAssetPath(Selection.assetGUIDs[0]).Replace("Assets/Resources/", string.Empty);

    int dotPos = path.LastIndexOf(".");

    if (dotPos >= 0)
    {
        path = path.Substring(0, dotPos);
    }

    GUIUtility.systemCopyBuffer = path;
}
  1. [MenuItem("GameObject/…")]하이어라키 우클릭 메뉴에 추가
  2. Selection.activeGameObject지금 고른 오브젝트
  3. parent 를 거슬러 오름경로 조립
  4. GUIUtility.systemCopyBuffer클립보드에 넣기

에셋 쪽 메뉴는 Project 창에서 고른 파일의 경로를 Resources.Load 에 바로 쓸 수 있는 모양(Resources/ 와 확장자를 뺀 경로)으로 복사합니다.

에디터 전용 코드

using UnityEditor 를 쓰는 코드는 게임 빌드에 들어갈 수 없습니다. 이 파일은 Editor 폴더에 두거나 #if UNITY_EDITOR 로 감싸야 빌드가 깨지지 않습니다. 클래스 이름 ContextMenu 는 Unity 의 [ContextMenu] 속성과 이름이 같으니 다른 이름이 더 안전합니다.

RETRO

돌아보며

이번 편에서 얻은 것

  • partial 로 한 클래스를 여러 파일에 나눈다. 구현 없는 partial void 는 호출째 사라진다
  • 이름이 겹치면 완전한 이름이나 using 별칭으로 구분한다
  • MenuItem 으로 반복 작업을 에디터 메뉴로 만든다

아쉬운 점

  • MonoBehaviour 를 new 로 만드는 예라 Unity 가 경고를 낸다
  • 에디터 코드가 일반 스크립트 폴더에 있어 빌드할 때 문제가 될 수 있다

정리

  1. partial 은 한 클래스를 여러 파일로 나눕니다. 자동 생성 코드와 손으로 쓴 코드를 나누는 데 씁니다.
  2. namespace 는 이름의 성(姓)입니다. 겹치면 완전한 이름이나 using 별칭으로 부릅니다.
  3. 반복 작업은 도구로 만드세요. MenuItem 몇 줄로 경로를 손으로 적는 실수를 없앴습니다.

다음 편에서는 어디서나 꺼내 쓰는 static 클래스로 플레이어 데이터를 저장하고, SQLite 데이터베이스에서 캐릭터 정보를 읽어 옵니다.

← 개발 노트 목록