LogoLogo
  • Get Started
  • Getting Started
    • Initial Setup
    • Create Your First Game
    • API Reference
    • Build Your First World Map
    • Multiplayer Testing
    • Use Templates & Examples
    • Styling & Assets
      • Modeling Guidelines
      • Texturing Guidelines
      • Default Assets
  • Build Faster With AI Tools
  • SDK Guides
    • Assets
    • Audio & SFX
      • Audio Manager
    • Blocks & Chunks
      • Block Types
      • Block Type Registry
      • Chunks
      • Chunk Lattice
    • Camera
    • Chat & Commands
    • Debugging
    • Entities
      • Animations
      • Block Entities
      • Colliders & Hitbox
      • Child Entities
      • Entity Controllers
        • Base Entity Controller
        • Pathfinding Entity Controller
        • DefaultPlayer Entity Controller
        • Simple Entity Controller
      • Entity Manager
      • Model Entities
      • Movement & Pathfinding
      • Player Controlled Entities
    • Events
    • Input & Controls
    • Lighting
      • Ambient Light
      • Light Manager
      • Point Lights
      • Spot Lights
      • Sun Light (Directional)
    • Mobile
    • Persisted Data
    • Players
      • Player Manager
      • Persisted Player Data
    • Plugins
    • Physics
      • Colliders
      • Collision Groups
      • Debugging
      • Gravity
      • Raycasts
      • Rigid Bodies
    • User Interface
      • Overlay UI
      • Scene UIs
      • Scene UI Manager
    • Worlds
      • Map Data Format
  • Helpful Resources
    • HYTOPIA Architecture & Platform Overview
    • Useful Third-Party Tools
Powered by GitBook
On this page
  • Limitations & Constraints Of Child Entities
  • Anchoring & Relative Movements
  • Creating A Child Entity
  • Nested Child Entities
  • Attaching & Detaching An Existing Entity As A Child
  • Applying Local Forces & Physics
  • Listing Model Nodes
  • Default Player Entity Anchor Nodes
  • Diving Deeper
Export as PDF
  1. SDK Guides
  2. Entities

Child Entities

PreviousColliders & HitboxNextEntity Controllers

Last updated 9 days ago

Child entities are entities that are attached to a parent entity. Child entities are purely visual and cannot not have physical colliders.

You can use child entities to create visual attachments to any other entity. For example, you could attach a sword model to the hand of a player entity, attach the player entity to the top of a horse model as a mount, and so much more.

Existing entities can be attached as child entities at any time, or you can even spawn an entity as a child of another already spawned entity. Robust and flexible!

Child entities are supported for both Block Entities and Model Entities.

Limitations & Constraints Of Child Entities

Child entities inherit most of the behaviors of standard entities, however they do have a few limitations and constraints as follows.

  • Colliders are disabled - Colliders and physical collisions are not supported by child entities. They are purely visual. All colliders of an child entity will be disabled when attached to a parent. When a child is removed from it's parent entity and is therefore no longer a child entity, its colliders will automatically be re-enabled.

  • Parent Must Be Spawned First - The parent of a child entity must already be spawned before the a child's .spawn()is called.

  • Isolated Kinematic Simulation - Child entities don't have colliders and therefore cannot collide or interact physically. They can however have forces, translations and rotations applied to them for visual simulations. Child entities will by default be created as a kinematic velocity based rigid body with no colliders.

Anchoring & Relative Movements

Child entities are always positioned and rotated relative to their parent. Their relative positioning and rotation will even stay consistent as the parent plays different animation states. Child entities are anchored to the center point of their parent model by default, or to a specific name model node of the parent if a parentNodeNameis provided in the child entities options when creating it.

For example, if you anchor a sword model as a child entity to the hand of a player model, and then trigger an animation that makes the player's arm swing, the sword will fluidly swing as you'd expect because it is attached to the model node that is part of the animation.

This relative anchoring, positioning and rotation is always constant for models in the HYTOPIA engine, even children that are children of another child entity.

Creating A Child Entity

Let's start with a practical example. Let's say we're building an RPG and want to attach a visual sword to our character's hand.

We can use the parentand parentNodeName options when creating our sword entity to attach it to our player entity's hand.

This is super simple with using a child entity like so.

const playerEntity = new DefaultPlayerEntity({
  player,
  name: 'Player',
});

// The parent, which is the player entity, must be spawned
// before the sword is spawned.
playerEntity.spawn(world, { x: 0, y: 10, z: 0 });

const swordChildEntity = new Entity({
  name: 'sword',
  modelUri: 'models/items/sword.gltf',
  parent: playerEntity,
  parentNodeName: 'hand_right_anchor', // attach it to the hand node of our parent model
});

swordChildEntity.spawn(
  world,
  { x: 0, y: 0.3, z: 0.5 }, // spawn with a position relative to the parent node
  { x: -Math.PI / 3, y: 0, z: 0, w: 1 } // spawn with a rotation
);

That's it! Our player is now holding a sword, and the sword will move appropriately and stay anchored with all our parent entities animations too!

Nested Child Entities

You can go a step farther if needed and nest an entity as a child of another child entity. Depth nesting is supporting to any depth desired, however it's not recommend to do excessive child nesting as it could impact gameplay performance for players. For example, try not to nest like (Player Entity -> child -> child -> child -> ... etc)

If you want to use child nesting, here's an example of how you can do that. Maybe we want our sword to have a fish spiked onto the end of it.

const playerEntity = new DefaultPlayerEntity({
  player,
  name: 'Player',
});

// The parent, which is the player entity, must be spawned
// before the sword is spawned.
playerEntity.spawn(world, { x: 0, y: 10, z: 0 });

const swordChildEntity = new Entity({
  name: 'sword',
  modelUri: 'models/items/sword.gltf', // you might not have this model by default
  parent: playerEntity,
  parentNodeName: 'hand_right_anchor', // attach it to the hand node of our parent model
});

swordChildEntity.spawn(
  world,
  { x: 0, y: 0.3, z: 0.5 }, // spawn with a position relative to the parent node
  { x: -Math.PI / 3, y: 0, z: 0, w: 1 } // spawn with a rotation
);

// Everything above this is the same code from our previous example.

// Create our fish as a child of our sword
const fishChildEntity = new Entity({
  name: 'fish',
  modelUri: 'models/items/fish.gltf', // you might now have this model by default.
  modelScale: 2,
  parent: swordChildEntity,
});
    
fishChildEntity.spawn(world, { x: 0, y: 1, z: 0.5 });

Wallah! We have a fish model that looks like it's staked on the end of our sword!

Attaching & Detaching An Existing Entity As A Child

You can attach and detach entities as children as much as you'd like. This is useful for a lot of things like picking up held items, weapons, making a player attach to a mount entity, and much more. This also means you don't need to do any dynamic spawning and despawning of child and parent entities when dealing with attachments, everything stays simple and easy!

In this example, let's create a sword and when a player collides with it, we'll attach it as a child entity in the player's hand. After 5 seconds, the sword will detach and fly away in front of the player.

const swordEntity = new Entity({
  name: 'Sword',
  modelUri: 'models/items/sword.gltf',
});

swordEntity.on(EntityEvent.ENTITY_COLLISION, ({ otherEntity, started }) => {
  if (started && otherEntity instanceof PlayerEntity) {
    swordEntity.setParent(otherEntity, 'hand_right_anchor', { x: 0, y: 0.2, z: 0.4 }, Quaternion.fromEuler(-90, 0, 0));
      
    setTimeout(() => {
      const facingDirection = otherEntity.directionFromRotation;
      const playerPosition = otherEntity.position;
      swordEntity.setParent(undefined, undefined, { 
        x: playerPosition.x + -facingDirection.x * 2, 
        y: playerPosition.y + 1, 
        z: playerPosition.z + -facingDirection.z * 2,
      });
      swordEntity.setLinearVelocity({ x: -facingDirection.x * 10, y: 10, z: -facingDirection.z * 10 });
    }, 5000);
  }
});

swordEntity.spawn(world, { x: 3, y: 10, z: 3 });

This results in the following! Also! If we were to touch the sword again after it was thrown, we'd pick it up again and the same throw effect after 5 seconds would happen as well.

Applying Local Forces & Physics

Child entities do not and cannot participate in physical collisions. They cannot have colliders. However, most of the methods available to a standard entity work just the same on a child entity for manipulating its visual position and rotation by setting position, rotation, or applying forces.

For example, child entities are the equivalent of kinematic rigid body. Therefore, we do things like apply velocities and forces that locally effect the child.

Here's how you can use these local forces for interesting visual effects like creating a hat that constantly rotates by using angular velocity.

const hatEntity = new Entity({
  name: 'wizardHat',
  modelUri: 'models/pumpkinhead.gltf',
  parent: playerEntity,
  parentNodeName: 'neck',
  rigidBodyOptions: {
    // Angular velocity is constant because external
    // physical forces do not effect children since
    // child entities are kinematic rigid bodies.
    angularVelocity: { x: 0, y: 1, z: 0 },
  },
});

hatEntity.spawn(world, { x: 0, y: 0.8, z: 0 }); // position relative to parent node

Here's our rotating pumpkin hat!

Listing Model Nodes

Sometimes you may be unsure of what available nodes a model has to attach to. Thankfully, we can use the ModelRegistry class in the SDK to get a full list of all known named nodes that a child entity can be attached to for a parent model entity.

console.log(ModelRegistry.instance.getNodeNames('models/items/sword.gltf'));

This console.log anywhere in our code will log an array of unique available node names for the model URI we provide.

Default Player Entity Anchor Nodes

Attaching children to different anchor points on the default player entity is extremely common. For example, you may want to attach a child sword entity to the hand of the default player entity model (player.gltf). You would attach it there by providing the appropriate anchor node name for the parentNodeName property in the child entity's options.

For convenience sake, we've provided a table below of the different anchor point node names the default player entity has.

Anchor Node Name
Purpose

arm_left_anchor

Left arm anchor

arm_right_anchor

Right arm anchor

back_anchor

Back anchor, useful for backpacks, etc

foot_left_anchor

Left foot anchor

foot_right_anchor

Right foor anchor

hand_left_anchor

Left hand anchor

hand_left_shield_anchor

Left hand shield anchor, positions on the outer of the left hand.

hand_right_anchor

Right hand anchor

hand_right_weapon_anchor

Right hand weapon anchor, positions relative to a held position in the hand for a weapon.

head_anchor

Head anchor

leg_left_anchor

Left leg anchor

leg_right_anchor

Right leg anchor

torso_anchor

Torso anchor, anchors at chest.

Diving Deeper

This example makes use of the setParent()function of the Entity class. This method is quite powerful and is worth taking a .

The child entity system is constantly evolving. It is a part of the Entity class, you can find the latest .

If there are features that we don't currently support for child entities that you'd like to see added to the HYTOPIA SDK, you can .

look at the documentation for, here
Entity API Reference here
submit a feature request here
A horse entity with a player entity attached as a child, creating a "mount" look.
A fish model that is a child of our sword, positioned relatively to look like it's staked on our sword!
A rotating pumpkin hat that stays anchored to our player even as it animates and moves.