0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Unity】Console のエラー文を Ctrl+C するだけで ChatGPT 向けプロンプトに自動変換する Editor 拡張

Last updated at Posted at 2025-05-29

コンソールのエラー文を Ctrl + C したら
クリップボードの内容が ChatGPT の質問文に
自動で置き換わる Editor 拡張を考えました。

タイトルなし.png

エラー文から自動的に .cs ファイルを検出し、
ソースコードも添付します。

これで ChatGPT の活用が楽になるかもしれません。
よろしければどうぞ!

サクっと使用したい場合は
unitypackage 版 をご利用ください。


SephirothConsoleCopyInterceptor.cs
#if UNITY_EDITOR

using UnityEditor;
using UnityEngine;
using System;
using System.Runtime.InteropServices;

[InitializeOnLoad]
public static class SephirothConsoleCopyInterceptor
{
    [DllImport("user32.dll")]
    private static extern short GetAsyncKeyState(int vKey);

    private const int VK_CONTROL = 0x11;
    private const int C_KEY = 0x43;

    private static double lastCopyTime = 0;
    private static double triggerTime = 0;
    private static bool shouldProcessClipboard = false;

    static SephirothConsoleCopyInterceptor()
    {
        EditorApplication.update -= OnEditorUpdate;
        EditorApplication.update += OnEditorUpdate;
    }

    private static void OnEditorUpdate()
    {
        // Ctrl + C を検出
        bool ctrl = (GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0;
        bool c = (GetAsyncKeyState(C_KEY) & 0x8000) != 0;


        if (!UnityEditorInternal.InternalEditorUtility.isApplicationActive)
        return;

         // Console ウィンドウ以外では無効化
        var focused = EditorWindow.focusedWindow;
        if (focused == null || !focused.titleContent.text.Equals("Console"))
            return;

        if (ctrl && c && EditorApplication.timeSinceStartup - lastCopyTime > 0.5f)
        {
            lastCopyTime = EditorApplication.timeSinceStartup;
            triggerTime = lastCopyTime + 0.1; // 0.1 秒後に実行
            shouldProcessClipboard = true;
        }

        if (shouldProcessClipboard && EditorApplication.timeSinceStartup >= triggerTime)
        {
            shouldProcessClipboard = false;

            try
            {
                string originalText = GUIUtility.systemCopyBuffer;
                string transformed = TransformToChatGPTPrompt(originalText);

                if (!string.IsNullOrWhiteSpace(transformed))
                {
                    GUIUtility.systemCopyBuffer = transformed;
                    Debug.Log("📋 ChatGPT 用に変換されたエラー文がコピーされました");
                }
            }
            catch (Exception ex)
            {
                Debug.LogError("クリップボード変換中にエラー: " + ex.Message);
            }
        }
    }

    private static string TransformToChatGPTPrompt(string errorText)
    {
        if (string.IsNullOrWhiteSpace(errorText)) return null;

        var lines = errorText.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        var scriptEntries = new System.Collections.Generic.List<(string relativePath, string absolutePath, string code)>();
        var seenPaths = new System.Collections.Generic.HashSet<string>(StringComparer.OrdinalIgnoreCase); // 重複防止

        foreach (var line in lines)
        {
            int assetIndex = line.IndexOf("Assets");
            int csIndex = line.IndexOf(".cs");

            if (assetIndex >= 0 && csIndex > assetIndex)
            {
                string partial = line.Substring(assetIndex + 6);
                partial = partial.Substring(0, partial.IndexOf(".cs") + 3);
                string relativePath = partial.Replace("\\", "/");
                string absolutePath = Application.dataPath + relativePath;

                // 重複チェック
                if (seenPaths.Contains(absolutePath))
                    continue;

                if (System.IO.File.Exists(absolutePath))
                {
                    try
                    {
                        string code = System.IO.File.ReadAllText(absolutePath);
                        scriptEntries.Add((relativePath, absolutePath, code));
                        seenPaths.Add(absolutePath); // 記録
                    }
                    catch (Exception ex)
                    {
                        Debug.LogWarning("スクリプトの読み込みに失敗: " + ex.Message);
                    }
                }
            }
        }

        // 各ファイルのコードを整形
        System.Text.StringBuilder codeBuilder = new();
        foreach (var entry in scriptEntries)
        {
            codeBuilder.AppendLine($"以下は関連するスクリプトファイルの内容です: `Assets{entry.relativePath}`");
            codeBuilder.AppendLine("```");
            string[] codeLines = entry.code.Split(new[] { '\r', '\n' });
            for (int i = 0; i < codeLines.Length; i++)
            {
                codeBuilder.AppendLine($"{i + 1}: {codeLines[i]}");
            }
            codeBuilder.AppendLine("```");
            codeBuilder.AppendLine();
        }

        return
    $@"以下の Unity エラーについて、原因と解決方法を教えてください。

    {errorText}

    {(codeBuilder.Length > 0 ? codeBuilder.ToString() : "")}
    
    エラーの要点や注意点があればそれも合わせて教えてください。";
    }
}

#endif

例えばクリップボードの内容が
下記のような内容になります。

クリップボードの内容
以下の Unity エラーについて、原因と解決方法を教えてください。

    Assets\SephirothChatGPTPromptCreator\SephirothChatGPTPromptCreator.cs(17,43): error CS1002: ; expected



    以下は関連するスクリプトファイルの内容です: `C:\Users\User\SephirothChatGPTPromptCreater\Assets\SephirothChatGPTPromptCreator\SephirothChatGPTPromptCreator.cs`

1: #if UNITY_EDITOR
2: 
3: using UnityEngine;
4: using UnityEditor;
5: using System.IO;
6: using System.Text;
7: using System.Collections.Generic;
8: using UnityEditor.SceneManagement;
9: using UnityEngine.SceneManagement;
10: 
11: public static class SephirothChatGPTPromptCreator
12: {
13:     [MenuItem("Assets/Tools/SephirothChatGPTPromptCreator/All", true)]
14:     private static bool ValidateSelectedUnityFile()
15:     {
16:         string path = AssetDatabase.GetAssetPath(Selection.activeObject);
17:         return path.EndsWith(".unity");aaa
18:     }
19: 
20:     [MenuItem("Assets/Tools/SephirothChatGPTPromptCreator/All")]
21:     private static void GeneratePromptFromScene()
22:     {
23:         string scenePath = AssetDatabase.GetAssetPath(Selection.activeObject);
24:         if (!scenePath.EndsWith(".unity"))
25:         {
26:             Debug.LogWarning("選択されたファイルは .unity ファイルではありません。");
27:             return;
28:         }
29: 
30:         var builder = new StringBuilder();
31: 
32:         // .unity ファイルの内容を追加
33:         string fullScenePath = Path.Combine(Directory.GetCurrentDirectory(), scenePath);
34:         builder.AppendLine(Path.GetFileName(scenePath));
35:         builder.AppendLine(File.ReadAllText(fullScenePath));
36:         builder.AppendLine();
37: 
38:         // シーンを開いてすべての MonoBehaviour を取得
39:         var openedScene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
40:         var allObjects = openedScene.GetRootGameObjects();
41: 
42:         var uniqueScripts = new HashSet<MonoScript>();
43: 
44:         foreach (var go in allObjects)
45:         {
46:             foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true))
47:             {
48:                 if (mb == null) continue; // Missing Script の場合
49:                 var script = MonoScript.FromMonoBehaviour(mb);
50:                 if (script != null)
51:                     uniqueScripts.Add(script);
52:             }
53:         }
54: 
55:         // 各スクリプトファイルを読み込み(Assetsフォルダ内のスクリプトのみ対象)
56:         foreach (var monoScript in uniqueScripts)
57:         {
58:             string scriptPath = AssetDatabase.GetAssetPath(monoScript);
59:             if (!scriptPath.StartsWith("Assets/")) 
60:                 continue; // Unity内部やパッケージのスクリプトは除外
61: 
62:             string fullScriptPath = Path.Combine(Directory.GetCurrentDirectory(), scriptPath);
63:             builder.AppendLine(Path.GetFileName(scriptPath));
64:             builder.AppendLine(File.ReadAllText(fullScriptPath));
65:             builder.AppendLine();
66:         }
67: 
68:         // クリップボードにコピー
69:         EditorGUIUtility.systemCopyBuffer = builder.ToString();
70:         Debug.Log("シーンと関連付けられた .cs スクリプトがクリップボードにコピーされました。");
71:     }
72: 
73:     [MenuItem("Assets/Tools/SephirothChatGPTPromptCreator/CSOnly", true)]
74:     private static bool ValidateSelectedUnityFile2()
75:     {
76:         string path = AssetDatabase.GetAssetPath(Selection.activeObject);
77:         return path.EndsWith(".unity");
78:     }
79: 
80:     [MenuItem("Assets/Tools/SephirothChatGPTPromptCreator/CSOnly")]
81:     private static void GeneratePromptFromScene2()
82:     {
83:         string scenePath = AssetDatabase.GetAssetPath(Selection.activeObject);
84:         if (!scenePath.EndsWith(".unity"))
85:         {
86:             Debug.LogWarning("選択されたファイルは .unity ファイルではありません。");
87:             return;
88:         }
89: 
90:         var builder = new StringBuilder();
91: 
92:         // シーンを開いてすべての MonoBehaviour を取得
93:         var openedScene = EditorSceneManager.OpenScene(scenePath, OpenSceneMode.Single);
94:         var allObjects = openedScene.GetRootGameObjects();
95: 
96:         var uniqueScripts = new HashSet<MonoScript>();
97: 
98:         foreach (var go in allObjects)
99:         {
100:             foreach (var mb in go.GetComponentsInChildren<MonoBehaviour>(true))
101:             {
102:                 if (mb == null) continue; // Missing Script の場合
103:                 var script = MonoScript.FromMonoBehaviour(mb);
104:                 if (script != null)
105:                     uniqueScripts.Add(script);
106:             }
107:         }
108: 
109:         // 各スクリプトファイルを読み込み(Assetsフォルダ内のスクリプトのみ対象)
110:         foreach (var monoScript in uniqueScripts)
111:         {
112:             string scriptPath = AssetDatabase.GetAssetPath(monoScript);
113:             if (!scriptPath.StartsWith("Assets/")) 
114:                 continue; // Unity内部やパッケージのスクリプトは除外
115: 
116:             string fullScriptPath = Path.Combine(Directory.GetCurrentDirectory(), scriptPath);
117:             builder.AppendLine(Path.GetFileName(scriptPath));
118:             builder.AppendLine(File.ReadAllText(fullScriptPath));
119:             builder.AppendLine();
120:         }
121: 
122:         // クリップボードにコピー
123:         EditorGUIUtility.systemCopyBuffer = builder.ToString();
124:         Debug.Log("シーンと関連付けられた .cs スクリプトがクリップボードにコピーされました。");
125:     }
126: }
127: 
128: #endif

    エラーの要点や注意点があればそれも合わせて教えてください。

以上、楽に ChatGPT を活用するための
Editor 拡張を紹介しました。

これで皆さんの開発が楽になる事があれば
非常に嬉しいです。

稀にエラー文にバグが発生しているコードの
パスが載っていない事がありますが、
その場合は動作しませんのでご容赦下さい。

今回はここまで、
閲覧ありがとうございました。

以下で ChatGPT に出力頂いた説明文を載せます。
興味のある方はどうぞ。


Unity Console のエラーを ChatGPT にそのまま相談できたら便利だと思いませんか?

このエディタ拡張は、Unity の Console で発生したエラー文を Ctrl + C でコピーするだけで、自動的に ChatGPT に貼り付けられる形式へと変換してくれるツールです。

コピー後わずか 0.1 秒で、クリップボード内のエラーメッセージが以下のようなフォーマットに変換されます:

生成される文章
以下の Unity エラーについて、原因と解決方法を教えてください。

    [コピーしたエラー文]

    以下は関連するスクリプトファイルの内容です:

[該当ファイルのコード全文]

    エラーの要点や注意点があればそれも合わせて教えてください。

🔧 主な機能:

Ctrl + C を押すだけでエラー文を ChatGPT 向けに自動整形

エラー文から自動的に .cs ファイルを検出し、ソースコードも添付

Unity エディタ拡張としてシームレスに動作

無駄な手間ゼロでエラーの原因調査が効率化!

📝 対応環境:

Unity 2020.3 以降

Windows 専用(※ macOS には未対応)

エディターモードのみ対応(Play中は無効)

💡 こんな人におすすめ:

Unity のエラーを毎回手動で ChatGPT に貼っている方

プログラミング初心者の方

デバッグ効率を最大化したい開発者

使い方はとても簡単!スクリプトをプロジェクトに導入するだけです。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?