유니티 툴바를 이용하여 씬 전환을 편하게 하자! #Scene Swithcer

 

개발을 하다 보면  Project 폴더 안에 존재하는 Scenes을 찾아서 일일이 클릭하여 해당 씬으로 가야 하는
번거로움 및 불편함이 존재합니다.

 

불편함을 줄이고자 Rainbow Folders 에셋을 구매해봤으나 해당 Scene을 찾고 여는데에 있던 불편함은 그대로였습니다.

 

물론, Prefab이나 Scripts폴더 등 각 폴더들을 구분되게 해준다는 점에서 훌륭한 에셋입니다!

 

Unity Asset - Rainbow Folders 2 후기

가격 및 후기 가격은 20달러로 약 3만원 정도 합니다!(26,390원) 별점과 관심도는 좋은 편에 속합니다! Asset Setting 에셋을 임포트 해봅니다! Project Setting 탭에 들어가보시면 Rainbow Folders 탭이 생긴 것

wlsdn629.tistory.com


Toolbar Import하기

 

GitHub - marijnz/unity-toolbar-extender: Extend the Unity Toolbar with your own Editor UI code.

Extend the Unity Toolbar with your own Editor UI code. - GitHub - marijnz/unity-toolbar-extender: Extend the Unity Toolbar with your own Editor UI code.

github.com

위 깃허브 링크에 들어가서 프로젝트를 다운로드합니다.

 

 

 

Package Manager의 모습은 에디터 버전에 따라 다를 수 있습니다.

현재 예시를 들고 있는 에디터의 버전은 2022.3.21f1 입니다.


임포트 및 샘플 예제를 다운로드하면 위와 같이 [Sampled] - [Toolbar Extender]... - [Scene swticher..] 폴더가 생긴 것을 확인할 수 있습니다.

폴더가 생김과 동시에 에디터 상단에 2가지 버튼이 생긴 것을 확인할 수 있습니다.

(저는 수정을 한 상태라 2개의 버튼이 아닌 4개의 버튼이 존재하며 버튼의 이름도 다릅니다. '주의' 바랍니다!)

 

자기 프로젝트에 맞게 수정하시면 됩니다.

 

저는 글씨체가 깨져서 ToolbarStyles부분을 빼버렸습니다!

using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace UnityToolbarExtender.Examples
{
   static class ToolbarStyles
   {
      public static readonly GUIStyle commandButtonStyle;

      static ToolbarStyles()
      {
         commandButtonStyle = new GUIStyle("Command")
         {
            fontSize = 16,
            alignment = TextAnchor.MiddleCenter,
            imagePosition = ImagePosition.ImageAbove,
            fontStyle = FontStyle.Bold
         };
      }
   }

   [InitializeOnLoad]
   public class SceneSwitchLeftButton
   {
      static SceneSwitchLeftButton()
      {
         ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
      }
      
      static void OnToolbarGUI()
      {
         GUILayout.FlexibleSpace();

         if(GUILayout.Button(new GUIContent("StartUp", "StartUp Scene"))) 
         {
            SceneHelper.OpenScene("StartUp");
         }

         if(GUILayout.Button(new GUIContent("MainMenu", "MainMenu Scene")))
         {
            SceneHelper.OpenScene("MainMenu");
         }
         
         if(GUILayout.Button(new GUIContent("Lobby", "Lobby Scene")))
         {
            SceneHelper.OpenScene("Lobby");
         }
         
         if(GUILayout.Button(new GUIContent("MainGame", "MainGame Scene")))
         {
            SceneHelper.OpenScene("MainGame");
         }
      }
   }
   
   static class SceneHelper
   {
      public static void OpenScene(string name)
      {
         var saved = EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
         if (saved)
         {
            _ = EditorSceneManager.OpenScene($"Assets/Scenes/{name}.unity");
         }
      }
   }
}

위 스크립트처럼 바꾼 이유는 해당 Scene 버튼을 눌렀을 때 자동으로 실행되지 않길 원했기 때문입니다.


Scene Button 크기를 Text크기에 맞게 동적으로 변하게 하기

string startButtonText = "StartUp";
GUIContent startButtonContent = new GUIContent(startButtonText);
Vector2 startButtonSize = GUI.skin.button.CalcSize(startButtonContent);
if (GUILayout.Button(startButtonContent, GUILayout.Width(startButtonSize.x), GUILayout.Height(startButtonSize.y)))
{
	 SceneHelper.StartScene("StartUp");
}

 

코드는 OnToolbarGUI 함수내에 작성하시면 됩니다.

 

Text 크기에 맞게 버튼 크기를 늘리기


사용자별로 Scene 관리 기능 추가

using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using System.Collections.Generic;

namespace UnityToolbarExtender.Examples
{
    static class ToolbarStyles
    {
        public static readonly GUIStyle commandButtonStyle;

        static ToolbarStyles()
        {
            commandButtonStyle = new GUIStyle("Command")
            {
                fontSize = 16,
                alignment = TextAnchor.MiddleCenter,
                imagePosition = ImagePosition.ImageAbove,
                fontStyle = FontStyle.Bold
            };
        }
    }

    [InitializeOnLoad]
    public class SceneSwitchLeftButton
    {
        static Dictionary<string, string> userScenes = new Dictionary<string, string>
        {
            {"진우", "Test1"},
            {"지은", "Test2"},
            {"예진", "Test3"},
        };
        
        static string selectedUser;

        static SceneSwitchLeftButton()
        {
            ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
        }

        static void OnToolbarGUI()
        {
            GUILayout.FlexibleSpace();

            if(GUILayout.Button(new GUIContent("StartUp", "StartUp Scene"))) 
            {
                SceneHelper.OpenScene("StartUp");
            }

            if(GUILayout.Button(new GUIContent("MainMenu", "MainMenu Scene")))
            {
                SceneHelper.OpenScene("MainMenu");
            }

            if (GUILayout.Button(selectedUser ?? "사용자 선택", EditorStyles.popup))
            {
                var menu = new GenericMenu();
                foreach (var user in userScenes.Keys)
                {
                    menu.AddItem(new GUIContent(user), false, OnUserSelected, user);
                }
                menu.ShowAsContext();
            }

            string sceneName = selectedUser != null ? userScenes[selectedUser] : "씬 선택";
            if(!string.IsNullOrEmpty(selectedUser) && GUILayout.Button(new GUIContent(sceneName, "Open User Scene")))
            {
                SceneHelper.OpenScene(userScenes[selectedUser]);
            }
        }

        static void OnUserSelected(object user)
        {
            selectedUser = (string) user;
        }
    }

    static class SceneHelper
    {
        public static void OpenScene(string name)
        {
            var saved = EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
            if (saved)
            {
                _ = EditorSceneManager.OpenScene($"Assets/Scenes/{name}.unity");
            }
        }
    }
}

사용자별로 씬을 등록할 수 있다

 

사용방법은 간단합니다.

 

userScenes 딕셔너리에 사용자 이름과 씬을 등록하면 됩니다.

 

 


사용자가 여러 씬을 가지게 될 경우

using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using System.Collections.Generic;

namespace UnityToolbarExtender.Examples
{
    static class ToolbarStyles
    {
        public static readonly GUIStyle commandButtonStyle;

        static ToolbarStyles()
        {
            commandButtonStyle = new GUIStyle("Command")
            {
                fontSize = 16,
                alignment = TextAnchor.MiddleCenter,
                imagePosition = ImagePosition.ImageAbove,
                fontStyle = FontStyle.Bold
            };
        }
    }

    [InitializeOnLoad]
    public class SceneSwitchLeftButton
    {
        static Dictionary<string, List<string>> userScenes = new Dictionary<string, List<string>>
        {
            {"진우", new List<string> { "Chapter3", "Chapter5", "Chapter6" }},
            {"지은", new List<string> { "Chapter1", "Chapter2", "Chapter4" }},
            {"사랑", new List<string> { "sarang" }},
            {"가영", new List<string> { "Test4" }},
        };

        static string selectedUser;
        static string selectedScene;

        static SceneSwitchLeftButton()
        {
            ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
        }

        static void OnToolbarGUI()
        {
            GUILayout.FlexibleSpace();

            if(GUILayout.Button(new GUIContent("MainMenu", "MainMenu Scene")))
            {
                SceneHelper.OpenScene("MainMenu");
            }
            if(GUILayout.Button(new GUIContent("MainGame", "MainGame Scene"))) 
            {
                SceneHelper.OpenScene("MainGame");
            }

            if (GUILayout.Button(selectedUser ?? "사용자 선택", EditorStyles.popup))
            {
                var menu = new GenericMenu();
                foreach (var user in userScenes.Keys)
                {
                    menu.AddItem(new GUIContent(user), false, OnUserSelected, user);
                }
                menu.ShowAsContext();
            }

            if (!string.IsNullOrEmpty(selectedUser) && GUILayout.Button(new GUIContent(selectedScene ?? "씬 선택", "Open User Scene"), EditorStyles.popup))
            {
                var userScenesMenu = new GenericMenu();
                foreach (var scene in userScenes[selectedUser])
                {
                    userScenesMenu.AddItem(new GUIContent(scene), false, OnSceneSelected, scene);
                }
                userScenesMenu.ShowAsContext();
            }
        }

        static void OnUserSelected(object user)
        {
            selectedUser = (string) user;
            selectedScene = null;
        }

        static void OnSceneSelected(object scene)
        {
            selectedScene = (string)scene;
            SceneHelper.OpenScene(selectedScene);
        }
    }

    static class SceneHelper
    {
        public static void OpenScene(string name)
        {
            var saved = EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
            if (saved)
            {
                _ = EditorSceneManager.OpenScene($"Assets/Scenes/{name}.unity");
            }
        }
    }
}

 

수정해야하는 부분

 

위 사진의 박스친 곳을 팀 프로젝트에 맞게 수정하시면 됩니다.

여러개의 씬

 

 

수정을 하시게 되면 위 사진처럼 씬을 여러개 선택할 수 있게 됩니다.

 


드롭다운을 사용한 방식

using UnityEditor;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;
using UnityEngine;

namespace UnityToolbarExtender.Examples
{
    [InitializeOnLoad]
    public class SceneSwitchLeftButton
    {
        static string[] sceneOptions =
        {
            "Awake", "MainMenu", "MainGame"
        };
        
        static int selectedIndex;

        static SceneSwitchLeftButton()
        {
            selectedIndex = EditorPrefs.GetInt("SelectedSceneIndex", 0); 
            ToolbarExtender.LeftToolbarGUI.Add(OnToolbarGUI);
        }

        static void OnToolbarGUI()
        {
            GUILayout.FlexibleSpace();

            int newSelectedIndex = EditorGUILayout.Popup(selectedIndex, sceneOptions, GUILayout.Width(100));

            if (newSelectedIndex != selectedIndex)
            {
                selectedIndex = newSelectedIndex;
                EditorPrefs.SetInt("SelectedSceneIndex", selectedIndex); 
                SceneHelper.OpenScene(sceneOptions[selectedIndex]);
            }
        }
    }

    static class SceneHelper
    {
        public static void OpenScene(string name)
        {
            if (EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo())
            {
                string scenePath = $"Assets/01.Scenes/{name}.unity";
                if (System.IO.File.Exists(scenePath))
                {
                    EditorSceneManager.OpenScene(scenePath);
                }
                else
                {
                    Debug.LogError($"Scene '{name}' does not exist at path '{scenePath}'");
                }
            }
        }
    }
}