Answer
A‑Frame’s schema only performs type‑casting when an attribute is changed through setAttribute() (or during HTML parsing). Direct manipulation of the underlying Three.js object graph does not trigger the update lifecycle, nor does it modify the component’s data object. To reflect external Three.js changes back into a schema‑defined property you must manually assign the new value to component.data.property and optionally call component.update() (or let the tick handler read the updated data). The schema does not natively support arbitrary JavaScript objects or arrays; attempting to pass a complex object via setAttribute results in the literal string "[object Object]" unless you serialize it yourself (e.g., with JSON.stringify).
Limitations for Synchronizing External State
- No automatic sync: Changes made directly to
el.object3D (position, rotation, scale, material properties, etc.) bypass the schema, so update is not called and data stays stale.
- Manual push required: To keep the schema in sync you must:
- Read the new Three.js value (e.g.,
el.object3D.position.x).
- Assign it to
el.components.mycomp.data.prop.
- Optionally invoke
el.components.mycomp.update() (or rely on tick to use the updated data).
- No re‑initialization needed: This manual assignment updates only the data layer; the component’s lifecycle methods (
init, remove) are not rerun.
Complex Object Support and Performance
- The schema provides built‑in casters for primitives (
string, number, boolean, int, float) and A‑Frame‑specific types (vec2, vec3, vec4, color, selector). It does not provide automatic casting for plain JavaScript objects or arrays.
- If you store a complex object in a schema field you must serialize it to a string (usually JSON) before calling
setAttribute. On each attribute change the system parses that string back into an object, creating temporary allocations and GC pressure.
- For high‑frequency updates (e.g., per‑frame physics or animation) this parse/stringify cycle can degrade frame rates, especially on low‑end hardware. Performance‑critical applications should keep complex state in plain JavaScript properties or in the Three.js object graph and only use the schema for primitive or built‑in vector/color values.
Verification Steps (optional)
// 1. Confirm schema casting works via setAttribute
const el = document.createElement('a-entity');
el.setAttribute('test', 'value', 5); // assumes a component with a number schema 'value'
el.components.test.update = function(data) { console.log('update', data.value); };
el.setAttribute('test', 'value', 10); // logs 10
// 2. Show direct Three.js change does NOT trigger update
el.object3D.position.x = 100; // update handler not called, data.value unchanged
// 3. Manual sync without re‑initialization
el.components.test.data.value = el.object3D.position.x;
el.components.test.update(el.components.test.data); // logs 100
// 4. Complex object via schema (shows stringification)
el.setAttribute('test', 'obj', '{x:1,y:2}');
console.log(el.components.test.data.obj); // "[object Object]" unless you JSON.stringify first
If you need to keep the schema in sync with a Three.js property that changes every frame, let me know the property name and how often it updates.