Hey all! I am creating a script editor for Unity3D. It currently supports reading scripts but it can’t edit scripts because MonoScriptObject.text is read-only and I cannot modify the existing script. Do you know of any way I can modify a script using code?
Sounds like you need to overwrite the actual .js / .cs file in your file system. If Asset.CreateAsset doesn’t work, you could use System.IO functions to just write to the file, bypassing Unity’s classes altogether.
I thought of that, but how do I get the path of the original file through the MonoScript class?
Only thing I can think of is that you’ll have to get the object in such a way that you already know where it came from, using AssetDatabase.Load or something.
I actually have them drop the script (as an asset) on an object field. Is there any way I can get its path?
None that I know of. I did get tired of Unity’s useless object selector popup, so I wrote a quick little plugin that actually filters Project prefabs by type, using their path to locate them. You could alter this to find cs/js files, and store the object’s path along with the object (probably in the findings variable):
static function ObjectSelector( cur : UnityEngine.Object, environment : String, type : System.Type, allowHierarchy : boolean ) : UnityEngine.Object {
var objs : UnityEngine.Object[] = GetAll( type, environment, allowHierarchy );
GUILayout.BeginVertical();
GUILayout.BeginHorizontal();
for ( var ix : int = 0; ix < objs.length; ix++ ) {
if ( ix % 5 == 0 ) {
GUILayout.EndHorizontal();
GUILayout.BeginHorizontal();
}
if ( cur == objs[ix] ) {
GUILayout.Label(GUIContent(objs[ix].name,objs[ix].name),GUILayout.Width(100));
} else if ( GUILayout.Button( GUIContent(objs[ix].name,objs[ix].name), GUILayout.Width(100) ) ) {
cur = objs[ix];
}
}
GUILayout.EndHorizontal();
GUILayout.EndVertical();
return cur;
}
static private var findings : Hashtable;
static private function GetAll( type : System.Type, element : String, allowHierarchy : boolean ) : UnityEngine.Object[] {
var go : GameObject;
var accept : boolean = true;
if ( !findings ) findings = new Hashtable();
if ( GUILayout.Button("Refresh findings") || !findings.Contains(element) ) {
if ( findings.Contains(element) ) findings.Remove(element);
var obs : Array = new Array();
if ( allowHierarchy ) {
for ( var ob : UnityEngine.Object in Resources.FindObjectsOfTypeAll(type) as UnityEngine.Object[] ) {
obs.Add(ob);
}
} else {
var files : String[] = System.IO.Directory.GetFiles(Application.dataPath,"*.prefab", System.IO.SearchOption.AllDirectories);
var pathlen : int = Application.dataPath.Length+1;
for ( var ix : int = files.Length; ix > 0; ix-- ) {
files[ix-1] = "Assets\\" + files[ix-1].Substring(pathlen);
go = UnityEditor.AssetDatabase.LoadAssetAtPath( files[ix-1], GameObject ) as GameObject;
if ( go.GetComponent(type) ) {
obs.Add( go.GetComponent(type) );
}
}
}
// Debug.Log("Found " + obs.length + " " + type + " object" + (obs.length==1?"":"s"));
findings.Add(element, obs.ToBuiltin(type) as UnityEngine.Object[]);
}
return findings[element] as UnityEngine.Object[];
}
ObjectSelector works like an EditorGUILayout function (put it in Inspector or Window GUI functions):
var myScript : Script;
myScript = GUIUtils.ObjectSelector ( myScript, “AllScripts”, Script, false );
// script2 = GUIUtils.ObjectSelector(myScript,“AllScripts”, Script, false );
// texture = GUIUtils.ObjectSelector(myScript,“Textures”,Texture,false);