Does script attributes only work in the editor?

I have a OrbitCamera script, and I load it dynamically using the engine.

// orbitCamera.js
var OrbitCamera = pc.createScript('orbitCamera');

OrbitCamera.attributes.add('speed', {
  type: 'number',
  default: 1,
  title: 'Speed',
  description: 'Orbit speed of the camera'
});

OrbitCamera.prototype.initialize = function() {
  this.x = 0;
  this.y = 0;
  this.distance = 0;
  this.target = new pc.Vec3();

  console.log(this.speed);

  this.app.mouse.on(pc.EVENT_MOUSEMOVE, this.onMouseMove, this);
  this.app.mouse.on(pc.EVENT_MOUSEWHEEL, this.onMouseWheel, this);
};
// app.js
require('./orbitCamera');
var camera = new pc.Entity();
camera.addComponent('camera');
camera.addComponent('script');
camera.script.create('orbitCamera');

However, I got undefined in the console… Does the script attributes only work in the editor?
It seems that I can only define this.speed = 1 in initialize phase to make the code work.

Attributes are initialized after entity has been initialized (enabled and in hierarchy).
So if you add the camera entity to hierarchy, then it should define all attributes and they will be accessible.

Do you mean it is normal that this.speed return undefined in initialize phase, because I can access it after initialize ?

I just test it at runtime, I create camera and add it to app.root, the script attributes is still undefined.

// app.js
require('./orbitCamera');
var camera = new pc.Entity();
camera.addComponent('camera');
camera.addComponent('script');
camera.script.create('orbitCamera');
app.root.addChild(camera);

console.log(camera.script.orbitCamera.speed) // undefined

I’ve made some tests, and here are the observations:

  1. If application is not started, then attributes won’t be initialized. - this is fine
  2. If entity is not within hierarchy, then attributes won’t be initialized. - this is fine
  3. If script is added to entity before it is added to hierarchy, then attributes will be initialized once entity is added to hierarchy and is enabled. - this is fine
  4. If script is added to entity which is already within running app hierarchy and is enabled, then attributes won’t be initialized. - this is not fine

Attributes do get initialized once entity is about to become active within application. But scenario 4 shows some issue here.

Reason why attributes are not initialized instantly is due to some complexities in data flow. We could look into trying to initialize attributes at the moment of script being added to entity, this would solve most of problems, but will introduce some other complexity there.

I have added ticket to look at scenario 4: https://github.com/playcanvas/engine/issues/949

3 Likes

Yes, my use case is same as your example in codepen: create script after entity added to the hierarchy.

Here is quick workaround, if you add this after you’ve added scripts, it will enforce attributes initialized.
So it disables and enables entity back.

entity.enabled = ! entity.enabled;
entity.enabled = ! entity.enabled;
1 Like

Does the script always call initialize when it switch from disabled to enabled ?

https://developer.playcanvas.com/en/user-manual/scripting/anatomy/#initialize

It is called only once per entity, right before first time it is about to become active.
So disabled entities do not call initialize until they get enabled within hierarchy.

And initialize works as it should (just tested the codepen example), it is only attributes do not get initialized.

1 Like