TransWikia.com

I'm trying to instantiate game object as a child of canvas in scene but it doesn't work

Game Development Asked by trojen on November 29, 2021

My problem is that I’ve prepared a class. Inside of this class i have a function to create a new modal window in scene as a child of canvas. I have another script in this script i am trying to create an object of first class and calling OpenModalWindow function through that object. It acctually spawns the modal window in the scene but not as a child of canvas.

The First Class:

public class WindowController : MonoBehaviour {
    public delegate void function();

    private Transform canvasTransform = null;
    private GameObject modalWindowObj = null;

    private void Awake()
    {
        canvasTransform = transform;
    }

    public void OpenModalWindow(GameObject modalWindow, string modalText, string button1Text, string Button2Text, function button1Func, function button2Func)
    {
        modalWindowObj = Instantiate(modalWindow, canvasTransform) as GameObject;
        this.modalWindowObj.transform.SetParent(canvasTransform);
    }
}

The Second Class:

public class ModalBoxTest : MonoBehaviour
{
    [SerializeField] private GameObject modalWindowRef = null;
    private WindowController test = new WindowController();

    private void OnTriggerEnter(Collider other)
    {
        if (other.gameObject.CompareTag("Player"))
        {
            test.OpenModalWindow(modalWindowRef, "deneme", "evet", "hayir", test1f, test2f);

        }
    }

    private void test1f()
    {
        Debug.Log("yes!");
    }

    private void test2f()
    {
        Debug.Log("no!");
        test = null;
    }
}

One Answer

private WindowController test = new WindowController();

This is not a safe way to create a type descending from MonoBehaviour. Unity warns you of this - so be sure you have warnings turned on in your Console window:

You are trying to create a MonoBehaviour using the 'new' keyword. This is not allowed. MonoBehaviours can only be added using AddComponent(). Alternatively, your script can inherit from ScriptableObject or no base class at all

These components have meaning only when they're attached to a GameObject, so creating one in this "free-floating" manner leaves it completely absent from your game scene, and unable to participate in most of the behaviours we expect from components - like having Unity call its lifecycle message functions including Awake().

Since Awake() never gets called on this object, the canvasTransform variable still has the value null by the time you call OpenModalWindow(). Instantiating something with the parent null means placing it at the root level of the scene hierarchy.

It looks like what you want to do here is attach an instance of the WindowController script on your Canvas in the editor when you're setting up your scene. Then get a reference to this existing instance inside your ModalBoxTest by one of the usual ways:

  • Make a public or [SerializeField] variable to hold the reference, and assign it at design time in the Inspector.

  • Use FindObjectOfType<WindowController>() to look up the current instance at runtime.

  • Use a singleton pattern or service locator to get the reference at runtime.

Or, if you don't have an existing Canvas that you want to attach to, you can spawn one at runtime like so:

// Create a new game object with the components we want.
var canvasObj = new GameObject("Canvas", new System.Type[] {
                     typeof(Canvas),
                     typeof(CanvasScaler) });

// For some reason, the raycaster doesn't seem to be 
// created properly unless we do it in a second step.
var raycaster = canvasObj.AddComponent<GraphicRaycaster>();

// Configure your canvas as desired.
var canvas = canvasObj.GetComponent<Canvas>();        
canvas.renderMode = RenderMode.ScreenSpaceOverlay;

// Add our controller last, so by the time it gets Awake
// all the other components are configured as we want,
// and it can read any configuration it needs from them.
windowController = canvasObj.AddComponent<WindowController>();

Answered by DMGregory on November 29, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP