playcanvas / engine

JavaScript game engine built on WebGL, WebGPU, WebXR and glTF
https://playcanvas.com
MIT License
9.43k stars 1.32k forks source link

Unity like Scriptable object #2447

Open yaustar opened 3 years ago

yaustar commented 3 years ago

Feature request to be able to have an asset that holds data such as references to other assets, etc.

Should be able to change the values at runtime too.

vkalpias commented 3 years ago

We implemented JSON script attributes partly for this reason too. One can make a template with JSON script attributes which would behave like the description.

yaustar commented 3 years ago

JSON attributes with a template wouldn't work the same as Unity Scriptable objects.

Scriptable objects is a an asset that holds data (like a global object) that can be assigned to GameObjects like an asset. This means that more than one GameObject can share the same set of data and read/write to it.

This allows for Editor driven data injection. E.g we would have a scriptable object that contains an int that represents the number of lives a player has.

The Game Manager would have a reference to this scriptable object and change the number pending on the what happens in the game.

A part of the UI system would also have a reference to it and changes the text based on the value of the int.

Code wise, there is no hook up needed, it's all done in the Editor.

yaustar commented 3 years ago

Wait, are you saying that we could have a reference to a Template Asset and change the values in the Template Asset in code?

Could we actually do the above with just a JSON asset thinking about it?

vkalpias commented 3 years ago

Wait, are you saying that we could have a reference to a Template Asset and change the values in the Template Asset in code?

Well I suppose you wouldn't change the template asset directly. You could have an Entity or an instance of a template and reference that although it would then have to live in your scene.

Could we actually do the above with just a JSON asset thinking about it?

Yes you can do that with a JSON asset, only issue is that if that JSON asset has any asset references then it won't be able to update those if say you fork the project. You could get around that by using tags instead of asset ids or asset names..

vkalpias commented 3 years ago

Actually now that I remember more details I believe one of the thoughts was to provide an optional schema for the a JSON asset and that would be used to display a UI for it. But I think this is all a bit complicated and now that we have JSON attributes you could use an Entity with JSON script attributes as your scriptable object..

LeXXik commented 3 years ago

I do it as @vkalpias offers, via JSON attributes. For example, I have a project script, called Settings, which stores all the various settings and options related to the game scrtipts, allowing a designer to tweak options from the Editor. In the editor, I have an entity Settings in the scene root, which has a script component with this settings script:

class Settings extends pc.ScriptType {}
pc.registerScript(Settings, 'settings');
Settings.attributes.add('debug', { ... }) // category debug, holding all sorts of debugging toggles as a json list
Settings.attributes.add('table', { ... }) // example category, holding json properties about a game table

Afterwards, I create a base class, e.g.

class Sequence extends pc.ScriptType {
    initialize() {
        this.settings = this.app.root.findByName('Settings').script.settings;
        this.init();
    }

    init() {} // virtual
}

Then any sequence script has an access to the project settings:

class SomeSequence extends Sequence {
    init() {
         const width = this.settings.table.width;
    }
}