├── .gitignore ├── Editor.meta ├── Editor ├── BKKChatGPT.cs ├── BKKChatGPT.cs.meta ├── ChatGPTAnswer.cs ├── ChatGPTAnswer.cs.meta ├── ChatGPTAnswerEditor.cs ├── ChatGPTAnswerEditor.cs.meta ├── ChatGPTAnswers.meta ├── ChatGPTScriptGeneratorWindow.cs ├── ChatGPTScriptGeneratorWindow.cs.meta ├── ChatGPTSettings.cs ├── ChatGPTSettings.cs.meta ├── ChatGPTSettingsEditor.cs ├── ChatGPTSettingsEditor.cs.meta ├── ChatGPTSettingsWindow.cs ├── ChatGPTSettingsWindow.cs.meta ├── EditorBackgroundUtility.cs ├── EditorBackgroundUtility.cs.meta ├── Resources.meta ├── Resources │ ├── ChatGPTSettings.asset │ └── ChatGPTSettings.asset.meta ├── ScriptGenerator.cs ├── ScriptGenerator.cs.meta ├── com.bkk.chatgptscriptgenerater.Editor.asmdef └── com.bkk.chatgptscriptgenerater.Editor.asmdef.meta ├── LICENSE ├── LICENSE.meta ├── README.md ├── README.md.meta ├── package.json └── package.json.meta /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Asset meta data should only be ignored when the corresponding asset is also ignored 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # Autogenerated Jetbrains Rider plugin 20 | [Aa]ssets/Plugins/Editor/JetBrains* 21 | 22 | # Visual Studio cache directory 23 | .vs/ 24 | 25 | # Gradle cache directory 26 | .gradle/ 27 | 28 | # Autogenerated VS/MD/Consulo solution and project files 29 | ExportedObj/ 30 | .consulo/ 31 | *.csproj 32 | *.unityproj 33 | *.sln 34 | *.suo 35 | *.tmp 36 | *.user 37 | *.userprefs 38 | *.pidb 39 | *.booproj 40 | *.svd 41 | *.pdb 42 | *.mdb 43 | *.opendb 44 | *.VC.db 45 | 46 | # Unity3D generated meta files 47 | *.pidb.meta 48 | *.pdb.meta 49 | *.mdb.meta 50 | 51 | # Unity3D generated file on crash reports 52 | sysinfo.txt 53 | 54 | # Builds 55 | *.apk 56 | *.unitypackage 57 | 58 | # Crashlytics generated file 59 | crashlytics-build.properties 60 | 61 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 21a07639e8d1cd3478e1996b24f34144 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BKKChatGPT.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | public static class BKKChatGPT 6 | { 7 | public static string GPT35Turbo = "gpt-3.5-turbo"; 8 | public static string GPT4 = "gpt-4"; 9 | public static string TextDavinci003 = "text-davinci-003"; 10 | 11 | public static readonly string[] modelOptions = new string[] 12 | { 13 | TextDavinci003, GPT35Turbo, GPT4 14 | }; 15 | 16 | public enum ModelEnum 17 | { 18 | TextDavinci003, 19 | GPT35Turbo, 20 | GPT4, 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Editor/BKKChatGPT.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3fc6e8b65f9d425b866864ea7d7439e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTAnswer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using UnityEngine; 5 | using UnityEngine.Networking; 6 | 7 | namespace BKK.ChatGPTEditor 8 | { 9 | [CreateAssetMenu(fileName = "Answer Asset", menuName = "ChatGPT Script Compiler/Answer Asset", order = 0)] 10 | public class ChatGPTAnswer : ScriptableObject 11 | { 12 | public string question; 13 | public string answer; 14 | 15 | public string fileName; 16 | public string savePath; 17 | 18 | [HideInInspector] public bool answerSent; 19 | 20 | private readonly ChatGPT4Message systemMessage = new ChatGPT4Message() 21 | { 22 | role = "user", 23 | content = 24 | "You are Unity Engine Script Generator. You will be given script related unity. Respond with only the script without explanation. If user talk about not unity engine related, respond \"I can't Respond about that.\"" 25 | }; 26 | 27 | public void SendAnswer() 28 | { 29 | Debug.Log("Answer Sent"); 30 | var settings = Resources.Load("ChatGPTSettings"); 31 | 32 | if (settings.aiModel.Contains(BKKChatGPT.TextDavinci003)) 33 | { 34 | EditorBackgroundUtility.StartBackgroundTask(GenerateLegacyResponse(settings.apiKey, settings.aiModel,question, SetAnswer)); 35 | } 36 | else 37 | { 38 | EditorBackgroundUtility.StartBackgroundTask(GenerateGPT4Response(settings.apiKey, settings.aiModel,question, SetAnswer)); 39 | } 40 | } 41 | 42 | private void SetAnswer(string _answer) 43 | { 44 | answer = _answer.Trim(); 45 | } 46 | 47 | private IEnumerator GenerateLegacyResponse(string apiKey, string model, string prompt, Action resultAction) 48 | { 49 | ChatGPTCompletionData completionData = new ChatGPTCompletionData 50 | { 51 | model = model, 52 | prompt = prompt, 53 | max_tokens = 1000, 54 | temperature = 0, 55 | }; 56 | 57 | string json = JsonUtility.ToJson(completionData); 58 | byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(json); 59 | 60 | using (UnityWebRequest request = UnityWebRequest.Post("https://api.openai.com/v1/completions", json)) 61 | { 62 | request.SetRequestHeader("Content-Type", "application/json"); 63 | request.SetRequestHeader("Authorization", $"Bearer {apiKey}"); 64 | request.uploadHandler = new UploadHandlerRaw(jsonBytes); 65 | request.downloadHandler = new DownloadHandlerBuffer(); 66 | 67 | yield return request.SendWebRequest(); 68 | 69 | while (request.isDone == false) yield return null; 70 | 71 | if (request.result == UnityWebRequest.Result.ConnectionError || 72 | request.result == UnityWebRequest.Result.ProtocolError) 73 | { 74 | Debug.Log(request.error); 75 | } 76 | else 77 | { 78 | Debug.Log("ChatGPT Answered!"); 79 | var result = JsonUtility.FromJson(request.downloadHandler.text); 80 | resultAction?.Invoke(result.choices[0].text); 81 | } 82 | answerSent = false; 83 | } 84 | } 85 | 86 | private IEnumerator GenerateGPT4Response(string apiKey, string model, string message, Action resultAction) 87 | { 88 | ChatGPT4CompletionData completionData = new ChatGPT4CompletionData 89 | { 90 | model = model, 91 | messages = new List() 92 | { 93 | systemMessage, 94 | new ChatGPT4Message() 95 | { 96 | role = "user", 97 | content = message, 98 | } 99 | }, 100 | temperature = 0, 101 | }; 102 | 103 | string json = JsonUtility.ToJson(completionData); 104 | byte[] jsonBytes = System.Text.Encoding.UTF8.GetBytes(json); 105 | 106 | using (UnityWebRequest request = UnityWebRequest.Post("https://api.openai.com/v1/chat/completions", json)) 107 | { 108 | request.SetRequestHeader("Content-Type", "application/json"); 109 | request.SetRequestHeader("Authorization", $"Bearer {apiKey}"); 110 | request.uploadHandler = new UploadHandlerRaw(jsonBytes); 111 | request.downloadHandler = new DownloadHandlerBuffer(); 112 | 113 | yield return request.SendWebRequest(); 114 | 115 | while (request.isDone == false) yield return null; 116 | 117 | if (request.result == UnityWebRequest.Result.ConnectionError || 118 | request.result == UnityWebRequest.Result.ProtocolError) 119 | { 120 | Debug.Log(request.error); 121 | } 122 | else 123 | { 124 | Debug.Log("ChatGPT Answered!"); 125 | ChatGPT4Result result = JsonUtility.FromJson(request.downloadHandler.text); 126 | resultAction?.Invoke(result.choices[0].message.content); 127 | } 128 | answerSent = false; 129 | } 130 | } 131 | 132 | [Serializable] 133 | public class ChatGPT4CompletionData 134 | { 135 | public string model; 136 | public List messages = new List(); 137 | public int temperature; 138 | } 139 | 140 | [Serializable] 141 | public class ChatGPT4Result 142 | { 143 | public string id; 144 | public string @object; 145 | public int created; 146 | public string model; 147 | public ChatGPTUsage usage; 148 | public List choices = new List(); 149 | } 150 | 151 | [Serializable] 152 | public class ChatGPT4Message 153 | { 154 | public string role; 155 | public string content; 156 | } 157 | 158 | [Serializable] 159 | public class ChatGPT4Choice 160 | { 161 | public ChatGPT4Message message; 162 | public string finish_reason; 163 | public int index; 164 | } 165 | 166 | [Serializable] 167 | public class ChatGPTCompletionData 168 | { 169 | public string model; 170 | public string prompt; 171 | public int max_tokens; 172 | public int temperature; 173 | } 174 | 175 | [Serializable] 176 | public class ChatGPTResult 177 | { 178 | public string id; 179 | public string @object; 180 | public int created; 181 | public string model; 182 | 183 | public List choices; 184 | public ChatGPTUsage usage; 185 | } 186 | 187 | [Serializable] 188 | public class ChatGPTChoice 189 | { 190 | public string text; 191 | public int index; 192 | public string finish_reason; 193 | } 194 | 195 | [Serializable] 196 | public class ChatGPTUsage 197 | { 198 | public int prompt_tokens; 199 | public int completion_tokens; 200 | public int total_tokens; 201 | } 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /Editor/ChatGPTAnswer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 791256a0d7e535d46904caa9c5853b6c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTAnswerEditor.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace BKK.ChatGPTEditor 5 | { 6 | [CustomEditor(typeof(ChatGPTAnswer))] 7 | public class ChatGPTAnswerEditor : Editor 8 | { 9 | private ChatGPTAnswer answerAsset; 10 | 11 | private ChatGPTSettings settings; 12 | 13 | private const string waitMessage = "Wait for Response..."; 14 | 15 | private const string standbyMessage = "Ready to Answer."; 16 | 17 | private const string apiKeyErrorMessage = "API Key is Empty."; 18 | private const string modelErrorMessage = "Model Name is Empty."; 19 | private const string settingErrorMessage = "ChatGPTSettings not Exists."; 20 | 21 | private Vector2 scrollA; 22 | private Vector2 scrollB; 23 | 24 | private int typingAreaHeight = 15; 25 | private int fontSize = 12; 26 | 27 | private void OnEnable() 28 | { 29 | if (target is ChatGPTAnswer answer) answerAsset = answer; 30 | settings = Resources.Load("ChatGPTSettings"); 31 | } 32 | 33 | public override void OnInspectorGUI() 34 | { 35 | if (answerAsset.answerSent) GUI.enabled = false; 36 | 37 | TextScrollArea("[ Question ]", ref answerAsset.question, ref scrollA); 38 | TextScrollArea("[ Answer ]", ref answerAsset.answer, ref scrollB); 39 | 40 | EditorGUILayout.Separator(); 41 | 42 | answerAsset.fileName = EditorGUILayout.TextField("File Name", answerAsset.fileName); 43 | 44 | answerAsset.savePath = EditorGUILayout.TextField("Save Path", answerAsset.savePath); 45 | 46 | EditorGUILayout.Separator(); 47 | 48 | if (!settings || settings.ApiKeyIsEmpty() || settings.ModelIsEmpty()) GUI.enabled = false; 49 | if (GUILayout.Button("Send Answer")) 50 | { 51 | answerAsset.SendAnswer(); 52 | answerAsset.answerSent = true; 53 | } 54 | 55 | if (!settings || settings.ApiKeyIsEmpty() || settings.ModelIsEmpty()) GUI.enabled = true; 56 | 57 | EditorGUILayout.BeginHorizontal(); 58 | GUILayout.FlexibleSpace(); 59 | if (answerAsset.answerSent) 60 | { 61 | GUILayout.Label(waitMessage); 62 | } 63 | else 64 | { 65 | if (!settings) 66 | { 67 | GUILayout.Label(settingErrorMessage); 68 | } 69 | else 70 | { 71 | if (settings.ApiKeyIsEmpty()) 72 | { 73 | GUILayout.Label(apiKeyErrorMessage); 74 | } 75 | else if (settings.ModelIsEmpty()) 76 | { 77 | GUILayout.Label(modelErrorMessage); 78 | } 79 | else 80 | { 81 | GUILayout.Label(standbyMessage); 82 | } 83 | } 84 | } 85 | 86 | GUILayout.FlexibleSpace(); 87 | EditorGUILayout.EndHorizontal(); 88 | if (answerAsset.answerSent) GUI.enabled = true; 89 | 90 | EditorUtility.SetDirty(answerAsset); 91 | Undo.RecordObject(answerAsset, "ChatGPTAnswer"); 92 | } 93 | 94 | private void TextScrollArea(string label, ref string text, ref Vector2 scrollPos) 95 | { 96 | EditorGUILayout.LabelField(label); 97 | scrollPos = EditorGUILayout.BeginScrollView(scrollPos, 98 | GUILayout.MaxHeight(typingAreaHeight * EditorGUIUtility.singleLineHeight)); 99 | 100 | text = EditorGUILayout.TextArea(text, 101 | EditorStyles.textArea, 102 | GUILayout.MaxHeight(typingAreaHeight * 103 | EditorGUIUtility.singleLineHeight)); 104 | 105 | EditorStyles.textArea.fontSize = fontSize; 106 | EditorGUILayout.EndScrollView(); 107 | } 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Editor/ChatGPTAnswerEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b6216bc2e84fae4ea2497ae6f988bb6 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTAnswers.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d4c9ee504b40a544d9dab7750300673b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/ChatGPTScriptGeneratorWindow.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace BKK.ChatGPTEditor 6 | { 7 | public class ChatGPTScriptGeneratorWindow : EditorWindow 8 | { 9 | private GUIStyle titleStyle; 10 | 11 | private ChatGPTAnswer answerAsset; 12 | private Editor answerAssetEditor; 13 | 14 | private ChatGPTSettings settings; 15 | 16 | private const string assetFileName = "Answer Asset.asset"; 17 | 18 | [MenuItem("Window/BKK/Chat GPT Script Generator")] 19 | private static void OpenChatGPTScriptGeneratorWindow() 20 | { 21 | ChatGPTScriptGeneratorWindow window = 22 | GetWindow(false, "Chat GPT Script Generator", true); 23 | window.titleContent = new GUIContent("Chat GPT Script Generator"); 24 | } 25 | 26 | private void OnEnable() 27 | { 28 | titleStyle = new GUIStyle 29 | { 30 | fontSize = 20, 31 | normal = 32 | { 33 | textColor = Color.white 34 | } 35 | }; 36 | 37 | EditorPrefs.GetString($"{this.GetType()}_CreatePath", "Assets/Editor/ChatGPTAnswers"); 38 | 39 | settings = Resources.Load("ChatGPTSettings"); 40 | } 41 | 42 | private void OnDisable() 43 | { 44 | EditorPrefs.SetString($"{this.GetType()}_CreatePath", settings.createPath); 45 | } 46 | 47 | private void OnGUI() 48 | { 49 | EditorGUILayout.BeginVertical(); 50 | 51 | EditorGUILayout.LabelField("Chat GPT Script Generator", titleStyle); 52 | 53 | EditorGUILayout.Separator(); 54 | EditorGUILayout.Separator(); 55 | 56 | if (answerAsset && answerAsset.answerSent) GUI.enabled = false; 57 | 58 | EditorGUI.BeginChangeCheck(); 59 | 60 | if (GUILayout.Button("Create Answer")) 61 | { 62 | var instance = ScriptableObject.CreateInstance(); 63 | var path = $"{settings.createPath}/{assetFileName}"; 64 | 65 | if (!Directory.Exists(settings.createPath)) 66 | { 67 | Directory.CreateDirectory(settings.createPath); 68 | } 69 | 70 | var uniquePath = AssetDatabase.GenerateUniqueAssetPath(path); 71 | AssetDatabase.CreateAsset(instance, uniquePath); 72 | 73 | AssetDatabase.SaveAssets(); 74 | 75 | answerAsset = instance; 76 | 77 | EditorGUI.FocusTextInControl(null); // take focus from textArea 78 | } 79 | 80 | EditorGUILayout.Separator(); 81 | 82 | answerAsset = 83 | (ChatGPTAnswer) EditorGUILayout.ObjectField("Answer Asset", answerAsset, typeof(ChatGPTAnswer), false); 84 | 85 | if (answerAsset && answerAsset.answerSent) GUI.enabled = true; 86 | 87 | if (answerAsset) 88 | { 89 | if (EditorGUI.EndChangeCheck()) 90 | answerAssetEditor = 91 | Editor.CreateEditor(answerAsset); // Create Answer Asset Editor when Answer Asset changed. 92 | 93 | answerAssetEditor.OnInspectorGUI(); 94 | EditorUtility.SetDirty(answerAssetEditor.target); 95 | 96 | if (answerAsset && answerAsset.answerSent) GUI.enabled = false; 97 | 98 | if (GUILayout.Button("Create Script And Compile")) 99 | { 100 | if (ScriptGenerator.IsScript(answerAsset.answer)) 101 | { 102 | ScriptGenerator.CreateCsFile(answerAsset.answer, answerAsset.fileName, answerAsset.savePath); 103 | } 104 | else 105 | { 106 | Debug.Log("Answer does not match class pattern."); 107 | } 108 | } 109 | 110 | if (answerAsset && answerAsset.answerSent) GUI.enabled = true; 111 | } 112 | 113 | if (answerAsset && answerAsset.answerSent) GUI.enabled = false; 114 | 115 | if (GUILayout.Button("Settings")) 116 | { 117 | var asset = AssetDatabase.LoadMainAssetAtPath($"{ChatGPTSettings.settingPath}/ChatGPTSettings.asset"); 118 | 119 | EditorGUIUtility.PingObject(asset); 120 | } 121 | 122 | EditorGUILayout.EndVertical(); 123 | 124 | if (answerAsset && answerAsset.answerSent) GUI.enabled = true; 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /Editor/ChatGPTScriptGeneratorWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee700c594bb460843a05ef4230b4a9df 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettings.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace BKK.ChatGPTEditor 6 | { 7 | public class ChatGPTSettings : ScriptableObject 8 | { 9 | [SerializeField] private string openAiApiKey; 10 | [SerializeField] private string model = "text-davinci-003"; 11 | [SerializeField] private string createAssetPath = "Assets/Editor/ChatGPTAnswers"; 12 | 13 | public string apiKey => openAiApiKey; 14 | public string aiModel => model; 15 | public string createPath => createAssetPath; 16 | 17 | public const string settingPath = "Assets/Editor/Resources"; 18 | 19 | [InitializeOnLoadMethod] 20 | private static void Init() 21 | { 22 | var existAssets = AssetDatabase.FindAssets($"ChatGPTSettings t:scriptableobject"); 23 | 24 | if (existAssets.Length == 0) 25 | { 26 | var instance = ScriptableObject.CreateInstance(); 27 | 28 | if (!Directory.Exists(settingPath)) 29 | { 30 | Directory.CreateDirectory(settingPath); 31 | } 32 | 33 | AssetDatabase.CreateAsset(instance, $"{settingPath}/ChatGPTSettings.asset"); 34 | AssetDatabase.SaveAssets(); 35 | } 36 | } 37 | 38 | public bool ApiKeyIsEmpty() 39 | { 40 | return string.IsNullOrEmpty(openAiApiKey) || string.IsNullOrWhiteSpace(openAiApiKey); 41 | } 42 | 43 | public bool ModelIsEmpty() 44 | { 45 | return string.IsNullOrEmpty(model) || string.IsNullOrWhiteSpace(model); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettings.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ba41ae520227e840a7148e291e21f05 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettingsEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEditor; 3 | using UnityEngine; 4 | 5 | namespace BKK.ChatGPTEditor 6 | { 7 | [CustomEditor(typeof(ChatGPTSettings))] 8 | public class ChatGPTSettingsEditor : Editor 9 | { 10 | private SerializedProperty m_OpenAiApiKey; 11 | private SerializedProperty m_Model; 12 | private SerializedProperty m_CreateAssetPath; 13 | 14 | private GUIStyle warnLabelStyle; 15 | 16 | private readonly string choosePathButtonText = "Choose"; 17 | private readonly string choosePathTitleText = "Choose Asset Path"; 18 | 19 | private readonly string modelFieldLabel = "Model"; 20 | 21 | private readonly string modelPrefsName = "UnityChatGPTScriptGenerator_Model"; 22 | 23 | private void OnEnable() 24 | { 25 | m_OpenAiApiKey = serializedObject.FindProperty("openAiApiKey"); 26 | m_Model = serializedObject.FindProperty("model"); 27 | m_CreateAssetPath = serializedObject.FindProperty("createAssetPath"); 28 | 29 | warnLabelStyle = new GUIStyle 30 | { 31 | normal = new GUIStyleState 32 | { 33 | textColor = Color.cyan 34 | } 35 | }; 36 | } 37 | 38 | public override void OnInspectorGUI() 39 | { 40 | serializedObject.Update(); 41 | 42 | EditorGUILayout.PropertyField(m_OpenAiApiKey); 43 | 44 | int modelIndex = EditorPrefs.GetInt("UnityChatGPTScriptGenerator_Model", 0); 45 | 46 | modelIndex = EditorGUILayout.Popup(modelFieldLabel, modelIndex, BKKChatGPT.modelOptions); 47 | 48 | EditorPrefs.SetInt(modelPrefsName, modelIndex); 49 | 50 | BKKChatGPT.ModelEnum modelEnum = (BKKChatGPT.ModelEnum) modelIndex; 51 | 52 | switch (modelEnum) 53 | { 54 | case BKKChatGPT.ModelEnum.TextDavinci003: 55 | m_Model.stringValue = BKKChatGPT.TextDavinci003; 56 | break; 57 | case BKKChatGPT.ModelEnum.GPT35Turbo: 58 | m_Model.stringValue = BKKChatGPT.GPT35Turbo; 59 | break; 60 | case BKKChatGPT.ModelEnum.GPT4: 61 | m_Model.stringValue = BKKChatGPT.GPT4; 62 | break; 63 | default: 64 | break; 65 | } 66 | 67 | EditorGUILayout.BeginHorizontal(); 68 | EditorGUILayout.PropertyField(m_CreateAssetPath); 69 | if (GUILayout.Button(choosePathButtonText, GUILayout.Width(100))) 70 | { 71 | string absolutePath = EditorUtility.OpenFolderPanel(choosePathTitleText, Application.dataPath, ""); 72 | 73 | if (!string.IsNullOrEmpty(absolutePath)) 74 | { 75 | string relativePath = "Assets" + absolutePath.Substring(Application.dataPath.Length); 76 | m_CreateAssetPath.stringValue = relativePath; 77 | } 78 | } 79 | EditorGUILayout.EndHorizontal(); 80 | serializedObject.ApplyModifiedProperties(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettingsEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3bebe872b493db4bacb9f6de417b8e9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettingsWindow.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace BKK.ChatGPTEditor 5 | { 6 | public class ChatGPTSettingsWindow : EditorWindow 7 | { 8 | private ChatGPTSettings settings; 9 | 10 | private Editor settingsEditor; 11 | 12 | [MenuItem("Window/BKK/Chat GPT Settings")] 13 | private static void OpenChatGPTSettingsWindow() 14 | { 15 | ChatGPTSettingsWindow window = 16 | GetWindow(false, "Chat GPT Settings", true); 17 | window.titleContent = new GUIContent("Chat GPT Settings"); 18 | } 19 | 20 | private void OnEnable() 21 | { 22 | settings = Resources.Load("ChatGPTSettings"); 23 | settingsEditor = Editor.CreateEditor(settings); 24 | } 25 | 26 | private void OnGUI() 27 | { 28 | settingsEditor.OnInspectorGUI(); 29 | EditorUtility.SetDirty(settingsEditor.target); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Editor/ChatGPTSettingsWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 09092c6f577e85b43ba9ec06c79e9b6e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/EditorBackgroundUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using UnityEditor; 4 | using UnityEngine; 5 | 6 | namespace BKK.ChatGPTEditor 7 | { 8 | public static class EditorBackgroundUtility 9 | { 10 | public static void StartBackgroundTask(IEnumerator update, Action end = null) 11 | { 12 | void ClosureCallback() 13 | { 14 | try 15 | { 16 | if (update.MoveNext() == false) 17 | { 18 | end?.Invoke(); 19 | EditorApplication.update -= ClosureCallback; 20 | } 21 | } 22 | catch (Exception ex) 23 | { 24 | end?.Invoke(); 25 | Debug.LogException(ex); 26 | EditorApplication.update -= ClosureCallback; 27 | } 28 | } 29 | 30 | EditorApplication.update += ClosureCallback; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Editor/EditorBackgroundUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 442d773c367e18643808afbbe552e789 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Resources.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4294d4e0d7a07414fb21933c479463ab 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Resources/ChatGPTSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!114 &11400000 4 | MonoBehaviour: 5 | m_ObjectHideFlags: 0 6 | m_CorrespondingSourceObject: {fileID: 0} 7 | m_PrefabInstance: {fileID: 0} 8 | m_PrefabAsset: {fileID: 0} 9 | m_GameObject: {fileID: 0} 10 | m_Enabled: 1 11 | m_EditorHideFlags: 0 12 | m_Script: {fileID: 11500000, guid: 1ba41ae520227e840a7148e291e21f05, type: 3} 13 | m_Name: ChatGPTSettings 14 | m_EditorClassIdentifier: 15 | openAiApiKey: 16 | model: gpt-3.5-turbo 17 | createAssetPath: Assets/Editor/ChatGPTAnswers 18 | -------------------------------------------------------------------------------- /Editor/Resources/ChatGPTSettings.asset.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eadf342fda99751419977abf509c3701 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 11400000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/ScriptGenerator.cs: -------------------------------------------------------------------------------- 1 | using System.IO; 2 | using System.Linq; 3 | using System.Text.RegularExpressions; 4 | using UnityEditor; 5 | using UnityEngine; 6 | 7 | namespace BKK.ChatGPTEditor 8 | { 9 | public static class ScriptGenerator 10 | { 11 | private const string pattern = 12 | @"(((internal)|(public)|(private)|(protected)|(sealed)|(abstract)|(static))?[\s\r\n\t]+){0,2}class[\s\S]+?(?={)"; 13 | 14 | public static void CreateCsFile(string contents, string name, string savePath) 15 | { 16 | var nameIsEmpty = name == string.Empty; 17 | 18 | var matches = Regex.Matches(contents, pattern, RegexOptions.Multiline); 19 | var classes = 20 | matches.Cast() 21 | .Select(x => x.Value.Trim()); // return: public class PlayerController : MonoBehaviour; 22 | var firstClass = classes.First(); 23 | var classType = Regex.Match(firstClass, @"class (.+?):").Groups[1].Value; 24 | var className = nameIsEmpty ? classType : name; 25 | 26 | if (string.IsNullOrEmpty(savePath)) savePath = "Assets"; 27 | 28 | var filePath = $"{savePath}/{className}.cs"; 29 | var existScripts = AssetDatabase.FindAssets($"{className} t:script"); 30 | 31 | if (!Directory.Exists(savePath)) 32 | { 33 | Directory.CreateDirectory(savePath); 34 | } 35 | 36 | if (existScripts.Length == 0) 37 | { 38 | using var outfile = new StreamWriter(filePath); 39 | 40 | if (nameIsEmpty) 41 | { 42 | outfile.WriteLine(contents); 43 | } 44 | else 45 | { 46 | var replacedContents = contents.Replace(className, name); // Change class name 47 | outfile.WriteLine(replacedContents); 48 | } 49 | 50 | outfile.Close(); 51 | 52 | Debug.Log($"{name}.cs Created. : {filePath}"); 53 | AssetDatabase.Refresh(); 54 | } 55 | else 56 | { 57 | var path = AssetDatabase.GUIDToAssetPath(existScripts[0]); 58 | 59 | Debug.Log($"{name}.cs Already Exists. : {path}"); 60 | } 61 | } 62 | 63 | public static bool IsScript(string contents) 64 | { 65 | return Regex.Matches(contents, pattern, RegexOptions.Multiline).Count != 0; 66 | } 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /Editor/ScriptGenerator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 62e50ecffc82d9a41b00fb57ce967043 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/com.bkk.chatgptscriptgenerater.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "NewAssembly", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [ 6 | "Editor" 7 | ], 8 | "excludePlatforms": [], 9 | "allowUnsafeCode": false, 10 | "overrideReferences": false, 11 | "precompiledReferences": [], 12 | "autoReferenced": true, 13 | "defineConstraints": [], 14 | "versionDefines": [], 15 | "noEngineReferences": false 16 | } -------------------------------------------------------------------------------- /Editor/com.bkk.chatgptscriptgenerater.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79f654cd26729c248b51fa521c22edd6 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kokyung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f67aa09536e89704499453da710391a0 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Unity ChatGPT Script Generator 2 | Unity ChatGPT Script Generater provides question ask to ChatGPT and script save in unity asset folder. 3 | 4 | **Now GPT-3.5 and GPT4 Supported.** 5 | 6 | ChatGPTScriptGenerator
7 | ### How to Install 8 | 9 | - Find manifest.json in Packages Folder and Add line like this. 10 | ``` 11 | { 12 | "dependencies": { 13 | "com.bkk.chatgptscriptgenerator": "https://github.com/Kokyung/ChatGPTScriptGenerator.git", 14 | ... 15 | }, 16 | } 17 | ``` 18 | ### How to Use 19 | - Go to Window -> BKK -> Chat GPT Settings 20 | - Type Open AI API Key. API Key can find from [Here](https://platform.openai.com/account/api-keys) 21 | - Go to Window -> BKK -> Chat GPT Script Generator. 22 | 23 | - Now you ready to use Chat GPT Script Generator. 24 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4dad8d4f6e70a104d848e25260166fe9 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.bkk.chatgptscriptgenerator", 3 | "version": "1.1.0", 4 | "displayName": "ChatGPT Script Generator", 5 | "description": "ChatGPT Script Generator provides question ask to ChatGPT and script save in asset folder.", 6 | "unity": "2020.3", 7 | "unityRelease": "0b5", 8 | "documentationUrl": "https://github.com/Kokyung/ChatGPTScriptGenerator#readme", 9 | "changelogUrl": "https://github.com/Kokyung/ChatGPTScriptGenerator/releases", 10 | "licensesUrl": "", 11 | "keywords": [ 12 | "ChatGPT", 13 | "ScriptGenerater", 14 | "ChatBot", 15 | "AI" 16 | ], 17 | "author": { 18 | "name": "Kokyung", 19 | "email": "kikikg0604@gmail.com", 20 | "url": "https://github.com/Kokyung" 21 | }, 22 | "type": "tool" 23 | } -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a399079781eb6494b9fdd61d4901733b 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | --------------------------------------------------------------------------------