0
\$\begingroup\$

I have a custom UI element and I would like to instantiate it from Hierarchy like you do with any other UI element (button, text etc.). I know how to do this so it is instantiated in the scene but how to make it instantiate exactly like UI elements so it gets instantiated onto a canvas?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Ok so I figure it out here is the creation code:

  public static void CreateUIObject(string path)
{
    GameObject selectedObject = Selection.activeGameObject;

    if(selectedObject != null)
    {
        //If selected object contains canvas
        if(selectedObject.GetComponentInParent<Canvas>())
        {
            GameObject newObject = GameObject.Instantiate(Resources.Load(path),
            Selection.activeGameObject.transform) as GameObject;
            newObject.name = path;
            Place(newObject);

        }
        else
        {
            GameObject newCanvas = GameObject.Instantiate(Resources.Load("Canvas"),
                Selection.activeGameObject.transform) as GameObject;
            newCanvas.name = "Canvas";
            Place(newCanvas);
            GameObject newObject = GameObject.Instantiate(Resources.Load(path),
            newCanvas.transform) as GameObject;
            newObject.name = path;
            Place(newObject);
        }
    }
    else
    {
        GameObject newCanvas = GameObject.Instantiate(Resources.Load("Canvas")) as GameObject;
        Place(newCanvas);
        newCanvas.name = "Canvas";
        GameObject newObject = GameObject.Instantiate(Resources.Load(path),
        newCanvas.transform) as GameObject;
        newObject.name = path;
        Place(newObject);
    }
}


public static void Place(GameObject gameObject)
{
    // Find location
    SceneView lastView = SceneView.lastActiveSceneView;
    gameObject.transform.position = lastView ? lastView.pivot : Vector3.zero;

    // Make sure we place the object in the proper scene, with a relevant name
    StageUtility.PlaceGameObjectInCurrentStage(gameObject);
    GameObjectUtility.EnsureUniqueNameForSibling(gameObject);

    // Record undo, and select
    Undo.RegisterCreatedObjectUndo(gameObject, $"Create Object: {gameObject.name}");
    Selection.activeGameObject = gameObject;

    // For prefabs, let's mark the scene as dirty for saving
    EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene());
}

And here is the part that calls this methode in the asset menue:

  [MenuItem("GameObject/UI/ArrowSelector(TMP)", priority = -50)]
private static void CreateArrowSelector()
{
    CreateUtility.CreateUIObject("ArrowSelector");
}

So first I get the selected object from the hierarchy. If it isn't null I check if that object or any of his parents contains canvas GameObject, if it does I instantiate my object Under it. If not I create new canvas (note that I put a canvas prefab into a resource folder because I don't know how to use Unitys default one) and use it as a parent for my UI object.

If selected object is null I just do the same thing as if there is no canvas on selected gameobject but without assigning a parent to the canvas.

I copied place function from a tutorial it handles some Unity tooling stuff like undo redo and not sure what else.

These are editor scripts so make sure to place them in Editor folder.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .