I have a piece of code that creates a new file and adds it as a ‘component’ to an object in the gameworld. the code works fine if i already have the file before the game begins. however, if the file is created during the game, i get the error cannot add as component as file does not exist. I initially though this to be a race condition and timing issue. So i created the files on the fly way before they would be accessed. But still the problem remains. I can see the files created in ‘explorer’ but unity does not seem to refresh them on the fly… am i missing something?
Do you plan on doing this in your actual published content? It would seem a dubious idea to begin with as you won’t likely get proper compilation anyway. I’m not sure about the answer in specific, it may not “refresh” in terms of seeing your new script and compiling it properly.
What file are you creating? How are you creating it? Why can’t that file be created ahead of time?
i am building a gaming platform on unity and the modified editor itself is the product. so there are cases where the user types something in UnityGUI and that needs to be fed back into the game world. in fact the user types the code to be executed and hence i will have to add this created file as a component. so my question was ‘does unity automatically pick up the newly created files in the assests folder and consider them as identical to the files that existed before running the game/unitygui?’ or how do i go about doing this?
i am creating the file using C# StreamWriter.
Thanks in advance.
I guess Unity needs to be forced to update it’s assets in this case (it normally updates when you switch Unity from the back to front, since that is when other Applications might have modified assets). Try calling AssetDatabase.Refresh().
thanks for that. after using AssetDatabase.Refresh( ) I can see the file that got created. however, I seem to be getting this error
NullReferenceException: Object reference not set to an instance of an object
UnityEditor.DockArea.EndOffsetArea ()
UnityEditor.DockArea.OnGUI () (at C:\builds\unity-trunk\unity\Editor\Mono\GUI\DockArea.cs:499)
UnityEditor.GUIView:Internal_SendEvent(Event)
UnityEditor.GUIView:Internal_SendEvent(Event)
UnityEditor.GUIView:SendEvent(Event) (at C:\builds\unity-trunk\unity\Editor\Mono\Generated\EditorWindow.cs:977)
UnityEditor.PopupCallbackInfo:SetEnumValueDelegate(Object, String[], Int32) (at C:\builds\unity-trunk\unity\Editor\Mono\Generated\EditorGUI.cs:1177)
System.MulticastDelegate:invoke_void_object_string[]_int(Object, String[], Int32)
Not sure what to do next ?
Recompiling scripts causes reloading of assemblies, which will kill the current state of some objects (which can lead to errors when done at inconvenient times).
From where are you calling AssetDatabase.Refresh()? Possibly using EditorApplication.LockReloadAssemblies() paired with EditorApplication.UnlockReloadAssemblies() in a smart way may prevent you from getting such errors.
I tried inserting EditorApplication.LockReloadAssemblies( );
in every part of my code, but to no avail. I am not sure how it works in the first place. here is my code:
void OnGUI()
{
//static function Popup (position : Rect, selectedIndex : int, displayedOptions : string[], style : GUIStyle = EditorStyles.popup) : int
level0ToolbarStrings[0] = "None";
level0ToolbarStrings[1] = "Create Event";
level0ToolbarInt = EditorGUI.Popup( new Rect (10, 10, 180, 30), "Event Creator", level0ToolbarInt, level0ToolbarStrings);
if( level0ToolbarInt == 0 ){
createNewObject = true;
}else if( level0ToolbarInt == 1 ){ //if the Event Creator has been selected
if( createNewObject ){
conditionNumber += 1;
eventObjectName = "Event_" + conditionNumber ;
GameObject g = new GameObject( eventObjectName );
createdObjectNumber = conditionNumber;
GameObject.Find(eventObjectName).AddComponent( "ConditionSelectionCreator" );
createNewObject = false;
}
level1ToolbarStrings[0] = "None";
level1ToolbarStrings[1] = "Condition";
level1ToolbarStrings[2] = "Selection";
level1ToolbarInt = EditorGUI.Popup( new Rect (10, 40, 180, 60), "Create", level1ToolbarInt, level1ToolbarStrings);
if( level1ToolbarInt == 1 ){ //user selected a condition
level21ToolbarStrings[0] = "Select Submit Here";
level21ToolbarStrings[1] = "Sumbit Condition";
textAreaString = EditorGUI.TextArea (new Rect (110, 80, 310, 180), textAreaString);
level21ToolbarInt = EditorGUI.Popup( new Rect (10, 280, 180, 300), "Sumbit Here", level21ToolbarInt, level21ToolbarStrings);
if( level21ToolbarInt == 1){ //user wants to sumbit the condition
Debug.Log("Current Value for the condition: " + textAreaString );
//open a file with the condition number __ ObjectID_Condition_<ConditionSelection_Number> __ and write this condition into it
string conditionFile = "_ConditionFile_" + conditionNumber + ".js";
string conditionFileToCreate = "_ConditionFile_" + (conditionNumber+1) + ".js";
TextWriter createNewFile = new StreamWriter("Assets\\" + conditionFileToCreate );
createNewFile.WriteLine( "//Condition to Trigger an event" );
createNewFile.Close( );
//string conditionFile = "_ConditionFile_0.js";
TextWriter tw = new StreamWriter("Assets\\" + conditionFile, true );
tw.WriteLine( textAreaString );
tw.Close( );
GameObject.Find(eventObjectName).AddComponent( conditionFile.Substring(0, conditionFile.Length-3) );
TextReader tr = new StreamReader("Assets\\" + conditionFile);
Debug.Log( "Reading from the written FILE " + conditionFile );
Debug.Log(tr.ReadLine());
tr.Close();
//AssetDatabase.Refresh( );
//EditorApplication.UnlockReloadAssemblies( );
level21ToolbarInt = 0;
level1ToolbarInt = 0;
}
}
Basically everytime an object is created, we write a condition for it… and a condition file is created each time that needs to be attached as a component to the newly created object. Could you please suggest if Assembly loading is indeed the problem? any ways to go around the problem?