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

Engine events

The goal: run Rust code when the engine says something happened: the game started, a frame passed, the actor was hit, a controller possessed the pawn.

#![allow(unused)]
fn main() {
#[uclass_impl]
impl Hero {
    #[ufunction(Override)]
    fn receive_begin_play(&mut self) {
    }

    #[ufunction(Override)]
    fn receive_tick(&mut self, delta_seconds: f32) {
    }

    #[ufunction(Override)]
    fn receive_end_play(&mut self, end_play_reason: u8) {
    }

    #[ufunction(Override)]
    fn on_landed(&mut self, hit: UStructRef<FHitResult>) {
    }
}
}

#[ufunction(Override)] implements an event of the parent class: one of the functions a Blueprint implements as an Event node (Event BeginPlay, Event Tick, Event Hit). The method is named after the event in snake_case and takes the event’s parameters, in order.

C++ virtuals are events

A C++ class overrides virtual functions (BeginPlay, Tick, NotifyHit). A Rust class, like a Blueprint, overrides the events the engine raises for them:

C++ virtualEventRust method
BeginPlayReceiveBeginPlayreceive_begin_play(&mut self)
EndPlayReceiveEndPlayreceive_end_play(&mut self, end_play_reason: u8)
TickReceiveTickreceive_tick(&mut self, delta_seconds: f32)
DestroyedReceiveDestroyedreceive_destroyed(&mut self)
TakeDamageReceiveAnyDamagereceive_any_damage(&mut self, damage: f32, damage_type: UObjectRef<DamageType>, instigated_by: UObjectRef<Controller>, damage_causer: UObjectRef<Actor>)
NotifyHitReceiveHitreceive_hit(&mut self, my_comp, other, other_comp, self_moved, hit_location, hit_normal, normal_impulse, hit)
NotifyActorBeginOverlapReceiveActorBeginOverlapreceive_actor_begin_overlap(&mut self, other_actor: UObjectRef<Actor>)
NotifyActorEndOverlapReceiveActorEndOverlapreceive_actor_end_overlap(&mut self, other_actor: UObjectRef<Actor>)
LandedOnLandedon_landed(&mut self, hit: UStructRef<FHitResult>)
OnMovementModeChangedK2_OnMovementModeChangedsee below
NotifyControllerChangedReceiveControllerChangedreceive_controller_changed(&mut self, old: UObjectRef<Controller>, new: UObjectRef<Controller>)
SetupPlayerInputComponentReceiveRestartedreceive_restarted(&mut self): the input component exists once a local player possesses the pawn
APlayerController::SetupInputComponentReceiveBeginPlayreceive_begin_play(&mut self)
OnPossessReceivePossessreceive_possess(&mut self, possessed_pawn: UObjectRef<Pawn>)
ChoosePlayerStartChoosePlayerStartchoose_player_start(&mut self, player: UObjectRef<Controller>) -> UObjectRef<Actor>
DrawHUDReceiveDrawHUDreceive_draw_hud(&mut self, size_x: i32, size_y: i32)
UpdateCameraBlueprintUpdateCamerasee Cameras
UAnimNotify::NotifyReceived_Notifysee Animation

Overriding receive_tick turns the actor’s tick on: nothing else is needed.

Parameter types

The event takesThe Rust method takes
A number or a boolthe Rust scalar (f32, i32, bool…)
An objectUObjectRef<T>
A classSubclassOf<T>
A struct (FHitResult, FVector)UStructRef<T>, a reference to the struct inside the call; to_owned() keeps a copy
An enumthe enum type or its u8 value
An output structUStructRef<T>, written in place
An output scalar or objectOutRef<T>, written with set

An event that returns a value returns it from the method:

#![allow(unused)]
fn main() {
#[ufunction(Override)]
fn choose_player_start(&mut self, _player: UObjectRef<Controller>) -> UObjectRef<Actor> {
    let starts = GameplayStatics::get_all_actors_of_class(
        self.as_ref().upcast_to(),
        SubclassOf::<PlayerStart>::base().upcast_to(),
    );

    starts.first().copied().unwrap_or_default()
}
}

Events whose name is not the method’s

When the event’s name is not the method’s name in PascalCase, name gives it:

#![allow(unused)]
fn main() {
const MOVE_FALLING: u8 = 3;

#[ufunction(Override, name = "K2_OnMovementModeChanged")]
fn on_movement_mode_changed(
    &mut self,
    _prev_movement_mode: u8,
    new_movement_mode: u8,
    _prev_custom_mode: u8,
    _new_custom_mode: u8,
) {
    if new_movement_mode == MOVE_FALLING {
    }
}
}

Finding an event’s name and parameters

An event is any function the parent class lets Blueprints implement. To find one:

  • in a Blueprint child of the parent class, right-click the Event Graph and look under Add Event: the node’s title is the event, and hovering it shows its name;
  • in the engine’s C++ headers, events are the UFUNCTION(BlueprintImplementableEvent) and UFUNCTION(BlueprintNativeEvent) declarations of the class, many named Receive... or K2_...;
  • in the generated bindings (Rust/bindings/src/), the class’s module lists them with their parameters.

A Blueprint child must not implement the same event

A Blueprint child that implements the same event in its graph replaces the Rust one: the engine runs the Blueprint’s graph instead. Keep the Blueprint children of Rust classes for data (meshes, sounds, input actions), and if a Blueprint needs to react too, give it an event of its own (see Functions, BlueprintImplementableEvent).