Show / Hide Table of Contents

Referencing A Canvas Controller From Its View Components

It is sometimes required that scripts within a canvas controller's view prefab obtain a reference to their owning canvas controller. For example, we might want to trigger a manual transition on the canvas controller after a time delay. Perhaps something like this:

public float delay;
public string transitionIdentifier;

private float elapsedTime;

private void Update()
{
    // Wait for the required time.
    elapsedTime += Time.deltaTime;
    if (elapsedTime >= delay)
    {
        // Perform the transition when the required time has elapsed.
        PerformGraphTransitionWithIdentifier(transitionIdentifier, this);
    }
}

However, if you were to add this code to a CanvasController script, you would find that the Update method is never called. This is because canvas controllers are ScriptableObjects, not MonoBehaviours, and they therefore do not have an Update method as MonoBehaviour does.

The solution then, is to place the above code in a MonoBehaviour script, PerformTransitionAfterDelay, and add it to a game object in our canvas controller's view prefab.

public class PerformTransitionAfterDelay : MonoBehaviour
{
    public float delay;
    public string transitionIdentifier;

    private float elapsedTime;

    private void Update()
    {
        // Wait for the required time.
        elapsedTime += Time.deltaTime;
        if (elapsedTime >= delay)
        {
            // Perform the transition when the required time has elapsed.
            PerformGraphTransitionWithIdentifier(transitionIdentifier, this); // <-- Error
            enabled = false;
        }
    }
}

This, however, poses a second problem - the call to PerformGraphTransitionWithIdentifier. PerformGraphTransitionWithIdentifier is a method on the CanvasController class, and now that we are no longer within our CanvasController script, we need to obtain a reference to the canvas controller in order to invoke PerformGraphTransitionWithIdentifier on it.

Canvas View Owner Bindings

Any script within a canvas controller's view prefab can obtain a reference to the owning canvas controller by using the Canvas View Owner Bindings object available in the view hierarchy - specifically its On Bound To Owner event.

When a canvas controller instantiates its view prefab, the view is bound to its owning canvas controller. This binding process binds the view references and callbacks to the canvas controller whom loaded it - its owner. Upon completion this process invokes the OnBoundToOwner event, passing the owning canvas controller to allow any components in the view (view objects) to also bind accordingly.

Note

This binding process occurs before the canvas controller's ViewDidLoad method is invoked, and before any MonoBehaviours have their Start method called.

On Bound To Owner

Looking at the Canvas View Owner Bindings' OnBoundToOwner event definition, we can see that the event passes a single CanvasController argument - the owner. We can therefore add a public method to our MonoBehaviour script, called Configure, that takes a single CanvasController argument. In this method we will store the owning canvas controller, allowing us to later call PerformGraphTransitionWithIdentifier on it, once the required time has elapsed.

public class PerformTransitionAfterDelay : MonoBehaviour
{
    // Specify the amount of time to wait in the inspector.
    public float delay;
    // Specify the transition identifier to invoke in the inspector.
    public string transitionIdentifier;

    private CanvasController canvasController;
    private float elapsedTime;

    // Add this method to the Canvas View Owner Bindings' On Bound To Owner event.
    public void Configure(CanvasController canvasController)
    {
        this.canvasController = canvasController;
    }

    private void Update()
    {
        // Wait for the required time.
        elapsedTime += Time.deltaTime;
        if (elapsedTime >= delay)
        {
            // Perform the transition when the required time has elapsed.
            canvasController.PerformGraphTransitionWithIdentifier(transitionIdentifier, this);
            enabled = false;
        }
    }
}

Now all that is left is to connect our script to the OnBoundToOwner event in the inspector.

Conclusion

And that's it. Our PerformTransitionAfterDelay MonoBehaviour, which is placed in the canvas controller's view prefab, will now be configured with the owning canvas controller upon load. After the specified time has elapsed, the identified transition will be triggered on the owning canvas controller.

This technique can be used for much more than just triggering a transition after a time delay. You could create a MonoBehaviour to listen to game events or accelerometer changes, to name a few ideas. The key insight is the use of the Canvas View Owner Bindings' On Bound To Owner event for obtaining a reference to the owning canvas controller in view scripts.

Back to top © 2019 Pelican 7 LTD. All rights reserved.