- Home /
Get dirty state from a scene
Hi Uniteers, I am currently looking for the possibility to identify whether the current open scene is dirty or not.
What I am trying to develope is an editor tool that can inform multiple members on a team if someone have made a change to a scene. This is to avoid that multiple members are working on the same scene file, and hopefully prematurely catch an upcomming merge error related to version control such as when using Git / Asset Server. However, I am required to inform my editor script when the scene becomes dirty, but I can't seem to find any methods which does that. Any advice, or am I missing something?
Answer by AmitSuri · Mar 04, 2019 at 12:07 AM
Workaround Solution: Thanks to @arelian11
Workaround Solution:
Attach this to a game object in your scene and save the scene. Now every time you compile and if you scene is marked dirty it will be detected by this code and logged. Click on the logged line in console and it will point you the offending gameobject that is marking the scene dirty. Next, check the parent of the target game object of grandparent or so on...and if you see that it has a scroll rect, fix the floating values on the scroll rect to be rounded integers instead of floating values.
This will fix the bug and the scene won't be marked dirty anymore. My scene had 30 or so objects that had this problem fixed it in 5 mins. No more version control bloat and more problems in sharing scene file.
public class SceneDirtyFlagChecker : MonoBehaviour
{
static SceneDirtyFlagChecker()
{
Undo.postprocessModifications += OnPostProcessModifications;
}
private static UndoPropertyModification[] OnPostProcessModifications(UndoPropertyModification[] propertyModifications)
{
Debug.LogWarning($"Scene was marked Dirty by number of objects = {propertyModifications.Length}");
for (int i = 0; i < propertyModifications.Length; i++)
{
Debug.LogWarning($"currentValue.target = {propertyModifications[i].currentValue.target}", propertyModifications[i].currentValue.target);
}
return propertyModifications;
}
}
Answer by frarees · Oct 03, 2014 at 02:05 PM
Currently (4.5.4f1) I see no public API to access dirty state of an object.
However, via reflection you can access bool EditorUtility.IsDirty (int instanceID)
.
Alright, this seems like a plausible approach. I'll return with my results.
Alright, I am having trouble making this work. I am lurking through the EditorUtility class, but I can't find any private methods or variables within that class. Are these private variables and methods hidden from us even as we inspect the class in our editors? I used the following code, however, I don't see the IsDirty method.
System.Type type = typeof(EditorUtility);
foreach($$anonymous$$ethodInfo methodInfo in type.Get$$anonymous$$ethods())
Debug.Log (methodInfo.Name); // Prints a long list of public methods
foreach(FieldInfo fieldInfo in type.GetFields())
Debug.Log (fieldInfo.Name); // Returns nothing
You need to specify some binding flags to get them. In this case, try with:
type.Get$$anonymous$$ethods (BindingFlags.Static | BindingFlags.NonPublic);
I have moved one step further now. I have now managed to access the IsDirty method, however I am having trouble detecting the IsDirty state, but scene is never registered as being dirty regardless of changing hiearchy order, adding/removing hiearchy items nor changing inspector values
void SomeFunction()
{
System.Type type = typeof(EditorUtility);
$$anonymous$$ethodInfo methodInfo = type.Get$$anonymous$$ethod("IsDirty", BindingFlags.Static | BindingFlags.NonPublic); // Get the method IsDirty
Object scene = AssetDatabase.LoadAssetAtPath(EditorApplication.currentScene, typeof(Object)); // Get the Scene Object from the assets
int instanceID = scene.GetInstanceID(); // Get the Scene Object's instance ID
bool isDirty = (bool)methodInfo.Invoke(this, new System.Object[1]{instanceID}); // Execute the referenced method
if(isDirty)
Debug.Log ("Is dirty"); // Is dirty is never called.
}
Update, the above posted code is functional for objects such as Prefabs within assets.
Answer by arelian11 · Feb 05, 2015 at 10:29 PM
I know this is a somewhat old question, but I've found a possible answer. I thought I'd post it here for reference.
It turns out, there is a callback that Unity triggers whenever an object is modified anywhere in the editor. It doesn't apply to the scene alone, but it will track scene changes.
public static bool sceneIsDirty = false;
static SceneDirtyChecker() {
Undo.postprocessModifications += OnPostProcessModifications;
}
static UndoPropertyModification[] OnPostProcessModifications(UndoPropertyModification[] propertyModifications) {
sceneIsDirty = true;
return propertyModifications;
}
All you have to do is manage the sceneIsDirty flag, and you're good to go!
Your answer
Follow this Question
Related Questions
Object Painter Editor Help 1 Answer
How to make Textured Wire mode non-transparent 0 Answers
Post-Process All Unity Scene GameObjects 1 Answer
Unity 4.6 Copying Complex GameObjects Between Scenes Resets Fields In the Editor 2 Answers
How can I make a custom 3d editor within the Unity editor? 1 Answer