Hi there !
I’m currently making an in-editor tool that is creating, parenting, deleting children inside a prefab. But no matter what method I call before or after editing my object, changes are lost when I quit the prefab mode. To test faster, I’ve unchecked the auto save option, so I guess it will work when the save button will be activated.
I’ve tried before edition: Undo.RecordObject(transform, "update branches");
and then after:
It’s unclear why this doesn’t work for you. Is ‘transform’ the changed object that’s part of the Prefab contents in Prefab Mode? Posting the entire script might help.
I’m basically making changes on children, destroying some, creating others, renaming, etc…
Here’s an example, when enabling the script it will rename randomly children:
using UnityEngine;
[ExecuteAlways]
public class TestEditPrefabMode : MonoBehaviour
{
private void OnEnable()
{
foreach(Transform child in transform)
{
child.name = Random.Range(0, 1000).ToString();
}
this.enabled = false;
}
}
using UnityEditor;
using UnityEngine;
[ExecuteAlways]
public class TestEditPrefabMode : MonoBehaviour
{
private void OnEnable()
{
foreach(Transform child in transform)
{
child.name = Random.Range(0, 1000).ToString();
}
PrefabUtility.ApplyPrefabInstance(gameObject, InteractionMode.AutomatedAction);
this.enabled = false;
}
}
Unity freezes for a long time and then it’s quite broken, even if my prefab is an empty root with 6 children. I’m using the latest beta (b9).
Edit: it looks like this code is working, but as I said it freezes the editor for a solid minute, and then the UI is blocked (apart the upper part) so I have to relaunch the project. And after relaunching I can confirm the edition worked. Do you have the same behavior?
Any chance you can file a bug report with an attached project ans step to reproduce? Makes it easier for us to understand what you are doing and verify the issue. Any attached project is only available to Unity employees for testing.
If your script is intended to run in Prefab mode it only makes sense to call Apply if your object is a nested prefab or a variant.
If you haven’t seen it already here is my presentation from Unite LA, giving some insights into how Prefabs works now and some scripting examples
I was there in person haha But pretty sure I missed a lot of stuff.
But yes, I’m trying to apply changes inside the prefab mode, but not to a nested prefab, only regular child objects.
I will watch it again, there was a lot of useful informations.
Thanks again !
The key is not to use SceneManager.GetActiveScene() as the argument in EditorSceneManager.MarkSceneDirty()
I believe this is because SceneManager.GetActiveScene() does not actually return the prefab editing scene, whereas the ‘scene’ property of the gameobject does.
You should in general not use SceneManager.GetActiveScene for that - even if you’re not in the prefab scene, you could be in a multi-scene setup, and the object you’re editing doesn’t need to be in the active scene.
This is the first time I use the prefab utilities, so I guess I’m missing something.
In short, I have several cars, when I cycle through them, inside a for loop I assign the actual car as a GameObject called “activeCar”. Then, when I buy an upgrade, the “buy” button calls the method “CarUpgrade”. Inside this method I try to update the active car prefab. As I said, this is the first time I use this, so I guess I’m missing something.
This is what I’m doing:
ArgumentNullException: Value cannot be null. Parameter name: obj
It points me to the line where I call the PrefabUtility, but activeCar is an actual GameObject… What am I missing?
One more thing, this code is outside the activeCar, before writing this code I called the PrefabUtility from within the BuyUpgrade() method, located on one activeCar script. So, what is the best way to do this?
I had the same exception. I actually fixed it by by using InstantiatePrefab instead of LoadPrefabContents. I think its because the latter doesn’t return a normal instance but rather an “isolated instance”.
When using LoadPrefabContents, one has to use SaveAsPrefabAsset.