LoginSignup
5
2

More than 5 years have passed since last update.

Sceneの受け渡しを扱いやすくする自動生成スクリプト

Last updated at Posted at 2017-10-25

前回に引き続き、自動生成ネタです。
UnityのLayerをEnumにしてくれるEditor拡張を作った

今回は、SceneをEnumにして扱えたら楽なんじゃないか?と思って作ってみた次第です。
単純にEnumにするのではく、stringの配列も加えています。

SceneInfoCreator.cs

using UnityEngine;
using UnityEditor;
using System.Linq;
using UnityEditorInternal;
using System.Collections.Generic;
using System;
using System.IO;
using UnityEngine.SceneManagement;
using UnityEditor.SceneManagement;

[InitializeOnLoad]
public class SceneInfoCreator
{
    private const string SCENE_ENUM_HASH_KEY = "Scene_Info_Hash";

    [MenuItem("Assets/SceneInfoCreator")]
    public static void _sceneNameCreator()
    {
        if (EditorApplication.isPlaying || Application.isPlaying)
            return;

        EditorApplication.delayCall += BuildSceneName;
    }

    static SceneInfoCreator()
    {
        if (EditorApplication.isPlaying || Application.isPlaying)
            return;

        EditorApplication.delayCall += BuildSceneName;
    }

    static void BuildSceneName()
    {
        System.Text.StringBuilder builder = new System.Text.StringBuilder();

        builder = WriteManagerClass(builder);

        string text = builder.ToString().Replace(",}", "}");
        string assetPath = Application.dataPath + "/Scripts/Utility/SceneInfo.cs";

        if (AssetDatabase.LoadAssetAtPath(assetPath.Replace("/Editor/..", ""), typeof(UnityEngine.Object)) != null && EditorPrefs.GetInt(SCENE_ENUM_HASH_KEY, 0) == text.GetHashCode())
            return;

        System.IO.File.WriteAllText(assetPath, text);
        EditorPrefs.SetInt(SCENE_ENUM_HASH_KEY, text.GetHashCode());
        AssetDatabase.Refresh(ImportAssetOptions.ImportRecursive);
        EditorApplication.delayCall -= BuildSceneName;
    }

    static System.Text.StringBuilder WriteManagerClass(System.Text.StringBuilder builder)
    {
        var sceneNames = new List<string>();
        EditorBuildSettings.scenes
                    .Where(_ => _.enabled)
                    .Select(_ => Path.GetFileNameWithoutExtension(Path.Combine(Directory.GetCurrentDirectory(), _.path)))
                    .Where(_ => !string.IsNullOrEmpty(_))
                    .ForEach(_ => sceneNames.Add(_));
        builder.AppendLine("/// <summary>");
        builder.AppendFormat("/// Access Scene Class").AppendLine();
        builder.AppendLine("/// </summary>");
        /// 
        builder.Append("public sealed class SceneInfo {").AppendLine();
        WriteSceneEnum(builder, sceneNames);
        WriteSceneNameArray(builder, sceneNames);
        builder.AppendLine("}");
        return builder;
    }

    static void WriteSceneEnum(System.Text.StringBuilder builder, List<string> sceneNames)
    {
        builder.Append("\t").AppendLine("/// <summary>");
        builder.Append("\t").AppendFormat("/// Access Scene Number Enum").AppendLine();
        builder.Append("\t").AppendLine("/// </summary>");
        builder.Append("\t").Append("public enum SceneEnum {").AppendLine();
        sceneNames.ForEach((sceneName, i) =>
        {
            var comma = (i == sceneNames.Count() - 1) ? "" : ",";
            builder.Append("\t").Append("\t").AppendFormat("{0} = {1}", sceneName.SymbolReplace(), i + comma).AppendLine();
        });
        builder.Append("\t").AppendLine("};");
    }

    static void WriteSceneNameArray(System.Text.StringBuilder builder, List<string> sceneNames)
    {
        builder.Append("\t").AppendLine("/// <summary>");
        builder.Append("\t").AppendFormat("/// Access Scene Name Array").AppendLine();
        builder.Append("\t").AppendLine("/// </summary>");
        builder.Append("\t").Append("public static readonly string[] SceneNames = new string[]{");
        sceneNames.ForEach((sceneName, i) =>
        {
            var comma = (i == sceneNames.Count() - 1) ? "" : ",";
            builder.AppendFormat(@"""{0}""" + comma, sceneName);
        });
        builder.AppendLine("}; ");
    }
}

上記の処理を実行した時にBuildSettingsで仮にInit.sceneとTest.sceneを登録した場合、以下のようなスクリプトが生成されます。

SceneInfo.cs
/// <summary>
/// Access Scene Class
/// </summary>
public sealed class SceneInfo {
    /// <summary>
    /// Access Scene Number Enum
    /// </summary>
    public enum SceneEnum {
        Init = 0,
        Test = 1
    };
    /// <summary>
    /// Access Scene Name Array
    /// </summary>
    public static readonly string[] SceneNames = new string[]{"Init","Test"}; 
}

これの自動生成があるだけでもかなりミスが減らせる気がします。InspectorでもEnum表示してScene選ぶとかできますし、何かと楽になりそうです。

ファイルの保存場所は適宜変えてください。

コピペでうまく動かない人は、前回の記事に書いてある拡張メソッドを追加してみてください。

自作フレームワークに組み込んで改修を続けているのでご興味あれば
https://github.com/MizoTake/MomijiFramework

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2