using { /Fortnite.com/Characters } using { /Fortnite.com/Animation/PlayAnimation } using { /Fortnite.com/Devices } using { /Verse.org/Assets } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # PLAY AN ANIMATION ON A PLAYER'S CHARACTER — directly, from Verse. # # Before the /Fortnite.com/Animation/PlayAnimation module, playing an animation # on the *player's own character* meant hacks: spawning a hidden NPC, swapping # meshes, or driving an Animated Mesh device standing in for the player. Now the # path is a straight line: # # 1. agent -> fort_character Presser.GetFortCharacter[] # 2. character -> play_animation_controller # Character.GetPlayAnimationController[] # 3. controller.Play(sequence, ...) -> play_animation_instance # # The instance is a remote control for that one playback: Stop it, read its # GetState, or subscribe to its CompletedEvent / InterruptedEvent. # # This device wires two buttons: one plays an editor-chosen animation sequence # on whoever pressed it, the other stops the most recent playback. play_emote_on_press_device := class(creative_device): # The animation to play. You CANNOT build an animation_sequence in Verse # (its constructor is epic_internal) -- it's an editor-imported asset. So the # slot is an OPTION: pick the asset in the device's Details panel in UEFN, # and we unwrap it at use with `EmoteAnim?`. @editable EmoteAnim : ?animation_sequence = false # Press to play the animation on the presser's character. @editable PlayButton : button_device = button_device{} # Press to stop the most recent playback. @editable StopButton : button_device = button_device{} # Remember the latest instance so the Stop button can cancel it. var CurrentAnim : ?play_animation_instance = false OnBegin() : void = PlayButton.InteractedWithEvent.Subscribe(OnPlayPressed) StopButton.InteractedWithEvent.Subscribe(OnStopPressed) # GetFortCharacter and GetPlayAnimationController both , so they go # in an `if` together with the option unwrap -- all three must succeed. OnPlayPressed(Presser : agent) : void = if: Anim := EmoteAnim? Character := Presser.GetFortCharacter[] Controller := Character.GetPlayAnimationController[] then: # Play() returns the instance IMMEDIATELY -- it does not suspend. # The optional ?params let you re-time and blend the clip. Instance := Controller.Play( Anim, ?PlayRate := 1.0, # 1.0 = authored speed ?BlendInTime := 0.2, # ease in over 0.2s ?BlendOutTime := 0.2) # ease out over 0.2s set CurrentAnim = option{Instance} Print("Playing animation on the presser's character") # Stop() halts the playback (it blends out and fires InterruptedEvent). OnStopPressed(Presser : agent) : void = if (Instance := CurrentAnim?): Instance.Stop() Print("Stopped the animation")