14 — Step-by-step tutorials¶
🇬🇧 English | 🇺🇦 Українська
Seven short lessons for those who are building item interaction for the first time. Each lesson has a goal, steps and a "What you should get" item: if the result differs, there are hints at the end of the lesson. The lessons go from simple to complex, but each can be done on its own. Terms that may be unfamiliar are explained in the glossary.
For all lessons:
- the plugin is enabled in Edit → Plugins → InteractionSystem and the editor is restarted;
- in the Content Browser → Settings Show Plugin Content is enabled, so you can see the plugin's classes and demo;
- the project is on Unreal Engine 5.8; the First Person or Third Person template will do.
Lesson 1. A first item you can pick up¶
Goal: the player aims their gaze at a crate, presses E — the crate ends up in front of them; F — throws the crate.
Time: 10 minutes.
Steps¶
- Open your character's Blueprint. In Components → Add add an
InteractorComponentand drag it onto the camera. In Details keepUse Pawn Viewpointon and setGrab Offsetto(70, 0, -15).
In plain words.
InteractorComponentis "a hand with a laser pointer". The pointer (the ray) shows what you want to take, andGrab Offsetis where this hand holds what it took: 70 cm in front of the camera and slightly lower.
- Create Content Browser → Add → Blueprint Class → All Classes → InteractionMasterItem and name it
BP_Crate. InMesh ComponentassignCubeand set the scale to0.4. - Drag
BP_Crateonto the level about 2 m in front of the player's start. - Create the Input Actions
IA_UseandIA_Throw(type Digital (bool)) and the Input Mapping ContextIMC_Interaction:E → IA_Use,F → IA_Throw. Add the context to the player the same way the template adds its own (the Add Mapping Context node in Event Receive Controller Changed or in Begin Play). - In the character's Event Graph:
- IA_Use → Started →
Request Grab(the target is yourInteractorComponent); - IA_Throw → Started →
Request Release:Linear Velocity= Get Forward Vector of the camera ×900,Angular Velocity=(0, 120, 0). - Press Play.
What you should get¶
- When you approach the crate, a small dot appears above it: an item is nearby.
- When you aim the screen center at the crate, the dot changes to
Eand the crate is highlighted. - After
Ethe crate ends up in front of the camera and moves with you. - After
Fthe crate flies forward and falls; it can be taken again.
If it did not work¶
| What you see | What to check |
|---|---|
Neither a dot nor E |
The crate is closer than 300 cm (Trace Distance); the mesh collision blocks the Visibility channel |
E is there but the crate is not taken |
Whether Request Grab is called (add a Print String); whether the input context is active |
| The crate is taken but does not fly | Whether you pass a non-zero Linear Velocity to Request Release |
For any unclear case open the debug panel with the command InteractionOverlay (15): it shows focus, the state of the hand and the server's answer.
Lesson 2. A door that opens for every player¶
Goal: a door opens when E is pressed, and all players see it open.
Steps¶
- Create a Blueprint Actor
BP_Door, and in Class Defaults enable Replicates. - Add a Static Mesh
Leaf(the door leaf) with collision and Mobility = Movable. - Class Settings → Interfaces → Add →
InteractableInterface. - Add a variable
bOpen(Boolean) and in Details → Replication choose RepNotify. The editor will create the functionOnRep_bOpen. In it:Leaf → Set Relative RotationwithYaw = Select(bOpen, 90, 0). - Implement Event Interaction:
Set bOpen = NOT bOpen. - Override the function
Can Interact: returntrueifAction == Interact. - In the character from lesson 1 add a second action or change
IA_Use: if Get Focused Actor cannot be grabbed (it is not anInteractionPhysicsActoror hasCan Be Grabbed = false), callRequest Interactioninstead ofRequest Grab. The ready logic of such a choice is described in 11. - Check in the network: Play → Net Mode → Play As Client, Number of Players = 2.
In plain words.
Interactionruns on the server, as if the referee wrote down "the door is open". RepNotify is the mailing of this news: every client receives the newbOpenand turns the leaf in its own copy of the world.
What you should get¶
One player presses E near the door — in both windows the door turns 90°. Another E closes it for both.
If it did not work¶
- The door opens in only one window: the leaf is turned directly in
Interactionand not throughbOpenwith RepNotify. - The door does not react on the client:
BP_Doordoes not have Replicates enabled. The server rejects actions with non-replicated actors (reasonInvalidTarget).
Lesson 3. Telling the player why an action failed¶
Goal: when the server rejects an action, the player sees a clear message.
Steps¶
- Select the character's
InteractorComponentand in Details → Events click + next toOn Action Result. - The event gives
Target Actor,Action,AcceptedandReason. IfAccepted = false, connect Switch on EInteractionRejectReason and output text (Print String or your widget):
Reason |
What happened | Example message |
|---|---|---|
Cooldown |
Pressed more often than Min Action Interval allows |
"Not so fast" |
InvalidTarget |
The target disappeared or is not replicated | "This item is unavailable" |
InvalidPose |
The server did not believe the hand position: far from the body, behind a wall, stale | "Your hand is too far" |
NotReachable |
The server's ray did not reach the target | "Cannot reach" |
HandBusy |
The hand already holds something | "Your hand is busy" |
Claimed |
Another player holds the target | "Someone is holding this item" |
Unavailable |
The target refused: grabbing is off, no room, no action | "Not possible right now" |
- Check: start two players (Play As Client, 2 players), take the crate with the first player and try to take the same crate with the second.
What you should get¶
The second player sees "Someone is holding this item": the server answered Claimed.
In plain words.
On Action Resultis the referee's answer to your application. It does not only say "no", it also explains which rule fired.
Lesson 4. A drawer that slides out of a cabinet¶
Goal: a drawer in a cabinet slides out after the hand, but no more than 40 cm, and moves together with the cabinet.
Steps¶
- Create a Blueprint Actor
BP_Cabinetwith Replicates. The root is the Static Mesh of the body. - Add a child Static Mesh
Drawer: Mobility = Movable, collision blocks Visibility. Do not enable Component Replicates: the manipulation carries the drawer's motion. - Add an
InteractionManipulationComponentand in its Details: Target Component Name = Drawer— move only the drawer, not the whole cabinet;- Inline Settings:
Maximum Hands = 1,Constraint = Linear,Constraint Axis— the sliding direction in the drawer's axes (for example(1, 0, 0)if its front panel looks along +X),Minimum Value = 0,Maximum Value = 40,Simulate On Releaseoff. - Optionally choose
InteractionManipulationComponent→ Events → On Handle Changed: whenFraction ≥ 0.99, play the sound of a fully extended drawer. - Play: take the drawer (
Efrom lesson 1) and step back.
What you should get¶
- The drawer travels only along its axis and stops after 40 cm, however far you step back.
- After release the drawer stays extended and remains part of the cabinet.
- If the cabinet moves (for example you move it in Blueprint), the drawer moves with it and still slides out relative to the cabinet.
- A call of
Reset Manipulationon the server closes the drawer.
In plain words.
Constraint = Linearis rails for the drawer.Minimum ValueandMaximum Valueare the stops at the ends of the rails in centimeters.
If it did not work¶
- The whole cabinet is taken:
Target Component Nameis not set or has an error in the name. - The drawer is not taken: the profile has
Maximum Hands = 2(a constraint needs one hand) orMovement = Physics(a constraint needsDirect). The reason is shown byValidate Setupand the debug panel.
Lesson 5. A Blueprint lantern: a custom grab target without C++¶
Goal: a lantern that is taken into the hand, switched on with the use button and stays where it was put. All the rules are in Blueprint.
Steps¶
- Create Blueprint Class → All Classes → InteractionBlueprintGrabTargetComponent and name it
BP_LanternGrab. This is a component in which you yourself describe what happens on a grab. - Open
BP_LanternGrab, and in Functions → Override add: - Begin Grip (
In Hand):Get Owner → Attach Actor To ComponentwithParent = In Hand, rulesSnap to Target; returntrue; - End Grip (
In Hand,In Reason, velocities):Get Owner → Detach From ActorwithKeep World; - Use (
In Hand): toggle the owner's light (see step 4) and returntrue. - Create a Blueprint Actor
BP_Lantern: enable Replicates and Replicate Movement (so the attachment to the hand reaches clients). The root is a Static Mesh with collision that blocks Visibility; a child Point Light. - In
BP_Lanternadd a variablebLightOnwith RepNotify; inOnRep_bLightOnswitch the light's visibility. InBP_LanternGrab → UsecallSet bLightOn = NOT bLightOnon the owner (Cast To BP_Lantern). - Add
BP_LanternGrabto the components ofBP_Lanternand put the lantern on the level. - In the character: if the hand already holds an item (
Get Held Actoris valid), pressingEshould callRequest Interaction— this is "use the item in the hand".
What you should get¶
Eon the lantern — it ends up in the hand and moves with you; the second player sees the lantern in your hand.- Another
E— the light turns on or off for everyone. F— the lantern stays hanging where you released it (there is no physics: yourEnd Gripdecided so).
In plain words. The plugin keeps the role of the referee: who may take, whether anyone else is holding, whether the hand is too far. And what to do with the lantern after permission is decided by your Blueprint.
Good to know¶
- Can Begin Grip is called both on the client (for the prompt) and on the server. Read only replicated state in it, change nothing.
- Begin Grip, End Grip and Use run only on the server.
In Reason = Releasedmeans an intentional release; other reasons are cancellations, and the item should not be thrown then.Set Grab Enabled(false)on the server forbids new grabs and releases the current hands.
Lesson 6. A crate that breaks under impacts¶
Goal: a crate withstands several strong impacts and bursts apart with an effect that everyone sees.
Steps¶
- Create a Blueprint from
InteractionPhysicsActor—BP_FragileCrate; assign a mesh. - Create a Data Asset from
InteractionPhysicsDataAssetwithStart With Physics = trueand assign it inObject Data. - Add an
InteractionDestructibleComponent. In Class Defaults setHealth = 30,Destroy Effect— any Niagara system (or Cascade),Damage Per Impulse = 0.01,Minimum Impact Damage = 5. - Optionally: Events → On Impact Destroyed → play a sound at the point
Location. The event fires on the server and on every client. - Play: take another crate (from lesson 1) and throw it at
BP_FragileCrateseveral times, or throwBP_FragileCrateitself at a wall.
What you should get¶
Light touches do nothing. After several strong impacts the crate disappears with a destruction effect in all windows.
In plain words. The damage from an impact = the strength of the impact ×
Damage Per Impulse. Impacts weaker thanMinimum Impact Damageare not counted, so a crate that just lies there or slides slowly does not wear out.
If it did not work¶
- The crate does not break: reduce
Healthor increaseDamage Per Impulse; make sure the crate simulates physics. - You want to break the crate with a sword strike or an explosion: call
Apply Impact Damage(Amount, Location)on the server from your logic.
Lesson 7. Testing in multiplayer and finding causes¶
Goal: learn to see what the server sees and to find the cause when an item "is not taken".
Steps¶
- Play → Net Mode → Play As Client, Number of Players = 2, press Play.
- In the client window open the console (
~) and typeEnableCheats— on a PIE client the debug commands are unavailable without it. - Type
InteractionOverlay. A panel appears on the right. - Aim the hand at an item and try to take it. Look at the State, Focus and Last answer rows in the Local sources card.
- Type
InteractionClaims: the server prints to the console who holds what. - Add network latency:
Net PktLag=150. Take an item again and see how the Waiting for the server state lasts longer.
What you should get¶
- The panel shows the role
CLIENT, your sources, focus and the server's answer to each attempt. - During the latency the item in your hand still moves at once: the motion in the owner's hand is predicted, and the server only confirms it.
- The messages in Recent answers explain every rejection; hover over one to read the explanation.
The panel and all commands are covered in detail in 15 — Debug tools.