Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Components

The goal: an actor made of components, a mesh, a collision shape, a camera on a spring arm, created with every instance, as a C++ constructor’s CreateDefaultSubobject creates them.

#![allow(unused)]
fn main() {
use bindings::engine::{
    BoxComponent, CameraComponent, ProjectileMovementComponent, SceneComponent,
    SpringArmComponent, StaticMeshComponent
};
use rusteal_runtime::{uclass, uclass_impl};

#[uclass(parent = Actor)]
pub struct Door {
    #[component(root)]
    root: SceneComponent,

    #[component(attach = "root")]
    frame: StaticMeshComponent,

    #[component(attach = "frame", socket = "Hinge")]
    panel: StaticMeshComponent,

    #[component(attach = "root", name = "Trigger Box")]
    trigger: BoxComponent,
}

#[uclass_impl]
impl Door {}
}
ArgumentWhat it does
rootThe component is the actor’s root component.
attach = "<field>"The component it is attached to: one declared before it in the class, or an inherited one by its field-style name.
socket = "<name>"A socket on the parent component (a bone, a spring arm’s end).
name = "..."The component’s name in the editor, when it is not the field’s.

A component that is not a scene component (a movement component, a perception component, a StateTree component) has no transform: it takes neither root nor attach.

#![allow(unused)]
fn main() {
#[component(name = "Projectile Movement")]
projectile_movement: ProjectileMovementComponent,
}

Attaching to inherited components

A Character already has a capsule (its root), a skeletal mesh and a movement component. Attach to them by their field-style names:

#![allow(unused)]
fn main() {
#[uclass(parent = Character)]
pub struct Hero {
    #[component(attach = "root_component")]
    camera_boom: SpringArmComponent,

    #[component(attach = "camera_boom", socket = "SpringEndpoint")]
    follow_camera: CameraComponent,
}
}
Inherited componentField-style name
The root component of any actorroot_component
A character’s skeletal meshmesh
A component of a Rust parent classits field’s name (first_person_camera_component)

Reaching a component

Each component gets a getter that returns a reference to it:

#![allow(unused)]
fn main() {
let boom = self.camera_boom()?.checked()?;
boom.set_target_arm_length(400.0);
}

The getter returns a RustealResult, because the component may not exist on the object at that moment (an object being destroyed). Inherited engine components come from the engine getters: me.get_mesh(), me.get_capsule_component(), me.get_character_movement().

Names and Blueprints

A component’s name is its field’s name, or name. A Blueprint child’s changes to an inherited component, a mesh assigned to it, a collision preset, are saved under that name. Keep it stable once Blueprints use the class: renaming the field without name loses those changes. When you port a C++ class, give each component the name the C++ CreateDefaultSubobject used, and the Blueprint children keep their data.

Configuring components

The values a component starts with go in Class defaults:

#![allow(unused)]
fn main() {
use bindings::engine::{BoxComponentExt, PrimitiveComponentExt};

#[class_defaults]
fn class_defaults(&mut self) -> RustealResult<()> {
    let trigger = self.trigger()?.checked()?;
    trigger.set_box_extent(&FVector::from_dvec3(DVec3::new(100.0, 100.0, 120.0)), Some(false));
    trigger.set_collision_profile_name(FName::new("OverlapAllDynamic").handle(), Some(true));
    Ok(())
}
}

Adding a component at runtime

A component created during the game, for example on an actor the class does not own, is added through the engine:

#![allow(unused)]
fn main() {
let class = SubclassOf::<InventoryComponent>::base().upcast_to::<ActorComponent>();
let identity = FTransform::from_transform(Transform::IDENTITY);
let component = actor.checked()?.add_component_by_class(class, false, &identity, false);
}

See the inventory recipe.

In the editor

The Blueprint child’s Components panel lists the Rust components as inherited components: select one to change its mesh, material or collision in the Details panel.

Screenshot: the Components panel of a Blueprint child listing the components of a Rust class. (images/classes/components_panel.png)