---
title: "Child Mesh Animation System Reference"
canonical: "https://wiki.sinsofasolarempire2.com/space/SSEFW/3181215745/Child%20Mesh%20Animation%20System%20Reference"
format: markdown
---
All properties are serialized within a `"child_meshes"` array on a unit definition.

---

## Required Properties

| JSON Key | Type | Description |
| --- | --- | --- |
| `mesh_alias_name` | `string` | Name matching a child mesh alias in the unit skin |
| `mesh_point` | `string` | Name of the mesh point to attach to on the parent mesh |
| `is_weapon_effects_destination` | `bool` | Whether weapon effects target this child mesh |

---

## Visibility Properties

| JSON Key | Type | Default | Description |
| --- | --- | --- | --- |
| `required_unit_item` | `string` | `""` | Unit item definition ID required for this mesh to be visible |
| `required_unit_item_level` | `int` | none | Minimum item level needed (only checked if `required_unit_item` is set) |
| `hidden_by_unit_item` | `string` | `""` | Unit item definition ID that hides this mesh when present |

---

## Continuous Rotation Properties

| JSON Key | Type | Default | Description |
| --- | --- | --- | --- |
| `rotation_axis` | `[x, y, z]` | none | Axis to rotate around (e.g. `[0, 1, 0]` for Y-axis). Required for rotation. |
| `rotation_speed` | `float` | none | Rotation speed in radians/sec. Required with `rotation_axis`. |
| `rotation_origin_mesh_point` | `string` | none | Mesh point name to use as rotation origin instead of the attachment point |
| `rotation_condition` | `string` | `"always"` | When rotation is active |
| `rotation_speed_modifier` | `float` | `1.0` | Multiplier applied to `delta_time` during rotation update |

### `rotation_condition` Values

| Value | Behavior |
| --- | --- |
| `"always"` | Always rotates (default) |
| `"not_in_combat"` | Stops rotating when the unit has recently fired weapons |
| `"only_when_charging_phase_jump"` | Only rotates during hyperspace charge segment |
| `"ability_firing"` | Only rotates while an ability beam is firing (1.5s hardcoded duration) |

---

## State Transition Properties

| JSON Key | Type | Default | Description |
| --- | --- | --- | --- |
| `will_transition_positions` | `bool` | `false` | Enables position/rotation state machine |
| `position_states` | `array` | `[]` | Array of `child_mesh_position_state` objects |
| `state_constraint` | `string` | `""` | Legacy constraint name (evaluated at mesh level) |
| `ability_name` | `string` | `""` | Ability name for `on_ability_cast` constraint matching |
| `transition_time` | `float` | `0.5` | Seconds to interpolate between states |
| `transition_delay` | `float` | `0.0` | Seconds to wait before starting a transition |
| `default_state_index` | `int` | `0` | Index into `position_states` used as the resting state |
| `construction_progress_threshold` | `float` | `0.95` | Construction progress (0.0-1.0) at which the `"on_unit_construction_complete"` transition is triggered. Allows the animation to begin before the unit finishes building. |

### `position_states` Entry

| JSON Key | Type | Required | Description |
| --- | --- | --- | --- |
| `state_name` | `string` | yes | Name used by the new-style per-state constraint evaluation |
| `position_offset` | `[x, y, z]` | yes | Position offset from attachment point |
| `rotation_offset` | `[[r00,r01,r02],[r10,r11,r12],[r20,r21,r22]]` | yes | 3x3 rotation matrix offset |

---

## State Constraints

There are two evaluation paths depending on whether you use `state_constraint` (legacy) or per-state `state_name` (new-style).

### Legacy: `state_constraint`

Set on the child mesh definition. Returns state index `0` or `1`. Requires at least 2 `position_states`.

| `state_constraint` value | Triggers state 1 when... |
| --- | --- |
| `"in_phase_jump_or_charging"` | Unit is charging hyperspace or in hyperspace jump |
| `"on_unit_construction_complete"` | Within 3 seconds of construction completing |
| `"in_combat"` | Unit has recently fired normal weapons |
| `"enemy_detected"` | Unit has an active attack target that is a threat |
| `"is_unit_factory_idle"` | Unit factory is currently building units (note: returns 1 when busy, name is misleading) |
| `"on_ability_cast"` | An active ability cast matches `ability_name` |
| `"ability_recoil"` | Special: triggers recoil animation (state 0->1->0 automatically) |

### New-style: Per-State `state_name`

Set on each `position_states` entry. States are evaluated top-to-bottom; the first state whose condition is `true` becomes the target.

| `state_name` value | Returns true when... |
| --- | --- |
| `"in_phase_jump_or_charging"` | Unit is charging hyperspace or in hyperspace jump |
| `"on_unit_construction_complete"` | Within 3 seconds of construction completing |
| `"in_combat"` | Unit has recently fired normal weapons |
| `"enemy_detected"` | Unit has an active attack target that is a threat |
| `"is_unit_factory_idle"` | Unit factory is NOT building units |
| `"is_unit_factory_building"` | Unit factory is currently building units |
| `"on_ability_cast"` | An active ability cast matches `ability_name` |
| Any unrecognized name | Always returns `true` (use as a default/fallback) |

---

## Recoil Properties

| JSON Key | Type | Default | Description |
| --- | --- | --- | --- |
| `recoil_completion_rotates_mesh` | `string` | none | `mesh_alias_name` of another child mesh to rotate when this mesh's recoil completes |
| `recoil_completion_rotation_angle` | `float` | none | Angle in radians to add to the target mesh on recoil completion |

Recoil fires on all meshes with `state_constraint: "ability_recoil"`. The mesh transitions to state 1, waits `transition_time + 0.05s`, then returns to state 0. On completion, it can rotate another child mesh by a discrete angle (e.g. a revolver cylinder advancing).

---

## Integration with Carriers and Unit Factories

Child mesh transitions can block strikecraft launches and unit spawning.

### Carrier Definition

The following property is set on the **carrier definition** (not within `child_meshes`):

| JSON Key | Type | Default | Description |
| --- | --- | --- | --- |
| `block_launch_when_child_meshes_transitioning` | `bool` | `false` | When `true`, strikecraft will not launch while any child mesh is mid-transition |

This is useful for carriers with animated hangar doors -- the doors open via a state transition, and strikecraft wait to launch until the doors have finished opening.

### Unit Factories

Unit factories **always** wait for child mesh transitions to complete before spawning a built unit. No additional property is needed -- this behavior is automatic. This pairs with the `"is_unit_factory_building"` / `"is_unit_factory_idle"` state constraints to animate factory doors or build arms that open/close during construction.

### Pre-Construction-Complete Animations

The `construction_progress_threshold` property works specifically with the `"on_unit_construction_complete"` state constraint. When the factory's build progress crosses the threshold value, the transition animation is triggered **before** the unit is fully built. The factory then waits for all child mesh transitions to finish before actually spawning the unit.

This creates a sequence like:

1. Factory is building (progress 0% -> 95%)
2. At 95% progress (`construction_progress_threshold: 0.95`), the `"on_unit_construction_complete"` constraint fires and the child mesh begins transitioning to state 1
3. Building continues to 100%, but the unit does not spawn yet
4. The child mesh transition completes (after `transition_time` seconds)
5. The unit spawns

---

## Behavioral Notes

- **Multi-state stepping**: When transitioning across multiple states (e.g. state 0 to state 3), the system steps through intermediate states one at a time (0->1->2->3), each taking `transition_time` seconds.
- **Mid-transition reversal**: If a target changes mid-transition, the system can reverse direction and properly interpolates using `1.0 - progress`.
- **Recoil auto-return**: `"ability_recoil"` automatically goes state 0->1 then back to 0 after `transition_time + 0.05s`.
- `rotation_speed: 0` with `rotation_axis`: Valid -- creates a mesh that only moves via discrete rotations (used by the recoil cylinder pattern).
- **New-style state evaluation order**: States are checked top-to-bottom; the first matching `state_name` wins. Use an unrecognized name (like `"default"`) as a fallback since unknown names return `true`.
- **Interpolation**: Position offsets are linearly interpolated. Rotation matrices are component-wise linearly interpolated (not slerp).

---

## JSON Examples

### 1. Simple Continuous Y-axis Rotation

A radar dish that always spins around the Y-axis.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "radar_dish",
            "mesh_point": "child_mesh_radar",
            "is_weapon_effects_destination": false,
            "rotation_axis": [0, 1, 0],
            "rotation_speed": 1.5
        }
    ]
}
```

### 2. Rotation That Stops in Combat

Spinning rings that stop when the unit fires weapons.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "ring_outer",
            "mesh_point": "child_mesh_ring",
            "is_weapon_effects_destination": false,
            "rotation_axis": [0, 0, 1],
            "rotation_speed": 2.0,
            "rotation_condition": "not_in_combat"
        }
    ]
}
```

### 3. Rotation Only During Phase Jump Charge

Drive fins that spin up only when charging hyperspace, at half speed.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "phase_drive",
            "mesh_point": "child_mesh_drive",
            "is_weapon_effects_destination": false,
            "rotation_axis": [0, 0, 1],
            "rotation_speed": 5.0,
            "rotation_condition": "only_when_charging_phase_jump",
            "rotation_speed_modifier": 0.5
        }
    ]
}
```

### 4. State Transition with Legacy Constraint

Wing panels that open during hyperspace charge/jump, with a delay before transitioning.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "wing_panel",
            "mesh_point": "child_mesh_wing",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "state_constraint": "in_phase_jump_or_charging",
            "transition_time": 1.0,
            "transition_delay": 0.2,
            "default_state_index": 0,
            "position_states": [
                {
                    "state_name": "closed",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "open",
                    "position_offset": [0, 0.5, 0],
                    "rotation_offset": [[0.707,0,-0.707],[0,1,0],[0.707,0,0.707]]
                }
            ]
        }
    ]
}
```

### 5. Ability Recoil with Cylinder Rotation

A revolver-style turret: the barrel recoils on fire, and on completion rotates the cylinder by 60 degrees (~1.0472 radians). The cylinder has `rotation_speed: 0` so it only moves via discrete rotation.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "barrel",
            "mesh_point": "child_mesh_barrel",
            "is_weapon_effects_destination": true,
            "will_transition_positions": true,
            "state_constraint": "ability_recoil",
            "transition_time": 0.15,
            "default_state_index": 0,
            "recoil_completion_rotates_mesh": "cylinder",
            "recoil_completion_rotation_angle": 1.0472,
            "position_states": [
                {
                    "state_name": "rest",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "recoiled",
                    "position_offset": [0, 0, -0.3],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                }
            ]
        },
        {
            "mesh_alias_name": "cylinder",
            "mesh_point": "child_mesh_cylinder",
            "is_weapon_effects_destination": false,
            "rotation_axis": [0, 0, 1],
            "rotation_speed": 0
        }
    ]
}
```

### 6. Rotation with Ability Firing Condition and Custom Origin

A beam emitter that spins only while the ability beam is active, rotating around a separate pivot point.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "beam_emitter",
            "mesh_point": "child_mesh_emitter",
            "is_weapon_effects_destination": true,
            "rotation_axis": [0, 1, 0],
            "rotation_speed": 3.0,
            "rotation_condition": "ability_firing",
            "rotation_origin_mesh_point": "emitter_pivot"
        }
    ]
}
```

### 7. New-style Per-State Constraints with Multi-State Transitions

Bay doors that respond to multiple conditions. States are evaluated top-to-bottom; `"default"` is unrecognized so it always returns `true` as a fallback.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "bay_door",
            "mesh_point": "child_mesh_bay",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "transition_time": 0.8,
            "default_state_index": 2,
            "position_states": [
                {
                    "state_name": "in_combat",
                    "position_offset": [0, -1.0, 0],
                    "rotation_offset": [[1,0,0],[0,0.707,0.707],[0,-0.707,0.707]]
                },
                {
                    "state_name": "is_unit_factory_building",
                    "position_offset": [0, -0.5, 0],
                    "rotation_offset": [[1,0,0],[0,0.866,0.5],[0,-0.5,0.866]]
                },
                {
                    "state_name": "default",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                }
            ]
        }
    ]
}
```

### 8. Visibility Gated by Unit Item

An upgraded antenna that only appears when the player has a specific research item at level 2, replacing the base antenna which is hidden by the same item.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "upgraded_antenna",
            "mesh_point": "child_mesh_antenna",
            "is_weapon_effects_destination": false,
            "required_unit_item": "trader_scouts_radar_upgrade",
            "required_unit_item_level": 2,
            "rotation_axis": [0, 1, 0],
            "rotation_speed": 1.0
        },
        {
            "mesh_alias_name": "base_antenna",
            "mesh_point": "child_mesh_antenna",
            "is_weapon_effects_destination": false,
            "hidden_by_unit_item": "trader_scouts_radar_upgrade"
        }
    ]
}
```

### 9. Carrier Hangar Doors That Block Launch

Hangar doors that open when the factory is building, with strikecraft launches blocked until the doors finish opening. The `block_launch_when_child_meshes_transitioning` property is set on the **carrier definition**, not within `child_meshes`.

```json
{
    "carrier": {
        "block_launch_when_child_meshes_transitioning": true,
        "launch_destination_formation": "some_formation",
        "launch_destination_formation_offset": {}
    },
    "child_meshes": [
        {
            "mesh_alias_name": "hangar_door_left",
            "mesh_point": "child_mesh_hangar_left",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "transition_time": 1.2,
            "default_state_index": 1,
            "position_states": [
                {
                    "state_name": "is_unit_factory_building",
                    "position_offset": [-0.5, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "default",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                }
            ]
        },
        {
            "mesh_alias_name": "hangar_door_right",
            "mesh_point": "child_mesh_hangar_right",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "transition_time": 1.2,
            "default_state_index": 1,
            "position_states": [
                {
                    "state_name": "is_unit_factory_building",
                    "position_offset": [0.5, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "default",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                }
            ]
        }
    ]
}
```

### 10. Factory Build Arms That Animate Before Unit Spawns

Build arms that open when construction reaches 95%, with the unit waiting to spawn until the animation completes. The `construction_progress_threshold` triggers the `"on_unit_construction_complete"` constraint early.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "build_arm_left",
            "mesh_point": "child_mesh_arm_left",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "state_constraint": "on_unit_construction_complete",
            "construction_progress_threshold": 0.95,
            "transition_time": 0.6,
            "default_state_index": 0,
            "position_states": [
                {
                    "state_name": "closed",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "open",
                    "position_offset": [-0.4, 0.2, 0],
                    "rotation_offset": [[0.866,0.5,0],[-0.5,0.866,0],[0,0,1]]
                }
            ]
        },
        {
            "mesh_alias_name": "build_arm_right",
            "mesh_point": "child_mesh_arm_right",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "state_constraint": "on_unit_construction_complete",
            "construction_progress_threshold": 0.95,
            "transition_time": 0.6,
            "default_state_index": 0,
            "position_states": [
                {
                    "state_name": "closed",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "open",
                    "position_offset": [0.4, 0.2, 0],
                    "rotation_offset": [[0.866,-0.5,0],[0.5,0.866,0],[0,0,1]]
                }
            ]
        }
    ]
}
```

### 11. Ability Cast with Named Ability Matching

Charge vanes that open when a specific ability is cast.

```json
{
    "child_meshes": [
        {
            "mesh_alias_name": "charge_vanes",
            "mesh_point": "child_mesh_vanes",
            "is_weapon_effects_destination": false,
            "will_transition_positions": true,
            "state_constraint": "on_ability_cast",
            "ability_name": "phase_missile_barrage",
            "transition_time": 0.4,
            "default_state_index": 0,
            "position_states": [
                {
                    "state_name": "closed",
                    "position_offset": [0, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                },
                {
                    "state_name": "open",
                    "position_offset": [0.5, 0, 0],
                    "rotation_offset": [[1,0,0],[0,1,0],[0,0,1]]
                }
            ]
        }
    ]
}
```