API guide and reference - APIAPI's Replicated Rope & Physics-Carry Kit

Every rope, zipline and carry feature, event and setting.

Assumes you have read install.md and quick-start.md. For what runs where on the network, read network-model.md.

This page is organised by feature. Each section names the classes you use, the events you bind and the rules that hold on a networked game. The reference index at the end lists every public class with its module.

Ropes

A rope is a UUKRopeComponent (module UKRope). Put it on the kit's UK Rope Actor (AUKRopeActor), or on an actor of your own. Its authoring properties are:

PropertyMeaning
PresetThe UUKRopePreset data asset that decides what the rope is (tether, cuttable rope, zipline) and how it collides.
AnchorA, AnchorBEach end's binding: an Actor, an optional Socket on its root component and a LocalOffset. An empty Actor leaves that end free.
RestLengthOverrideCmThis instance's rest length, read when the preset's rest-length policy is FromActor.
bRopeOwnsActorLifetimeOpt in when your own actor class exists only to carry this rope (see below).

The server simulates the rope and owns its state; every client simulates its own copy and is corrected toward the server's. In Blueprint, read IsCut() and IsCuttable() for state, GetRiderState() for a zipline's rider and GetPresetStats() for cut and ride counters; from C++ also IsSimulating(), GetTopology() and GetReplicationStats().

Rope and actor lifetime

AUKRopeActor net settings

AUKRopeActor copies CorrectionRate (→ NetUpdateFrequency) and NetCullDistance (→ NetCullDistanceSquared) from Project Settings › UK Rope › Replication when its class default object is built:

  • A settings edit reaches the actor only after an editor restart (and in a packaged game, from the start). Placed actors and Blueprint subclasses keep the values their class default had when the editor started; set the actor's own net settings directly to override them per actor.
  • Relevancy is measured from the actor's root, which stays where the actor was placed — or, for a cut piece, the parent's transform — however far the rope's particles swing or fall. Keep NetCullDistance well above the rope's length plus its expected swing, or clients far from the actor's origin lose the rope while its end is still near them.
  • A cut parent goes dormant (DORM_DormantAll): it never changes again, so it costs no replication. A client that joins or becomes relevant later still receives its final (cut) state.

A rope end whose anchor is not visible to a client

Moving anchors on clients

Rope events

EventWhen it fires
OnRopeCut(SegmentIndex, bFromInitialState)The rope was cut. bFromInitialState is true when this machine learns about an older cut (a join, or the rope became relevant).
OnChildRopeReady(Child)A cut piece of this rope is known on this machine.
OnRopeOrphanedNo end of the rope is bound any more.
OnRiderStateChanged(OldState, NewState)The server wrote the zipline rider state (server only).
OnZiplineMounted(Pawn), OnZiplineDismounted(Pawn, Reason)A ride started or ended, on every machine. See Ziplines.

ServerCut(SegmentIndex) (Blueprint: Server Cut, authority only) cuts the rope directly from server code; players cut through their interactor (see Requests). SetPreset sets the preset of a rope you spawn yourself; it is accepted only before the rope's BeginPlay (afterwards it is ignored with UK-VAL-189).

Rope presets

A UUKRopePreset is a data asset: in the Content Browser choose Miscellaneous › Data Asset and pick the class UKRopePreset. It is read once, when the rope begins play, and is fixed for the rope's life.

Field groupFields
What the rope isMode (Tether, CutRope, Zipline), RestLengthPolicy (FromAsset, FromAnchors, FromActor), RestLengthCm, SlackFraction, SegmentCount, bAllowMovableAnchors
CollisionRopeRadiusCm, CollisionMode (Cache or Sweep), CollisionObjectTypes, bAcknowledgeDynamicCollisionCost
CuttingbCuttable, MaxCutDepth
InteractionReachCm, bRequiresLineOfSight
ZiplineModeSpeed, HangOffsetCm, bBidirectional, bAllowMountWhileHolding, bAllowCarryWhileRiding, Exit (ExitMarginCm, ExitVelocityScale, ExitUpImpulseCmS, bDismountOnRequest)

CollisionObjectTypes lists object types, not a trace channel. A preset whose object types include moving objects (WorldDynamic, Pawn, ...) refreshes its collision every frame; set bAcknowledgeDynamicCollisionCost to say you accept that cost. A preset saved by a newer kit than the one installed is refused (UK-VAL-186) and the rope stays unbound. The GrappleHook and Swing modes are reserved for a later version and refused today (UK-VAL-185).

Requests: cut, mount, grab, drop, throw

A player acts through the UUKRopeInteractorComponent on its pawn (module UKRope; add it to the pawn Blueprint). Every request is called on the locally controlled pawn; a call on any other machine's copy is refused (UK-VAL-150).

CallVerbNotes
RequestCut(Rope, SegmentIndex)CutThe rope's preset must be cuttable.
RequestMount(Rope), RequestDismount()Mount, DismountZipline presets. See Ziplines.
RequestGrab(Target)GrabTarget is the object's UUKCarryableComponent.
RequestDrop(), RequestThrow(ThrowChargeQ)Drop, ThrowThrowChargeQ is the charge as a byte: 0 is a drop at the carrier's velocity, 255 a full-charge throw (from the preset's ThrowSpeedMin to ThrowSpeedMax, scaled down by the weight class).

Each call returns the request's RequestSerial. The answer arrives as OnRopeRequestResolved(Result): Result.RequestSerial, Result.Verb, Result.bAccepted and, when refused, Result.Reason (an EUKRopeRejectReason). OnPredictedRequestStarted(Verb, Target) and OnPredictedRequestEnded(RequestSerial, Why) bracket the local presentation of a pending request; Why is an EUKRopePredictionEndReason (ServerResolved, LocalResolved, Retracted, OwnerLost, Timeout). Read GetPendingVerb, GetPendingRequestSerial, IsRiding and GetStats() for state and diagnostics.

The server checks every request again: reach (the preset's ReachCm plus a tolerance), line of sight, the preset, and the object's or rope's state. A client sends at most a few requests per second; extra presses are refused locally as Throttled.

Requesting a cut: the result can arrive before RequestCut returns

Malformed requests and UK-VAL-151

Teardown calls the release path twice

Carry events on a listen host fire inside the request

Throws follow the player's view

Ziplines

A rope whose preset mode is Zipline can carry one rider. Call RequestMount(Rope) on the locally controlled pawn's UUKRopeInteractorComponent (Blueprint: Request Mount) and RequestDismount() to leave; each returns its RequestSerial and the outcome arrives through OnRopeRequestResolved — like RequestCut, possibly before the call returns (a local refusal, a listen host's own pawn, standalone), so key on Result.RequestSerial. The server answers with one reason: WrongPreset (not a Zipline, a cut rope, or a rope too short for its exit margins), OutOfReach (the pawn root farther than the preset's reach plus the tolerance from the nearest mountable point — the line lowered by HangOffsetCm, kept ExitMarginCm away from each end — or a mount whose ride toward its end would be shorter than ExitMarginCm), InvalidAnchor (an end of the line is gone), NoLineOfSight, AlreadyRiding (the rope already has a rider, or the pawn rides another rope) and AlreadyHeld (the pawn carries an object and the preset's bAllowMountWhileHolding is off); a dismount answers NotRiding, or WrongPreset when the preset's exit rules turn bDismountOnRequest off. Nothing is predicted: the mount is shown from the rope's replicated rider state — read it with UUKRopeComponent::GetRiderState() (rider pawn, ride direction, mount point MountT, server time of the mount), and on the server bind OnRiderStateChanged. The rider state is written only through ServerMountRider / ServerDismountRider, which update the rope and the pawn together.

Direction. The direction of a ride is chosen at the mount: downhill toward the lower anchor; on a level line (height difference within Project Settings → UK Rope → Presets → Level Tolerance Cm, default 10) toward the far anchor; a preset with bBidirectional follows the player's view. RequestMount sends the pawn's view direction with the request, so a two-way zipline goes the way the player looks on every pawn type — ACharacter or not. From C++ the server call is ServerMountZipline(Rope, RequestSerial, AimDir); UUKRopeComponent::ServerMountRider(Pawn, AimDir) takes the same optional aim (zero = the pawn's control rotation on the server).

Riding. Once mounted, the pawn travels along the line at the preset's ModeSpeed toward the end chosen at the mount, moved by its movement bridge on the server and on the owning player's machine (other players see the server's movement through normal replication). Pawns with a UPawnMovementComponent that are not ACharacter (for example UFloatingPawnMovement) use the built-in default bridge, and while they ride their own movement component does not tick (the bridge is the only integrator; the tick comes back at the dismount). An ACharacter rides through the Character Movement adapter (see Ziplines on a Character). A pawn with no movement component mounts but does not move (one UK-VAL-121 warning per machine). IsRiding() on the interactor reads true on the server and on the owning player's machine while the ride runs (never on other players' machines).

The rider is pulled onto the line: a pawn may mount from anywhere inside the reach (up to ReachCm + tolerance, 300 cm with the defaults); during the ride it is drawn smoothly onto its hang line (HangOffsetCm below the cable) without changing its speed along the cable — Project Settings → UK Rope → Presets HangConvergeRate (4 /s) and MaxHangConvergeCmS (400 cm/s; 0 turns the pull off). A pawn standing on a platform under a downhill cable lifts off it when MaxHangConvergeCmS × cos(slope) > ModeSpeed × sin(slope) (an 11° cable: yes with the defaults); raise MaxHangConvergeCmS for steeper cables.

Reaching the end. The ride ends ReachedEnd once the pawn has travelled from its mount point to within ExitMarginCm of the far anchor — it never ends on the frame it starts, even when the player mounts right at the end of the usable span — and the pawn leaves with the exit velocity of the preset (ExitVelocityScale × ride velocity + ExitUpImpulseCmS up). A single long frame never carries the rider past the end of the line — the last step stops at the exit. The owning player's screen stops at the end of the line and waits there for the server's dismount (no overrun on a slow or lossy connection).

How a ride ends

Stuck. A rider that stops making progress toward its exit is dismounted with Reason Stuck after Project Settings → UK Rope → Presets → Stuck Seconds (default 3 s, 0.5–10). The usual cause is a blocking obstacle across the line: the default bridge stops the pawn at the first blocking hit — it does not slide around it — so keep a zipline's path clear of geometry that blocks your pawn. The server logs one LogUKRope warning naming the rope, the pawn and its class. A frame counts as stalled when the pawn moved less than the smaller of 1/10 000 of the line's length and half of what the ride asked for, so slow rides on very long lines are not mistaken for stuck ones. A pawn the kit cannot move (no movement component, no bridge) is never dismounted Stuck; it stays on the line until it is dismounted. Keep the preset's ExitMarginCm above your pawn's radius plus the end post's half-width: a pawn that reaches the post before the exit hangs there and is dismounted Stuck after Stuck Seconds on every ride.

Other endings. Cutting a ridden zipline dismounts the rider RopeCut before the two cut pieces appear — no piece ever carries a rider, and the player can mount again at once. When either anchor of a ridden zipline is destroyed, the rider is dismounted AnchorLost in the frame the server sees the loss. A rope that loses both anchors is removed after Orphan Linger Seconds (default 2), and a rope that keeps one anchor stays. Destroying or unloading a ridden rope also dismounts its rider AnchorLost. A pawn that loses its controller or is destroyed is dismounted by the server. A possession change dismounts the rider OwnerLost in the frame of the change — mount the pawn again after Possess if it should keep riding. Replacing or destroying the pawn's movement component dismounts it BridgeLost. Every one of these endings releases the pawn with the velocity its ride last asked for, without the preset's exit scale or impulse, which apply to ReachedEnd and Requested only — for Stuck that is the ride's speed toward the obstacle, not the pawn's (zero) speed.

A new controller mid-ride. After a possession, the new owner can keep running the previous owner's ride until the rope's dismount reaches it. On a good connection that is 0 frames; when the packet carrying the possession is lost, the rope's dismount is re-sent at the rope's next network update, so with the default 5 Hz rope rate the new owner rode on for up to 4 frames (up to 53 cm at 800 cm/s) in our tests and ended up to 87 cm further along the line than the server (at most one rope update — 160 cm at 800 cm/s — per lost packet). On a pawn without a CharacterMovementComponent nothing corrects that difference afterwards: if it matters, teleport or remount the pawn after Possess. (Measured with default replication; with Iris the dismount arrived with the possession in every test.) A stall that only the server sees — another player standing on the line on the server but not yet on the owner's screen — ends the ride Stuck where the server stopped it, while the owner's screen rides on to the end of the line and waits there; the two can be several metres apart afterwards on such a pawn.

Events. Bind OnZiplineMounted(Pawn) and OnZiplineDismounted(Pawn, Reason) on the rope (UUKRopeComponent, Blueprint: On Zipline Mounted / Dismounted). Every mount a machine announced gets exactly one OnZiplineDismounted — when the rope is destroyed under its rider, clients receive AnchorLost as the rope goes away. Reason is exact on every machine (the server sends it with the dismount); only a dismount and a new mount that happen between two network updates are reported as worked out locally, and a ride that starts and ends between two network updates is not announced on clients at all (neither event), so count riders from the server, or from both events per machine. Each rope announces exactly one OnZiplineDismounted per OnZiplineMounted, but between two ropes the order is not guaranteed on clients: when a pawn hops from one zipline straight onto another, its owner may hear the second rope's Mounted before the first rope's Dismounted. Keep "is riding" state with IsRiding() / GetMountedRope() rather than a flag set by both delegates.

Carrying and riding. By default a pawn holding an object cannot mount (AlreadyHeld) and a riding pawn cannot grab (AlreadyRiding). Set the preset's bAllowMountWhileHolding to let a carrier ride with its object attached, and bAllowCarryWhileRiding to allow grab, drop and throw during a ride; none of them ends the ride. A heavy object does not slow a zipline ride, whose speed is the preset's ModeSpeed, and an object dropped or thrown while riding leaves with the ride's speed; the carry slowdown applies again once the pawn is off the line.

Players who join while someone rides a zipline

A player who joins a session while someone is riding a zipline sees the rider on the line from the frame both the rope and the rider exist on their machine: GetRiderState().Rider names the riding pawn and OnZiplineMounted fires once for that ride (never for a ride that ended before the join — a rope that was ridden and left earlier announces nothing). The joining player's machine never runs that ride: the rider is moved by the server's replication (a Character rider keeps its Custom movement mode 200 and keeps moving along the line between updates), and nothing is applied to the rider through the joining machine's movement bridge. If the rope reaches the joining player before the rider's pawn does, IsRiderPending() reads true until the pawn arrives, and the ride is announced then. If a joining player later takes control of a pawn that is riding (a possession), the server ends that ride (OwnerLost) in the same moment. On a connection without packet loss the new owner runs no frame of that ride; when the packet carrying the server's end is lost, the new owner's machine can keep riding for a few frames until the rope's next update (measured up to 4 frames, which left a non-Character pawn up to about 87 cm from the server's position) — see A new controller mid-ride above. Measured with separate game processes on 5.6, 5.7 and 5.8, default replication, and with Iris on 5.8 (the "rope before rider" order was measured with default replication only).

Carrying objects

Three classes, all in module UKRope:

ClassPut it onWhat it does
UUKCarryComponentthe pawnHolds at most one object. Events OnGrabbed, OnDropped(Object, Reason), OnThrown, OnGrabRejected(Object, Reason), OnReachStarted, OnReachEnded(Object, Why); read GetHeldObject(), IsReaching(), GetReachTarget(). Server-side C++: ServerGrab, ServerDrop, ServerThrow.
UUKCarryableComponentthe object (a physics actor with Replicates and Replicate Movement on)Owns the object's replicated carry state. Event OnCarryStateChanged(OldState, NewState); read GetCarryState(), GetHolder(), GetGripSocket(), GetPreset(), GetCarryStats().
UUKCarryPreseta data asset on the carryable's PresetWeight (WeightClass, PenaltyCurve, bUseMass, RefMassKg, MassSpanKg, MassOverrideKg), grip (GripSocket, GripOffsetDefault, GripPaddingCm), throw (ThrowSpeedMin, ThrowSpeedMax), HeldCollisionProfile, and the grab's ReachCm / bRequiresLineOfSight. An empty Preset uses the class defaults.

The carry state (FUKCarryState) has a Phase (Idle, Held, Throwing, Free), the Holder, the GripOffset, Flags and a change Serial. OnDropped reports an EUKCarryReleaseReason: Dropped, Thrown, OwnerLost (the holder went away) or ObjectLost (the object went away). An object whose Replicate Movement is off is still carried, but a thrown or dropped object then moves only on the server (UK-VAL-160).

Dropping and throwing: what every machine sees

Four details of the release:

Held objects near walls

While an object is held, the server checks about 30 times a second (Grip Clamp Hz) whether the object fits at its grip offset, and pulls it in toward the carrier when a wall is in the way, keeping Grip Padding Cm between the object and the wall. Floors, ramps a character can walk up (up to about 45 degrees) and walls beside or behind the carrier never pull it in. This also works against level geometry that uses its complex collision as simple collision (one mesh for the floor and the walls).

  • OnCarryStateChanged fires while the object is held. The event also fires when only the grip offset changes: walking toward a wall can fire it up to Grip Clamp Hz times a second, on the server and on every client. Compare NewState.Phase with OldState.Phase before you play a pickup or drop sound or update the UI.
  • Fast carriers and the padding. Between two checks the object moves with the carrier. A carrier walking at speed v toward a wall can push the object up to v / Grip Clamp Hz − Grip Padding Cm into it on other players' screens. With the defaults (padding 5 cm, 30 checks a second) that is no overlap up to 150 cm/s and about 15 cm at the Character Movement Component's default 600 cm/s. The player holding the object does not see this: their own machine checks the wall every frame for its display (see How the holder sees a held object). Other players' copies are not wall-checked locally; raise Grip Padding Cm (or Grip Clamp Hz) if your carriers walk faster and the overlap shows there.
  • ClampMicroseconds and ClampApplyMicroseconds in GetCarryStats() time the server's check and its write separately. The write includes your OnCarryStateChanged listeners.

How the holder sees a held object

Held objects and pawn collision

Removing only the carryable component from a held object (DestroyComponent) releases the object on the server: it leaves the carrier, simulates again if it simulated before the grab, and gets its Pawn response back. The kit wakes the actor for this, so the release also reaches clients when the actor is dormant. On the server the carry slowdown ends at once; the server's carrier and every client's copy of it that showed the hold fire OnDropped with ObjectLost. Every client releases its copy the same way, on both replication systems:

  • Generic replication (the default): every client removes its copy of the component and restores the object.
  • Iris: a carryable component that is part of the actor's class (added in C++ or in the Blueprint components list) or placed in the level is not removed on clients — the copy stays on the actor, but the kit notices that the server let go of the object and restores it on that client: it falls with physics, gets its Pawn response back, and the carrying player can grab again at once. Its GetCarryState() and GetHolder() keep reading Held and the former carrier on those clients (that component no longer receives updates), and another player's Grab of it is refused there by the local check (AlreadyHeld) — the server has no carryable left to grab; read the carrier's GetHeldObject() instead. A carryable added at runtime with AddComponentByClass is removed on clients.

When the holder or the object goes away

A held object is never left attached to something that no longer exists:

  • The holder disconnects, dies or is unpossessed. The server releases the object in that frame, as a drop with no throw: it falls where it was held. The server's carrier fires OnDropped with OwnerLost once — also when a possessed pawn is destroyed, where the engine first detaches the controller. Clients see an ordinary release (OnDropped with Dropped on their copy of the carrier, if that copy still exists). A new controller that takes over the pawn starts with empty hands and can grab at once.
  • The held object's actor is destroyed (or its level is unloaded). In that frame the server's carrier holds nothing, its carry slowdown ends, and it fires OnDropped with ObjectLost once. A later Drop or Throw from that player is refused with NotHolding, quietly (no log above Verbose). Clients simply lose the object: their carrier copies stop holding it and fire no event.
  • The carry component itself is removed (DestroyComponent on the UUKCarryComponent — a Game Feature that added it removes it this way when it deactivates). The server releases the held object in that call, exactly like a holder that died: it falls where it was held, the carrier fires OnDropped with OwnerLost once, and anyone can grab it again. A pawn destroyed afterwards fires nothing more.
  • Your own code detaches the held object on the server (DetachFromActor / DetachFromComponent, or SetSimulatePhysics(true) on it, which detaches it too). The kit treats this as a drop at its next hold check (at most one Grip Clamp Hz tick later): the server's carrier lets go, its slowdown ends and it fires OnDropped with Dropped; the object gets back the movement-replication, Pawn-response and simulation settings it had when it was grabbed (an object that did not simulate before the grab stops simulating). Clients usually see the detach first and fire OnDropped with ObjectLost on their copy of the carrier — one event per copy either way. To let go on purpose, prefer the carrier's ServerDrop / ServerThrow: every machine then reports Dropped / Thrown.

Two players grabbing the same object

Carry state writes and UK-VAL-163

Carry slowdown and object weight

A held object slows its holder by its preset's Weight Class (Light none, Medium 0.8, Heavy 0.55 of the walk speed). The slowdown is applied on the server and on the holding player's own machine, through the pawn's movement bridge. Other players' machines never apply it — they see the holder's movement as the engine replicates it.

  • Which pawns are slowed. A pawn with a movement component that is not a Character (for example a Floating Pawn Movement) is slowed through the kit's default movement bridge, and any pawn through your own Bridge Override. A Character whose movement component is the kit's UUKRopeCharacterMovement (or a class derived from it) is slowed through the Character Movement adapter (module UKRopeCMCAdapter, on by default). Blueprint: reparent your character Blueprint to UKRope Character (AUKRopeCharacter — Class Settings › Parent Class); its movement component is then the kit's, and nothing else about the character changes. Do not add UKRope Character Movement as an extra component — a Character only ever moves with its own movement component. C++: derive your character from AUKRopeCharacter, or call ObjectInitializer.SetDefaultSubobjectClass<UUKRopeCharacterMovement>(ACharacter::CharacterMovementComponentName) in its constructor. A Character on the engine's plain Character Movement component is declined — UK-VAL-123 ("has no rope PhysCustom hook") — and carries at full speed. If your character must keep its own movement class, implement IUKRopeCMCHook on it and call UK::Rope::CMC::PhysCustomRope from PhysCustom (for the kit's custom modes 200 / 201), UK::Rope::CMC::PenalisedMaxSpeed from GetMaxSpeed and UK::Rope::CMC::PenalisedMaxAcceleration from GetMaxAcceleration — all three: in any build but Shipping the kit logs one Warning naming your class when a slowdown does not reach GetMaxSpeed or GetMaxAcceleration (also for a subclass of UUKRopeCharacterMovement that overrides them without calling Super). UK-VAL-120 means the adapter module is not loaded.
  • Custom movement modes 200 and 201 belong to the kit. On the Character Movement adapter a rope ride runs in the Custom movement mode with custom mode 200 (zipline) or 201 (swing). If your own custom movement mode uses either number, the kit takes it over — the character falls — and logs one Warning naming the mode; renumber your mode.
  • The slowdown never changes your Max Walk Speed. On a Character the kit scales what the movement component reads (GetMaxSpeed while walking, crouched or falling, and GetMaxAcceleration), not the Max Walk Speed, Max Walk Speed Crouched or Max Acceleration values. Your own changes while the object is held — a sprint, a gameplay attribute — combine with the slowdown (a sprint to 700 while carrying a Heavy object walks at 385) and are exactly what is in force after the release. Flying, swimming and the kit's own rope modes keep their top speed (acceleration is still reduced); a zipline ride keeps its speed while carrying, and an object dropped or thrown while riding leaves with the ride's speed.
  • What the slowdown does not cover. On a Character the slowdown scales the movement component's speed limits, so movement that does not go through them is not slowed: root motion locomotion (animation root motion, or a root motion source that overrides velocity) moves at the animation's speed, and with analog input a Min Analog Walk Speed above the slowed walk speed is the speed the character walks at. If you use either, scale it yourself while GetHeldObject() is set.
  • Character corrections at a grab or a release. The server applies the slowdown when it accepts the grab; the holder's machine applies it when that news arrives — about one network round trip apart (the same at a release). With the default bridge the holder's machine moves its own pawn, so nothing is corrected. With server-checked character movement (the Character Movement adapter) a player who is walking through that moment gets a few position corrections (measured without packet loss: about 1 at a grab or a release on a local network, about 3 at 150 ms ping — up to 6 in our tests over 17 network draws, default replication and Iris, dedicated and listen servers; a lossy connection can add a few more), a player standing still none, and almost never while the object is held (corrections in 1 of the 68 carry runs of our network sweep, none in the others).
  • Mass. With Use Mass on, the slowdown also depends on the object's mass. Set Mass Override Kg (MassOverrideKg) on the carry preset to the mass you want it to use. Left at 0, the kit uses the mass the object's class or Blueprint authors — never a mass you change at run time (a run-time mass change on the server does not reach the players' machines, so the server and the holder would disagree), and never a Mass (kg) override you set on one placed instance in a level (the kit reads the class's value; set Mass Override Kg on a preset for that instance instead). The value can also differ from the mass the editor shows: for a skeletal mesh root only its first physics body counts, on Unreal Engine 5.8 all of the body's shapes count (the editor counts only the mass-relevant ones), and a physical material assigned through the mesh's material is not used.
  • The slowdown ends with every way a hold ends: a drop or throw, the object destroyed or its carry component removed, the holder's carry component removed, the holder losing the object to a disconnect or a pawn change, and a drop + grab by another player in the same server frame. When your server code swaps the held object for another in one frame (ServerDrop, then ServerGrab), the holder keeps the new object's slowdown whatever order the two updates arrive in.
  • No movement bridge. A pawn the kit cannot bridge (no movement component it supports and no Bridge Override) carries without a slowdown; the first time a slowdown is owed the carrier logs one Warning (carrier '<pawn>': no movement bridge — the carry weight penalty … is not applied).

Network cost of carrying

A held object sends nothing while it is held: it is an attachment, not a replicated physics body, so eight players each holding a crate cost 0 bytes per second for the crates (measured over 10 s on every connection of an 8-player dedicated session, default replication and Iris). Grabbing costs one update on the object of about 62 bytes with default replication (about 44 bytes under Iris), whatever the hand component is called — the kit's target for a grab is 96 bytes. The first grab with a given player's hand on a given client also introduces that hand component to the client, once: a separate, one-time cost that carries the component's name, about one byte per character. Measured on an 8-player dedicated server: about 26 bytes for a hand component named Grip (4 characters) and about 36 bytes for an ACharacter's mesh (CharacterMesh0, 14 characters), the usual home of the Grip Socket — so that first grab arrives as one update of 88–89 or 98–99 bytes. The grab target counts the grab, not this one-time introduction (under Iris the name is a short token and the first grab stays about 44 bytes). Every later grab with that hand on that client costs the 62 bytes. Dropping costs about 32 bytes (about 45 bytes under Iris, where the measurement includes the falling object's first movement update), after which the falling object replicates its movement like any physics actor until it comes to rest.

Read the socket a held object hangs from with UUKCarryableComponent::GetGripSocket() — in Blueprint the pure node Get Grip Socket (category UK Rope | Carry): the socket the held object is attached to, or None when the object is not held (also None when the holder had no component with the preset's Grip Socket and the object was attached to the pawn's root). The kit does not send the socket name itself — the engine's attachment replication carries it. On a client it is also None for the moment between a hand-over's new holder arriving and that holder's attachment arriving — it never names the previous holder's socket.

Players who join while an object is held

A player who joins while someone holds an object sees it held from the first frame both the object and its holder exist on that machine: attached to the holder's hand, never falling. The join carries only the object's normal replicated state — the kit sends nothing of its own: the engine's own attachment replication is the join snapshot. This holds also when the object reaches the joining player before its holder does: the object waits without falling and is attached in the frame its holder arrives (measured: one frame after the object). A rope that was cut before the join arrives cut (IsCut() true). Measured with separate game processes on 5.6, 5.7 and 5.8 with default replication, and with Iris on 5.8 (the case where the object arrives before its holder was measured with default replication only).

Character Movement adapter

Module UKRopeCMCAdapter (Runtime, loaded by default) makes a Character ride ziplines and carry with a slowdown under the engine's own client prediction and server corrections. Use one of:

  • Blueprint: reparent the character Blueprint to UKRope Character (AUKRopeCharacter).
  • C++: derive from AUKRopeCharacter, or give your character the movement component class UUKRopeCharacterMovement.
  • Your own movement component class: implement IUKRopeCMCHook and call the three helpers in UK::Rope::CMC (see Carry slowdown and object weight), and forward OnClientCorrectionReceived to UK::Rope::CMC::NoteClientCorrection.

The adapter registers the movement bridge kind CMC. Read GetBridgeKind() and GetBridgeStats() on the interactor to see which bridge a pawn got; GetBridgeStats().CorrectionsSinceMount counts the engine's corrections on the owning client.

Ziplines on a Character

A Character whose movement component is the kit's UUKRopeCharacterMovement (Blueprint: reparent the character to UKRope Character; C++: derive from AUKRopeCharacter or name the component class — see Carry slowdown and object weight) rides a zipline in its movement component's Custom movement mode, custom mode 200. The server simulates the ride for every move the player sends, the player's machine predicts it with the same step, and the engine's own position corrections keep the two together — nothing to set up beyond the adapter.

  • What other players see. The rider's Movement Mode is Custom with Custom Movement Mode 200 on every machine for the whole ride, so an animation Blueprint can switch to a zipline pose on it; between network updates other players' copies keep moving along the ride.
  • Corrections at the mount and at the dismount. The ride starts on the server first and on the player's machine one network trip later (the same at the end), and the engine corrects the player for that moment: about 1 correction at the mount on a local network, about 3–4 at 150 ms ping; the same at the dismount. In our tests at 150 ms ping (17 network draws per case, default replication and Iris) that was up to 8 without packet loss on dedicated servers, and up to 6 in the cases also run on listen servers. With packet loss and the default rope update rate (5 Hz — a lost update of the rope's ride state is re-sent at the rope's next update, up to 200 ms later) our tests measured up to 6 on dedicated servers; the model bound, the engine's correction rate over that delay, is 12. During the ride itself there are none on a steady connection. On a connection whose delay varies from packet to packet, the engine's corrections can repeat for up to about half a second after the mount, the dismount or anywhere along the ride: when a correction for an older move and the confirmation of a newer move arrive in the same network update, the engine replays the player's moves from the corrected position without the moves it has just confirmed, so the player's machine ends a couple of frames of travel behind the server and is corrected again until its newer moves reach the server. This is the engine's own Character Movement behaviour, not the kit's; the server's position is always the one kept.
  • Leaving the ride. At the end (or a dismount for any reason) the character leaves Falling with the ride's velocity, on the server and on the player's machine. If your own code changes the character's movement mode during a ride, the kit takes the ride's mode back on the next frame; if the mode at the dismount is no longer the kit's (for example the server's correction already put the player's machine into Falling), the kit leaves that mode and velocity alone.
  • If the server never corrects the player. While the player's machine waits for the ride to start (or after its bridge was replaced mid-ride), it keeps the character moving in mode 200 and relies on the server's corrections to end that; if you turn the server's movement corrections off (bIgnoreClientMovementErrorChecksAndCorrection, or bClientIgnoreMovementCorrections on 5.8), the player's machine falls after Project Settings → UK Rope → Interactor → Ack Timeout Seconds (default 2 s) without a ride or a correction, and logs one LogUKRopeCMC warning naming the component. A movement component of your own that implements the rope hook should also forward OnClientCorrectionReceived to UK::Rope::CMC::NoteClientCorrection (as UUKRopeCharacterMovement does), or that wait counts from the last ride step only.
  • A new controller mid-ride. Possessing a riding character ends the ride on the server (OwnerLost, in the possession's frame); the new controller's machine is corrected to the server's position within a few network trips (a non-Character pawn keeps whatever position its own machine reached).
  • A character that never moves on the line. If your movement component's custom physics does not hand modes 200 / 201 to the kit (a PhysCustom override that never calls Super or UK::Rope::CMC::PhysCustomRope), the ride makes no progress and the rider is dismounted Stuck after Stuck Seconds, leaving with the ride's commanded velocity.
  • Carrying while riding (Allow Mount While Holding): a drop or a throw during the ride releases the object at the ride's speed; the carry slowdown never slows the ride.
  • Bridge Override. Setting a character's Bridge Override to the Character Movement bridge when its movement component does not carry the rope hook is refused with UK-VAL-124 (the ride would never move); the character then gets no bridge (UK-VAL-123 names its movement component).

Movement bridge

The kit never moves a pawn directly. It asks the pawn's movement bridge (IUKMovementBridge) to apply a ride or a carry slowdown, on the server and on the owning player's machine. The interactor picks the bridge once per pawn, in this order:

  1. the interactor's BridgeOverride (a class implementing IUKMovementBridge; refused with UK-VAL-124 when it cannot drive the pawn);
  2. a registered adapter that accepts the pawn (the Character Movement adapter accepts a Character whose movement component carries the rope hook, and declines any other Character with UK-VAL-123);
  3. the default bridge (UUKDefaultMovementBridge) for a pawn with a UPawnMovementComponent that is not a Character.

A pawn left with no bridge still mounts and carries but is never moved or slowed (UK-VAL-121, or UK-VAL-120 for a Character when the adapter module is not loaded; a Mover pawn gets UK-VAL-122). Turn Project Settings › UK Rope › Bridge › Auto Detect Bridge off to require a BridgeOverride on every pawn. OnBridgeInvalidated(OldKind, NewKind) fires when the selection runs again (for example after the movement component is replaced); GetMovementBridge() returns the bound instance.

The default bridge moves the pawn's updated component with a sweep and stops at the first blocking hit; it does not slide around obstacles.

Replication rules for your code

Rope shape on clients

Server and client must run the same plugin version

Run the same version of the plugin on the server and on every client. The rope's correction stream and its join snapshot carry fields whose layout can change between versions; a client built with another version rejects or misreads them.

More rules - what is server-authoritative, what is predicted, what each feature costs on the wire, and what differs under Iris - are in network-model.md.

Project Settings

All tunables live in Project Settings › Plugins › UK Rope (UUKRopeSettings, saved to your project's DefaultGame.ini). Each field's tooltip states its unit and safe range.

GroupFields
SolverSolver (Substeps, Iterations, Damping, FixedStepSeconds, MaxStepsPerFrame), ServerMaxStepsPerFrame
CollisionCacheRefreshFrames
ReplicationCorrectionRate, KeyParticles, CorrectionSmoothSteps, SnapshotRefreshSeconds, MaxRopeLengthCm, CorrectionOverheadFactor, NetCullDistance, OrphanLingerSeconds, PendingAnchorHoldSeconds, AnchorSmoothingSeconds, AnchorMaxExtrapolationSeconds, AnchorSnapDistanceCm, AnchorVelocityWindowSeconds, AnchorStopHorizonIntervals
InteractorRequestsPerSecond, RequestBurst, ServerThrottleSlack, ReachToleranceCm, ReachToleranceFraction, AckTimeoutSeconds, LineOfSightChannel
BridgebAutoDetectBridge
CarryGripClampHz, GripClampDeadbandCm, ThrowSettleSeconds, FreeSettleSeconds, CosmeticLagCm
PresetsLevelToleranceCm, StuckSeconds, MaxZiplineSlack, HangConvergeRate, MaxHangConvergeCmS
VisualbSpawnVisuals, VisualComponentClass, SegmentMesh, Material, SegmentMeshLengthCm, SegmentMeshRadiusCm, VisualRadiusScale, Lod1DistanceCm, Lod2DistanceCm, LodHysteresis, CullDistanceCm, UpdateEpsilonCm, NotRenderedGraceSeconds, CutChildWaitSeconds, MinSegmentCm, bWeldEndsToAnchors, bCastShadow, ZiplineHandleMesh
OverlayOverlayRefreshHz, RejectionLingerSeconds, RejectionHistory, FocusLingerSeconds, OverlayMaxLines, OverlayMaxLineChars, OverlayCorrectionLineMinCm, OverlayBudgetGraceFrames

Fields the kit reserves for a later version (ReelMaxHz, ReelStaleSeconds) have no effect in this version.

Rope visual

On every machine that draws - clients, a listen host and a standalone game - the kit attaches one rope visual to each rope at runtime. UUKRopeVisualSubsystem (a world subsystem in the client-only UKRopeClient module) adds a UUKRopeSplineVisualComponent to the rope's owner when the rope starts and destroys it when the rope goes away; GetVisualFor returns a rope's visual. The visual is not replicated and no asset of yours references the module, so a dedicated server never loads it. A rope placed in a level has no visual in the editor; it gets one when play starts.

  • Mesh and material. The visual bends a chain of spline meshes along the rope's render points (smoothed between solver steps, with each bound end drawn at its anchor's attach point). It uses Segment Mesh and Material from Project Settings › Plugins › UK Rope › Visual: a tube modelled along +X, whose authored length and radius you enter in SegmentMeshLengthCm and SegmentMeshRadiusCm; VisualRadiusScale makes it thicker or thinner. While Segment Mesh is empty a rope draws nothing and the client logs UK-VAL-132 once.
  • Level of detail and culling. Farther ropes use fewer segments (Lod1DistanceCm, Lod2DistanceCm), a rope beyond CullDistanceCm is not drawn, and a rope at rest is not re-pushed to the renderer.
  • Collision. The visual's meshes have no collision (NoCollision), and the rope's shape can differ slightly from client to client (see Rope shape on clients), so resolve hits, grabs and attach points on the server.
  • Cut ropes. When a rope is cut, the consumed segment disappears in the frame of the cut; each side of the parent hides as its new piece appears, and the pieces get their own visuals. If a piece never reaches this machine, the parent hides after CutChildWaitSeconds. A player who joins after a cut never sees the consumed segment.
  • Replacing the visual. In order of effort: change Segment Mesh and Material; set Visual Component Class to a USceneComponent class of your own that implements IUKRopeVisual (C++ in a client or game module, or Blueprint - a class that cannot be used falls back to the kit's visual and logs UK-VAL-130); turn bSpawnKitVisual off on one rope and draw it yourself from GetRenderPoints / FillRenderPoints; or turn Spawn Visuals off to attach no visual anywhere.
  • Orphaned ropes. A rope that loses every anchor on an owner other than the kit's UK Rope Actor stops simulating, and its visual keeps its last shape; call SetVisualHidden on the visual to hide it.

Network debug overlay

The network debug overlay draws text panels on the game viewport of any build except Shipping (the editor included): the local pawn (its requests, the carry, the movement bridge, a ride), the focused rope or object (the held object, the ridden rope, or the target of the last request), and on a listen host a table of the connected clients. A rejected request appears in the frame its reply arrives, with its serial, verb and reason, and fades out.

  • Turning it on. Set the console variable UK.Rope.Overlay to 1 for the panels or 2 for everything (per-connection rows, timing rows, and for each rope whose last correction moved it noticeably a line from each key particle to the server's corrected position); 0, the default, turns it off and leaves nothing registered or allocated. From Blueprint, SetVerbosity and GetVerbosity on the local player's UUKRopeOverlaySubsystem (category UK Rope › Debug) write and read the same variable, and clamp values outside 0-2. At start-up, use -ExecCmds="UK.Rope.Overlay 1" or a UK.Rope.Overlay=1 line under [ConsoleVariables] in your project's DefaultEngine.ini. UK.Rope.Overlay.Dump prints every panel to the LogUKRopeClient log.
  • Where it runs. The overlay is part of the client-only UKRopeClient module, so a dedicated server never loads it and UK.Rope.Overlay does not exist there. In Shipping builds it is compiled out: SetVerbosity changes nothing and GetVerbosity returns 0. A -nullrhi process (an automated test run) draws nothing and logs UK-VAL-193 once; UK.Rope.Overlay.Dump still prints the panels.
  • Settings. Refresh rate, how long a rejection stays, the line and character limits and the correction-line threshold are in Project Settings › Plugins › UK Rope › Overlay.
  • Referencing the overlay from your assets. Reference UUKRopeOverlaySubsystem only from client-side classes (a widget, a local player subsystem), never from a pawn or game mode, because a cooked dedicated server does not contain the class and fails to load such an asset.

Reference index

Class / typeModuleKindSection
AUKRopeActorUKRopeActor (UK Rope Actor)Ropes
UUKRopeComponentUKRopeActor componentRopes, Ziplines
UUKRopePresetUKRopeData assetRope presets
FUKAnchorBinding, FUKRopeTopologyUKRopeStructRopes
FUKRiderStateUKRopeStructZiplines
UUKRopeInteractorComponentUKRopeActor component (on the pawn)Requests
FUKRopeRequestResultWire, EUKRopeRejectReason, EUKRopeVerb, EUKRopePredictionEndReasonUKRopeStruct / enumsRequests
EUKDismountReasonUKRopeEnumZiplines
UUKCarryComponentUKRopeActor component (on the pawn)Carrying objects
UUKCarryableComponentUKRopeActor component (on the object)Carrying objects
UUKCarryPresetUKRopeData assetCarrying objects
FUKCarryState, FUKCarryStats, EUKCarryPhase, EUKCarryReleaseReason, EUKCarryReachEndReason, EUKHeldCollisionProfile, EUKWeightClassUKRopeStructs / enumsCarrying objects
IUKMovementBridge, UUKDefaultMovementBridgeUKRopeInterface / classMovement bridge
AUKRopeCharacter, UUKRopeCharacterMovement, IUKRopeCMCHook, UUKCMCMovementBridgeUKRopeCMCAdapterCharacter / component / interface / bridgeCharacter Movement adapter
UUKRopeSettingsUKRopeDeveloper settingsProject Settings
UUKRopeVisualSubsystem, UUKRopeSplineVisualComponentUKRopeClientWorld subsystem / scene componentRope visual
IUKRopeVisualUKRopeInterface (your own visual class)Rope visual
UUKRopeOverlaySubsystemUKRopeClientLocal player subsystemNetwork debug overlay
LogUKRope, LogUKRopeCMC, LogUKRopeClientUKRope, UKRopeCMCAdapter, UKRopeClientLog categoriesnetwork-model.md

Every Blueprint node of the kit is in the category UK Rope (with sub-categories Interactor, Carry, Rider, Bridge, Presets, Replication).