- Home /
Instantiate an object in a prefab?
I have a setup with some nodes to form a path for a moving platform, each with a custom editor UI button to instantiate the currently selected node, and set the newly made node as the next node in the path. This works fine, except it breaks when I try to make a prefab of the setup so I can drag-and-drop in more moving platforms later.
When I make it a prefab, everything seems fine at first - I can make a new node, and it's set as the next one along the path. However, the editor doesn't mark the first node as having been modified from the prefab, so when I hit play it reverts to the prefab - and the connection to the new node breaks. If I drag and drop in the new node as reference it works fine, but I wanted to try and make the button do all the work so I wouldn't need to worry about having to drag and drop for every node.
Is there a way to force the prefab to recognize that there's been an update when pressing the button? I'm guessing it's just not recognizing it, since I'm using custom UI. Is there a more graceful way to fix this?
I have just been playing around with custom editors. Are you using SerializedProperty and SerializedObject? Those are recommended when working around with prefabs and prefab instances.
The other way, by using customClass = (customClass)target
is apparently not that safe with prefabs. It requires you to use something like PrefabUtility.RecordPrefabInstanceProperty$$anonymous$$odifications
. This is a link: Link
Answer by newbdragoon · Sep 13, 2020 at 07:47 PM
Thanks for the help! I managed to get it working with customClass = (customClass)target and PrefabUtility.RecordPrefabInstancePropertyModifications - however, I'm not using SerializedProperty and SerializedObject since I didn't really realize that they were better to use, and I don't have any experiecne using them. Since I'm not using them, though, I can't Undo the creation of the new pathing nodes. This isn't the worst thing in the universe, but it would be nice. I tried a few different things with SerializedObject and couldn't quite figure out how to get it working, can anyone shed some light on what I might be doing wrong? Here's the relevant code, without using SerializedObject since I'm not sure how to correctly implement it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CustomEditor(typeof(PlatformPathNode))]
public class PlatformPathNodeUI : Editor
{
public override void OnInspectorGUI()
{
PlatformPathNode thisNode = (PlatformPathNode)target; //grabs the current object
if (GUILayout.Button("Create New Node"))
{
int c = thisNode.transform.parent.childCount;
Instantiate(thisNode.transform.GetComponent<PlatformPathNode>(), thisNode.transform.parent); //creates a clone of this node with the same parent
PlatformPathNode newNode = thisNode.transform.parent.GetChild(c).GetComponent<PlatformPathNode>(); //grab the new node
newNode.name = "Node " + (c - 1); //renames the new node to show its number in the child hierarchy
thisNode.nextNode = newNode; //sets the newly made node as the next one in the path
PrefabUtility.RecordPrefabInstancePropertyModifications(thisNode);
Selection.activeObject = thisNode.nextNode; //set the new node as active
}
}
}
Too be honest I don't quite manage to follow along. Do you really need this connection via thisNode.nextNode
? Everything is connected as next child within a transform anyhow isn't it? So you could just access it later by calling this from the Parent Transform:
foreach (Transform child in transform)
{
PlatformPathNode node = child.GetComponent<PlatformPathNode>();
node.DoSomeStuff();
}
Then you don't need to make any references at all. You can happily create your nodes in the scene, no?
However there is an actual Undo
class within Unity. You can find it HERE. So try writing Undo.RecordObject(thisNode, "Change on Node")
as the first thing in your GUILayout.Button part. $$anonymous$$aybe that's all you need.
Also how about this:
if (GUILayout.Button("Create New Node))
{
Undo.RecordObject(thisNode, "Change on Node");
PlatformPathNode newNode = Instantiate(thisNode, thisNode.transform.parent);
newNode.index = thisNode.index + 1;
thisNode.nextNode = newNode;
PrefabUtility.RecordPrefabInstanceblablalba;
Selection.activeSelection = blablabla;
}
I am not experienced enough with SerializedProperty and SerializedObject to help you with that.
Your answer
Follow this Question
Related Questions
Instantiate specific object from "FindGameObjectsWithTag" Array 0 Answers
instantiating a projectile continually over time 2 Answers
Adding prefabs to a list or an array from a folder and instantiating them. 2 Answers
How to Instantiate a GameObject from a ScriptableObject piece of script? 0 Answers
How prefab the instance works? 1 Answer