0
\$\begingroup\$

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;
    }
}
\$\endgroup\$
  • \$\begingroup\$ I'm confused that OpenModalWindow takes modalWindow as an argument, then tries to instantiate it. \$\endgroup\$ – Almo Jul 22 at 18:19
  • \$\begingroup\$ yeah sorry about undetailed info. it is an gameobject reference that takes a modalwindow prefab \$\endgroup\$ – trojen Jul 22 at 18:21
  • \$\begingroup\$ in this prefab there are 2 button and a panel inside of it. i am trying to instantiate this on the scene and make as a child of canvas \$\endgroup\$ – trojen Jul 22 at 18:23
  • \$\begingroup\$ Do not create MonoBehaviour objects with new. AddComponent is the correct way to create new instances, attaching them to a GameObject. \$\endgroup\$ – DMGregory Jul 22 at 18:24
  • \$\begingroup\$ does it makes that overridden? is that why i can't set parent? \$\endgroup\$ – trojen Jul 22 at 18:28
1
\$\begingroup\$
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>();
| improve this answer | |
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.