Reputation:
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
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
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
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)
Upvotes: 0