user128511
user128511

Reputation:

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.

Upvotes: 1

Views: 1380

Answers (3)

Jeanc
Jeanc

Reputation: 1

you need to load a GameObject like this :

 string prefabPath = "Assets/demo1/Resources/GameObject.prefab";
    Object prefab = AssetDatabase.LoadAssetAtPath<GameObject>(prefabPath);

Don't forget the suffix name

Upvotes: 0

ColmanJ
ColmanJ

Reputation: 456

 // 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;

Upvotes: 1

ColmanJ
ColmanJ

Reputation: 456

just cast the loaded object to a GameObject

Object prefab = AssetDatabase.LoadAssetAtPath(pathToPrefab, typeof(GameObject));
GameObject root = prefab as GameObject; //a prefab is also just a gameobject
FooScript = root.GetComponent<FooScript>();
root.someValue = 789;

don't forget to save the changes

EditorUtility.SetDirty(prefab)

AssetDatabase.SaveAssets

Upvotes: 0

Related Questions