ScriptableObject replacement?

Based on the experience of the previous project, I realized that maintaining a set of data objects in the main scene and linking them to actual objects in the game scene is clearly inconvenient for maintenance and assembly.

As an option, you can link a data file (for example, json), but accordingly, when you need to throw a link to some asset from the explorer - there is no convenient method.

I’m currently thinking about simulating the desired behavior through individual data object templates, but that also sounds relatively inefficient, especially considering that you can’t change template component parameters from the explorer.

How do you get out of this situation?

1 Like

Hey @robert.ua, just trying to visualise what you mean here. Are you talking about storing game state for a project?

No, more like data for template objects (not only that, but now it is), which I do not want to multiply together with templates when instantiating them, also the possibility of throwing a certain data object on multiple templates.

In the last project, it was data for obstacles (one of usecases). On the actual object itself, there was only a reference to the data object (characteristics, various arrays), but to assign it i need either create the object in real time (which I did for level generation), or make a system identifiers (in case you need to support both real-time generation and simple placement of an obstacle on the stage, which you would like at least in the process of development and testing.

If I could create this data object at the file level (literally a ScriptableObject) instead of an entity, it would be much more convenient.

/// data can be more complex, but here is an example
var ObstacleData = pc.createScript('obstacleData');

ObstacleData.attributes.add('templateAsset', {type: 'asset', assetType:'template'});
ObstacleData.attributes.add('stepsWidth', {type: 'number', precision: 0, default: 1});
ObstacleData.attributes.add('hitSound', {type:'asset', assetType:'audio'})
ObstacleData.attributes.add('actions', {
    type: 'json',
    array: true,
    schema: [
        {
            name: 'func',
            type: 'string',
            enum: [
                { 'hide': 'hide' },
                { 'applyDamage': 'applyDamage' },
                { 'delay': 'delay' },
                { 'addHealth': 'addHealth' },
                { 'addMoney': 'addMoney' },
                { 'addFire': 'addFire' },
                { 'addMagnet': 'addMagnet' },
            ]
        },
        {
            name: 'param',
            type: 'string',
        },
    ]
});

ObstacleData.prototype.initialize = function() {
    this.entity.data = this;
};

////some logic from pooling and data linking
            const newPoolEntity = new pc.Entity(node.entity.name);
            this.entity.addChild(newPoolEntity);
            newPoolEntity.addComponent('script',)
            const newPool = newPoolEntity.script.create('entityPool', {attributes: 
            {
                templateAsset: node.entity.data.templateAsset, 
                startSize: node.poolCount,
            }});
            newPool.data = node.entity.data; // linking data   data <- pool <- poolItem
            this.poolsMap.set(node.entity.data.templateAsset.id, newPool);

A stop gap solution would be to have Template Assets as scriptable objects and a scene that has all the objects instanced.

This scene can be opened in another browser tab for quick access editing.

All the Template assets could be tagged with ‘scriptable’ and a bit of code that gets called before the scene loads could instance the templates (but not attach to the scene graph) and have the asset reference the entity as a custom property.

(What would be nice is to have an official API for template assets to access the scene data directly so we wouldn’t have to instance them)

1 Like