- Home /
Prefab modified by script in Editor loses changes when IsPlaying
Looked all over, no solution. This is simple. I drag and drop a prefab onto my scene. It's built in script randomly resizes it. That works fine. But when I run it, the prefab gets resized again.
I control whether or not to run the resize routine with a public boolean, and a private boolean. Basically, when the user checks the box to make it Unique, it runs the resize and sets the private boolean to show that it's already been done, so that it doesn't run in every iteration of Update.
Works great in Editor. I can resize and restore to my heart's content. But when I run it, apparently the value for the private bool is being lost because it's running the resize routine. And when I stop the run, it runs it again.
I need this to resize once, in the editor, on command, and then remember those settings/scale when it's run and when the run is stopped. I'm not using a custom editor, but I've tried SetDirty, and Serialization. Nothing is working.
Here is most of the code, the part that controls when the resize (Randomize) function is run. #if UNITY_EDITOR using UnityEngine; using UnityEngine.UI; using UnityEditor; using System.Collections;
[ExecuteInEditMode]
public class AlienEditor : MonoBehaviour {
public bool MakeUnique;
private bool IsUnique; // To determine if we need to change it.
// Use this for initialization
void Start () {
// Not doing anything in here!
}
// Update is called once per frame
void Update () {
// Don't do this when the game is running, only in the editor
if (!Application.isPlaying)
{
// Make it unique
if ((MakeUnique) && !(IsUnique))
{
Debug.Log("Time to Make Unique!");
Randomize(gameObject.transform);
IsUnique = true;
EditorUtility.SetDirty(gameObject);
}
// Make it standard
if (!(MakeUnique) && (IsUnique))
{
Debug.Log("Time to Load the Prefab!");
Reset();
IsUnique = false;
}
}// Not Playing
}
}
#endif
Answer by _dns_ · Apr 24, 2015 at 08:35 PM
Hi, yes, the private variables are not serialized so it resets when the game runs.
There are other way of doing this in the editor, depending on your needs:
1-Use the OnValidate() callback. It's called in editor only and only when a value is changed in the inspector. So during this callback, you could test the value of the MakeUnique bool, and if true: randomize, if false, reset.
2-Use a menu extension with option to randomize or reset the selected object (use the Selection editor object to know what object is selected)
3-use a context menu attribute with a randomize & a reset item.
4-Use an editor window so you can design lots of options and feedback to the user
To call something when instantiating in the editor, there is also the OnEnable() callback that is called in editor & in game when the ExecuteInEditMode attribute is used. It might be more convenient than Update().
I hope some of those options will help ! EDIT: there is also the SerializeField attribute to serialize a private variable.
I figured out a solution. I made the variables public ins$$anonymous$$d of private and serialized, but used HideInInspector. This fixed one problem, so now it only modifies the instance when I tell it to, but I still have one problem:
-Prefab instance that is clearly modified in the editor reverts to original Prefab when Playing.
Tried EditorUtility.SetDirty(gameObject); but it still reverts to the prefab size when I hit Play, but restores to the scaled size when I stop and go back to the editor.
Hummm, ok, I had such a problem in some occasions: modifying an object's property but it keeps reverting to the prefab value. The solution is to modify the instance's property in the scene using PrefabUtility.getProperty$$anonymous$$odification (and Set...). It's a little painful but worked for me as last resort.
I don't know why sometimes I can modify one object's property without problems and sometimes I need to use those PrefabUtility functions. I guess it may depend on when the property are modified (= from what callback).
Interesting. I saw those functions in my travels to solve this, but didn't see any code or even good definitions. It's weird that I can manually scale something in Editor and it sticks, but if a script does it, it does not. I'll try the SetProeprty$$anonymous$$odification, but I think I'm also going to post a bug about this.
[EDIT]: Everything I've seen about SetProperty$$anonymous$$odification looks like it's for bringing an instance back to look like the prefab, not the other way around. I don't think this will help me. I want the original prefab left untouched, and the instance to be changed in the Player to match how it was changed in the editor.
Answer by nbhagatx098771 · Jan 18, 2019 at 03:37 AM
yes, i had the same issue, the changes made by my editor script are getting stored on nonprefab but for prefabs, it was getting reset at a run time.
Here is the method you need to call to store it PrefabUtility.RecordPrefabInstancePropertyModifications(Gameobject.component)
you need to pass the component (script name) whose variable is changed.
Answer by Tanoshimi2000 · Apr 27, 2015 at 10:18 PM
Found the problem. It turned out my custom animations contained keyframes for Scale, and this was overriding the editor scaling.