[SOLVED] Attach any entity to imported FBX animation?

Can I import an FBX scene with an animation, and then attach one of my other entities to this animation?

Let’s say I have an animation where a sphere moves along a complicated pattern. I import this scene and add it to the root. Now I want to attach another of my entities to this sphere so that it copies its movements. Is it possible?

I tried to attach my other entity as a child of the impoted animated entity, but it doesn’t work. I guess it’s because the animated entity does not change its position and rotation as such. It’s rather a meshinstance in the animated entity that change s position and rotation.

Yes it’s possible to do this, only you need to do it in code. For example if you have an Entity with an animation component and you know the name of the node that is moving in that animation you could do:

this.entity.findByName('moving_node').addChild( myEntity );

1 Like

Excelllent! That should work.

Hi, I was about to post a question about this but then I found this thread. I have an FBX imported animation of an object moving through space (a drone). The drone structure of the FBX looks like this in Cinema4D.

The name of the node that has the keyframes is thus Drone_Loop_v003_Export:Drone_Rigg_v003:Drone_GRP

Let’s say I have script attached to the same Entity that has the animation component, and then use this code above, that would translate to

console.log("animatedEntity: " + this.entity.findByName('Drone_Loop_v003_Export:Drone_Rigg_v003:Drone_GRP'));

However, that just reports null in my console. What am I missing you reckon?

@vaios, does that code of yours still apply or is it part of some older api?

No it still applies. I’m not sure why you can’t find the desired node by name you could try logging the entire entity tree with a little script to debug it perhaps.

Ok, strange. I’m trying this code to iteration through All Entities and their .children, hope that’s the right way.

TreeLog.prototype.initialize = function() {
    
    var rootEntities = this.entity.children;
    
    // Loop through children and report
     for (i = 0; i < rootEntities.length; i++) { 
         console.log(rootEntities[i]);
         
         // Loop through next level
         var level2 = rootEntities[i].children;
         console.log(level2);
     }
};

My Drone_Anim_001 reports 0 children, an array with only the rootnode.

I tried creating a new test model in Cinema4D and exported/imported via FBX. That one retains the node structure. Must be something wrong with the original FBX from Maya. I’ll try re-creating the initial animation FBX.

Ok, back to the root cause now. I’ve managed to reimport a new FBX where I can find the right node. However, your addChild code gives me this error:

Error: GraphNode is already parented

I’m trying to use .reparent now, which does seem to attach it to the right node. The new entity with the light follwows the animation but only for a few frames, then the animation somehow restarts.

this however, must be something else, because the animated got clipped even before I started adding objects. Thanks for your support!!

I ran across this thread while trying to parent a particle emitter to an item in the GraphNode hierarchy of an FBX animation and figured I’d add this comment for anybody that might run into a similar situation in the future.

I had the same issue of the GraphNode already being parented and that seemed like a major roadblock. PlayCanvas apparently does not want any entities that exist in part of the Root hierarchy to change their parenting once the app loads so this suggested code just doesn’t work. Though it would probably work if you created the entity via code.

this.entity.findByName('moving_node').addChild( myEntity );

I didn’t find any sample code for using .reparent, and how to make that work was not obvious to me. So my workaround to this problem was to “fake” or simulate the parenting. I plan on looking at .reparent and will post if I can figure that out.

fakeParent.prototype.update = function(dt) {
    var entityFollow = this.entity.findByName('moving_node').getPosition();
    var entityRotate = this.entity.findByName('moving_node').getEulerAngles();
    this.childEntity.setPosition(entityFollow);
    this.childEntity.setEulerAngles(entityRotate);

};

As you can see, this code needs to be added to the .update function of a script if you want the position to be continuously updated. I included this in a script that had other uses, but you might prefer making a simple “parent” script that only does this make what is happening more obvious in the editor.

I didn’t see anything in the API for grabbing and setting the scale using world space. I only found that for local space. So the entity isn’t fully parented since it doesn’t follow the parent’s scale. But in my case, scale didn’t matter.

Also, I wanted to shift my emitter position relative to the axis of the element that I was “parenting” to, so I simply parented the particle emitter object to child.Entity in the Editor.

One weakness of this method is that you can’t see the results interactively in the editor. You must launch your project in order to see the “parenting” in effect.

Well, here’s the follow-up. This morning when I looked at the .reparent method again it suddenly seemed obvious to me how to implement it. It is actually super-simple.

Where “moving_node” is the entity you want to parent to in the FBX, and where “childEntity” is the entity you want parented to “moving_node”.

In the initialize portion of your script you need to identify the entity in your FBX with .findByName like this:

this.FBXentity = this.app.root.findByName('FBXentity');
this.moving_node = this.FBXentity.findByName('moving_node');

Now that you have the entity in your FBX identified, you simply use the .reparent method.
You just need to make sure that this line gets executed at the appropriate time. It only needs to be executed once. It does not need to be in the .update portion of a script.

this.childEntity.reparent(this.moving_node);

I found that the scale in my particular case was way off from what I had expected. So at first it didn’t seem like the .reparent had worked since I couldn’t see the object. So if the object doesn’t show up as you’d expect, try adjusting the scale.

2 Likes