gman gman - 4 months ago 17
C# Question

How to edit a MonoBehaviour's properties on a prefab in the UnityEditor from Script

Assume I have a simple

MonoBehaviour


public class FooScript : MonoBehaviour {
public int someValue = 0;
}


I make GameObject, attach a
FooScript
. I make a prefab from that and delete in instance in the scene.

In the editor I can select the prefab in the project and I can edit
someValue
.

Assuming I know the path to the prefab how I can make an edit time script that makes edits to the
FooScript
instance inside the prefab?

What've tried

GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(pathToPrefab);
GameObject root = ???? // WHAT DO I CALL HERE!?
FooScript fooScript = root.GetComponent<FooScript>();
fooScript.someValue = 789;


Actually in that case
prefab
is null

If switch to

Object prefab = AssetDatabase.LoadMainAssetAtPath(prefabPath);
GameObject root = prefab as GameObject;


prefab
is not null but
root
is

Next I tried this

Object[] objs = AssetDatabase.LoadAllAssetsAtPath(prefabPath);
foreach (var o in obs)
{
Debug.Log(" type:" + (o.GetType().Name));
}


That prints

type: GameObject
type: Transform
type: FooScript


But using that is a hacky solution as I'd have to try every GameObject and or FooScript. I means I suppose as a pragmatic solution it might work but it feels like adding technical debt I'll have to fix later

Other things I've tried is creating a new prefab with a new GameObject and a new FooScript and calling
PrefabUtility.ReplacePrefab


GameObject newGameObject = new GameObject();
FooScript fooScript = newGameObject.AddComponent<FooScript>();
fooScript.someValue = 789;

Object prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);
PrefabUtility.ReplacePrefab(newGameObject, prefab, ReplacePrefabOptions.ConnectToPrefab);

GameObject.Destory(newGameObject); // don't want this in the scene


But that's not working for me. The values in the prefab get replaced but all instances in the scene get disconnected.

To reiterate. I'm NOT trying to edit an instance of a prefab. I'm trying to edit the prefab itself from a script at edit time.

Answer
 // this fails
 GameObject prefab = 
    AssetDatabase.LoadAssetAtPath<GameObject>(pathToPrefab));

 // this fails
 GameObject prefab = 
    AssetDatabase.LoadAssetAtPath(pathToPrefab, typeof(GameObject));  

 // this succeeds
 GameObject prefab = 
    AssetDatabase.LoadAssetAtPath(pathToPrefab, typeof(Object)) as GameObject;