Create a static instance of a script

Hello,

I was wondering if there was a way to create a static instance of a script and then make method calls to it from a different script.

So in c# I would create something like:

public class MenuController{
    
    public static MenuController instance;

    public void ClickedButton(int btnID){
        //do something with the btnID
    }
}

And the I could create a separate class to put on the different buttons that could make a call to the main controller script:

public class MyButton{
    public int myID = 0;
    public void OnClick(){
        MenuController.instance.ClickedButton(myID);
    }
}

I see some people appear to use “this.app.on” and “this.app.fire” but I was wondering if there was just a way to create a static instance to make those calls instead.

Thanks!

Technically, javascript doesn’t have classes, so everything is pretty much a function. There is a sugar syntax that would make them look like a class, but they are still functions. As such, you can just call them directly. Here is how you could do it:

Let’s say you have a parent element and a child. Parent has a MenuController script and a button child has MyButton script.

menu-controller.js

/* jshint esversion */
class MenuController extends pc.ScriptType {
    initialize() {
        // called automatically by engine
        // you can consider it is as a constructor of a class that is initialized for you
        // you can add some properties here, related to MenuController, e.g.
        this.word = 'some text';
    }
    
    clickedButton(id) {
        const idButton = id;  // id === 'some id'
    }
}
pc.registerScript(MenuController, 'menuController');

my-button.js

/* jshint esversion */
class MyButton extends pc.ScriptType {
    initialize() {
         // same thing, you can locate scripts and objects in your initialization function, e.g.
         this.id = 'some id';
         this.parentScript = this.parent.script.menuController;
         
          // I will skip the event handling, but lets say onClick() 
          // is called when this button is cllicked
    }

    onClick() {
        console.log(this.parent.word); // 'some text'
        this.parent.clickedButton(this.id);
    }
}
pc.registerScript(MyButton, 'myButton');
1 Like

If you just have one static instance, I would just have a global object with functions.

Personally, I’m not a big fan of using singleton managers a prefer event firing or a subscriber/observer pattern.

There’s a quite a few methods available to you to do what you need pending on the problem. If you have a specific use case, we could suggest something more specfic?

2 Likes

Thanks for your responses guys! I think I just need to embrace the event firing model instead of our usual system. It is not a big deal it was just more a convenience thing coming from the world of C# and Unity.

Thanks again for your help!

You can do the same thing as you do in Unity (we don’t have DontDestroyOnLoad though)

var OnScreenJoystick = pc.createScript('onScreenJoystick');

// initialize code called once per entity
OnScreenJoystick.prototype.initialize = function() {
    if (!OnScreenJoystick.instance) {
        OnScreenJoystick.instance = this;

        this.on('destroy', function() {
            OnScreenJoystick.instance = null;
        });
    } else {
        console.error('Instance already created');
    }
};

Well son of a gun! That is exactly what I was hunting for! It is simpler than I was trying to make it.

Thanks again, my company is really enjoying adding Playcanvas to our workflow!

1 Like