after an afternoon of debugging it finally dawned on me my problem is actually related to the other question I asked earlier today.
I have an objectC with a component spawning an instance of a AssetReference to objectB.
objectB in turn has a reference to a child objectA which it wishes to manipulate. For testing purposes I want objectB to deactivate object A.
So, recap: objectC spawns objectB deactivates child objectA.
Hereās the catch though: The component on objectB does not directly contain the reference to objectA. Instead, objectB contains a serialized plain object which contains the reference.
And thatās where it breaks Because whenever I fetch the reference to objectA, itās not the actual instanceās objectA but the prefabās objectA. (Prefab in the sense of the loaded instance under AssetReference.asset.)
I can work around it for now but it will become a hard problem pretty soon: I need a way to store a collection of sets of references and further data. There is no way of putting it all flat on the componentās level. So I need nested (plain serialized) objects containing references.
Hi krizzl0r, below is one approach to working around nested plain serialized objects that contain hierarchy references. Since Needle Engine only rebinding references automatically on topālevel (e.g. component) fields during instantiation, any nested objectās reference (like your objectA) wonāt be automatically reāmapped from the prefab. You need to rebind it manually once the instance is created.
Stepābyāstep pseudocode:
Define a plain serialized helper class (e.g. ChildData) containing a reference field to objectA.
In your objectB component, add a field of type ChildData.
In the onEnable (or awake) method of objectB, use the instanceās hierarchy (e.g. using gameObject.getObjectByName(āobjectAā)) to locate the instanceās child.
Update the nested objectās reference with the instanceās child rather than the prefabās.
Now you can safely manipulate objectA (for example, deactivating it).
Below is an example in TypeScript:
import { Behaviour, serializable } from "@needle-tools/engine";
import { Object3D } from "three";
// Helper class to store nested reference
class ChildData {
// This field stores a reference to objectA
@serializable(Object3D)
childRef?: Object3D;
}
// Component on objectB
export class ObjectBBehaviour extends Behaviour {
// Nested plain object holding a reference to objectA
@serializable(ChildData)
nestedData: ChildData = new ChildData();
onEnable(): void {
// Find objectA in the instanceās hierarchy (ensure it has the expected name)
const instanceChildA = this.gameObject.getObjectByName("objectA");
if (!instanceChildA) {
console.warn("objectA not found in the instance hierarchy");
return;
}
// Manually update the nested reference to point to the correct instance
this.nestedData.childRef = instanceChildA;
// For example, deactivating objectA (or adjust as needed)
instanceChildA.visible = false;
}
}
In this example the manual rebind ensures that after objectB is instantiated from objectCās AssetReference, the nested object inside objectB properly points to its own child (objectA) rather than the prefabās objectA. This workaround is necessary because plain serialized nested objects are not automatically updated during instantiation, as you discovered.
This approach follows similar principles as the automated reference resolution seen in Needle Engineās instantiation routines (see the reference mapping in the instantiation code at engine_gameobject.ts).
Hope this helps, and happy coding!
1 replies left - Become PRO for more replies. thread_J2iMfXSJ4VDUmk5u2OiW2Zfq Reply to this post directly if you need further help (bottom right button)
Hi @krizzl0r this is unfortunately a change we can not do easily to avoid compatibility issues with existing projects and needs some more consideration.
The issue is caused by object references currently not being deep cloned during instantiate calls (when cloning components). In your case it means the reference of your custom class is shared by all instances, thatās why the wrong object is being disabled when you try to access the assigned Object3D.
Thatās one option - you could probably also implement __internalNewInstanceCreated() in your component to resolve children, just make sure to call the super method: