[ENGINE ONLY] Add scripts at runtime

Hi guys, I am loading scenes like this in the engine:

  loadScene() {
      console.log('Load Scene');
      const app = this.$pc.Application.getApplication();
      app.preload = true;
      app.loadScene(
        settings.SCENE_PATH,
        function(err, scene) {
          if (!err) {
            // Scene loaded successfully
            console.log('Scene loaded.');
            // Hide Spash screen
            app.fire('preload:end');
            // Process the scene
            this.processScene(scene);
          } else {
            // Error
            console.log('Error: ', err);
          }
        }.bind(this)
      );
    },

Is there an event that detects that a script component is needed, so that I can load the script manually
at runtime either from local file system or remote?

Hi @iso74,

Not sure about that, but an alternative would be to find all the required script types for the new scene.

You can use the findComponents('script') pc.Entity method to get a list of all script components:

const scriptComponents = scene.root.findComponents('script');

From there you can loop through each script component and load on demand each script asset required.

1 Like

What’s the reason for not having the scripts added during the scene load?

Because I want to add scripts in a different way then, I am using engine only and i probably don’t want to load scripts from a public folder.

Basically it would be good if I could react on this warning here, to insert the scripts then:

That warning is being fired from here, when the script component is trying to create an instance of a script type but that type isn’t available. There isn’t an event fired for you to listen to, you could try submitting a feature request in the engine repo about it for the team to review:

1 Like

How would you want to load them? I don’t see how this prevents you from loading them before the scene.

1 Like

Great, can you tell me how?

Here is written:

findByUrl(url) 

Find a scene by the URL and return the pc.SceneRegistryItem.

How can I use this to get the scripts in there and then load the scripts and then add the SceneRegistryItem to the Registry?

Maybe like this: const myScene = this.$pc.SceneRegistry(app).findByUrl(scene.path);
But it doesn’t seem to work like this.

What is the current setup? Are the game scripts in a separate folder/file/on a DB?

1 Like

Yes exactly. I am using Vue.js as framework. Scripts are stored in a separate folder/file.
I use a Editor exported scene.json to play with.

It works all in all in my setup, but I want also load the scripts on runtime not via Mixins which I have to define in advance, so to avoid declaration in the json and my own one

As long as you know where the files are, you can just add them to the HTML at runtime document.

I do this with my set of devtools for PlayCanvas here: https://github.com/yaustar/yaustar.github.io/blob/master/playcanvas-devtools/injector.js#L135

I have a list of JS files I want to add to the document header and them via this loop with a callback that fires when they have all loaded.

This I dont want, I dont want to add something to the document header, this is not the Vue way

What is the Vue way of adding external scripts?

Adding it to document.head :smiley:
So I transformed the scripts to Vue Mixins that way I can use the Webpack ecosystem to import them into a Vue component.

Dont get me wrong it is working already but I need a way to get the scripts inside a scene.json.
So I will load the scene data with axios look if are scripts in there and then add the mixins then load the scene into Registry

Oh, I thought you wanted them to be loaded at runtime on demand?

Scripts so my mind belong to game logic and for me should not be so present in public folder,
this is other when maybe you have a viewer app. Even though I know that there is less chance to obfuscate Js files. Maybe I will use something like NUXT for serverside rendering of JS and Canvas, but this will be another challenge :slight_smile: For now yes all scripts are stored at the Vue side and I will decide which script should be used.

I don’t use Vue so I’m intrigued on how this works. If they are not in the public folder, how does the client access them?

It is baked with the Webpack ecosystem to one “bigger” file I assume, I also have no deep internals here