Global JSON & Accessing Attributes

Hi all, I want to load in a JSON. Easy enough, I’ve made it an attribute and can access it in the script it’s originally tied to. Unfortunately, this presents three problems:

  1. It seems to be tied to being on a script that is on an entity, as opposed to a library script (of which I got the answer for here.

  2. I can’t seem to figure out how to properly access it outside of it’s own script. Within it’s own script, this.[attr].resource gets me the contents of the JSON, but trying otherFile.attributes.get('[attr]'); returns an object containing {type: "asset", assetType: "json"} and I can’t seem to find any documentation or other forum posts that tell me how I might go about getting an attribute from another script.

  3. It poses the problem wherein I want this JSON file accessible in every script, and even if I can access via a library script, that’s acceptable, but will undoubtedly make code a little more bloated. In short, is there a way to load it dynamically from an asset and then have it be available to every script? Perhaps by attaching it to one of the global objects (I know that pc is the overhead PlayCanvas object, but I don’t know if there are others that might be better suited, or if it’s even feasible to do so).

Hi @TingleyWJ,

There are many ways to make an script specific property/value available to other scripts. Here is one, adding it as a property to a global object. It’s not the most elegant, but it will give you an idea. Javascript in Playcanvas works as regular Javascript, there isn’t anything special here.

Let’s say I have a script named Game and we load a JSON asset through an attribute named characterData:

var Game = pc.createScript('game');

Game.attributes.add('characterData', {
    type: 'asset',
    assetType: 'json'
});

// initialize code called once per entity
Game.prototype.initialize = function() {

   // we can now access this asset from any other script file
   Game.characterData = this.characterData;

};

Now we can access it from any other script file (just make sure that game.js script loads first in your project script loading order:

var Player= pc.createScript('player');

// initialize code called once per entity
Player.prototype.initialize = function() {

   console.log(Game.characterData);
};

Another way to load the JSON data into a global object is to listen for the app start event and reference the JSON data with a global variable:

(function () {
    var app = pc.Application.getApplication();
    app.on('start', function() {
        var jsonAssets = app.assets.findByTag('json-data');
        // Assuming the json asset is preloaded and it's the only one 
        if (jsonAssets.length > 0 && jsonAssets[0].loaded) { 
            window.someJsonData = jsonAssets[0].resource; 
        }
    });
})();

Example project here: https://playcanvas.com/editor/scene/929169

In regards to access other script instances and components, I cover some of it here: How to refer to different parts of the API while scripting

TLDR, you need to have a reference to the entity that has the script instance or component you want to access. To get that entity reference in the first place, you can either search for it with the various ‘findBy’ functions or have a script attribute that allows you make the reference in the Editor (example on line 3 on this script: https://playcanvas.com/editor/code/405842?tabs=4468263).

1 Like