- Home /
Immediate editor inside unity
I found code herefor a C# immediate window to run inside unity editor, but could not get it to work. (Error running gmcs: Cannot find the specified file) I hacked around a bit with paths and compilers but couldn't get it. Could anyone lend a hand?
(I'm just learning C# and have a free community edition Visual Studio where I see there is also a non-working "immediate window". - or - user error? Either way ... inside of unity would be the bomb. Thanks all for the community, it helps with the learning! )
I use Unity 5.6.1f1 and the provided code works out-of-the-box for me. However there's a small issue in the code. It will treat any warning as error and not execute the code. There's however an easy fix to ignore warnings:
// compile an assembly from our source code
var result = codeProvider.CompileAssemblyFromSource(options, string.Format(scriptFormat, scriptText));
bool successful = true;
// log any errors we got
foreach (CompilerError error in result.Errors)
{
// the magic -11 on the line is to compensate for usings and class wrapper around the user script code.
// subtracting 11 from it will give the user the line numbers in their code.
if (error.IsWarning)
Debug.LogWarning(string.Format("Immediate Compiler Warning ({0}): {1}", error.Line - 11, error.ErrorText));
else
{
Debug.LogError(string.Format("Immediate Compiler Error ({0}): {1}", error.Line - 11, error.ErrorText));
successful = false;
}
}
if (successful)
{
var type = result.CompiledAssembly.GetType("ImmediateWindowCodeWrapper");
lastScript$$anonymous$$ethod = type.Get$$anonymous$$ethod("PerformAction", BindingFlags.Public | BindingFlags.Static);
}
You should be more specific when and where you get that error. Did you actually copy the full error from the console? copy&paste? What Unity version do you use? What scripting backend do you have selected in your project? Also note that the immediate code can not access any class from your project as the assemblies are not added to the references in the compiler options. What's the code you try to execute in the immediate window?
Answer by KittenSnipes · Feb 09, 2018 at 07:14 AM
I spent my time to make this cool script. It runs even during edit mode but is not exactly what you wanted but I hope its ok. Btw you need to add it to a gameObject but it could be an empty gameObject. Then just drag the script on it and do what you wish. Cheers:
Script:
using UnityEngine;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
[ExecuteInEditMode]
public class ImmediateWindow : MonoBehaviour
{
public List<string> codeToUse;
//The new scripts name
public string scriptName;
public void UpdateScript()
{
//This is the directory where the file will be put
string directoryLocation = Application.dataPath + "\\";
//Clears the file for re-writing
File.WriteAllText(directoryLocation + scriptName + ".cs", string.Empty);
//This writes the new file but it will be empty
using (StreamWriter newWriter = new StreamWriter(directoryLocation + scriptName + ".cs", true))
{
//The rest of this writes what you want your file to contain
newWriter.WriteLine("using UnityEngine;");
//This is an empty line because I like having spaces :D
newWriter.WriteLine();
//Here is the thing that writes the public script class
newWriter.WriteLine("public class " + scriptName + " : MonoBehaviour {");
//Another lovely space ;)
newWriter.WriteLine();
//This reads the list of strings
for (int i = 0; i < codeToUse.Count; i++)
{
//This writes each new string in to the file
newWriter.WriteLine(codeToUse[i]);
}
//The ending curlie bracket of the class
newWriter.WriteLine("}");
}
//Tells us the class is done writing
Debug.Log("Writing Of Script Done!");
}
}
//This makes that cool update button
//It references the class we made
[CustomEditor(typeof(ImmediateWindow))]
//This is our editor class that references Editor
//So we can edit and put our button in the Editor
public class ImmediateWindowEditor : Editor
{
//This overrides the Inspector's GUI for editing
public override void OnInspectorGUI()
{
//This draws how the inspector looks already
DrawDefaultInspector();
//This references the class we made
ImmediateWindow window = (ImmediateWindow)target;
//This makes our cool button and says if we press it
if (GUILayout.Button("UpdateScript"))
{
//Update our script
window.UpdateScript();
//Refresh all the assets so the script loads properly
AssetDatabase.Refresh();
}
}
}
Wonderful! Way to think outside the box! I'm going to tweak it and see what you think.
Answer by ballz · Feb 10, 2018 at 05:05 AM
@KittenSnipes must go in editor folder. pardon my hacky code, nowhere near as nice as yours.
using UnityEngine; using UnityEditor; using System.IO; using UnityEngine.SceneManagement;
public class CWindow : EditorWindow { // script text private string scriptText = "UnityEngine.Debug.Log(\"Hello World\");" ;
// reusable script file to store C#
string scriptName = "CWindowTemp";
//the new script to execute
private MonoBehaviour mb ;
//a root object where we park the temporary MonoBehaviour component
private GameObject go;
// position of scroll view
private Vector2 scrollPos;
void OnGUI()
{
// start the scroll view
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
// show the script field
string newScriptText = EditorGUILayout.TextArea(scriptText, GUILayout.Height(position.height - 10));
// close the scroll view
EditorGUILayout.EndScrollView();
if (newScriptText != scriptText)
{
// if the script changed, update our cached version and null out our cached method
scriptText = newScriptText;
}
// store if the GUI is enabled so we can restore it later
bool guiEnabled = GUI.enabled;
// disable the GUI if the script text is empty
GUI.enabled = guiEnabled && !string.IsNullOrEmpty(scriptText);
// show the execute button
if (GUILayout.Button("Run"))
{
UpdateScript(scriptText);
// restore the GUI
GUI.enabled = guiEnabled;
}
}// onGui
[MenuItem("Window/CWindow")]
static void Init()
{
//var window = GetWindow(EditorGUILayoutTextArea);
//window.Show();
// get the window, show it, and hand it focus
var window = GetWindow<CWindow>("CWindow", false);
window.Show();
window.Focus();
}
public void UpdateScript(string scriptText)
{
//This is the directory where the file will be put
//string directoryLocation = Application.dataPath + System.IO.Path.PathSeparator;
string directoryLocation = Application.dataPath + "/Scripts/";
//Clears the file for re-writing
File.WriteAllText(directoryLocation + "CWindowTemp.cs", string.Empty);
//This writes the new file but it will be empty
using (StreamWriter newWriter = new StreamWriter(directoryLocation + "CWindowTemp.cs", true))
{
//The rest of this writes what you want your file to contain
newWriter.WriteLine(string.Format(scriptFormat, scriptText));
}
//Tells us the class is done writing
Debug.Log(Application.dataPath + " Done!");
//Refresh all the assets so the script loads properly
AssetDatabase.Refresh();
// Get the root object
go = SceneManager.GetActiveScene().GetRootGameObjects()[0];
mb = go.AddComponent<CWindowTemp>();
mb.hideFlags = HideFlags.HideInInspector;
//enabling the behaviour will trigger the OnEnabled method with our code
mb.enabled = true;
mb.enabled = false;
DestroyImmediate(go.GetComponent<CWindowTemp>());
}
// here is a template for your scripting... add or delete as needed
static readonly string scriptFormat = @"
using System; using System.Reflection; using System.Runtime.CompilerServices; using System.Collections; using System.Collections.Generic; using System.Text; using System.Linq;
using UnityEngine; using UnityEditor; using UnityEngine.SceneManagement;
using basil.util;
[ExecuteInEditMode] public class CWindowTemp : MonoBehaviour {{ public void OnEnable() {{ // user code goes here {0}; }} }}";
}
Your answer
Follow this Question
Related Questions
How can I instantiate a prefab/s in all loaded scenes or in selected scenes from list ? 1 Answer
Multiple Cars not working 1 Answer
How can i add a second camera that will be showing only specific gameobject in game window ? 1 Answer
Distribute terrain in zones 3 Answers
How can I use linerenderer with world space and to be able to move the objects ? 1 Answer