GUIDESOBJECT FOR MULTIPLAYER
Object for multiplayer
This guide makes the switch from the guides work in a game with more than one player. BP_MySwitch replicates, so every player’s machine gets its state. BP_MySoundAction plays its sound on every machine, and the server checks the Conditions that only it can check. You do it in seven steps, in Blueprint only.
You need
Section titled “You need”- You have followed Quick start, so BP_MySwitch exists and works in single-player.
- You have followed Your own Action, so BP_MySoundAction exists and is set on the switch.
- You have followed Your own Condition, so BP_MyDistanceCondition exists and is in the switch’s Usable Conditions.
Then follow these steps in order.
-
Make the switch replicate. Open BP_MySwitch, click Class Defaults and, under Replication, turn on Replicates. The plugin’s object component replicates only when its actor replicates, and a new Actor Blueprint has this off, so without it the other players never see the new state.
-
Check the project network settings. Open Project Settings › Plugins › Character Interaction System. These are the settings of
UCISNetworkSettings, saved inDefaultGame.ini. The defaults suit most projects. The tolerances let the server accept a use from a client whose character lags a little behind the server’s copy of it. The server checks only the use requests of remote clients: a standalone game, a listen host’s own character and the characters the server runs are never checked.Server Validation Server Validation Distance Tolerance Absolute 100.0 Distance Tolerance Scale 0.5 Angle Tolerance Degrees 30.0 Hold Time Tolerance 0.3 The Server Validation settings of the Character Interaction System project settings, with their default values. -
Choose where the Action runs. Open BP_MySoundAction, click Class Defaults and find Net Execution Policy under Execution. It sets the machines the Action runs on during a use:
- All Machines: on every machine, so the sound and the animation are seen by everyone. This is the default.
- Local Predicted: on the player’s machine and on the server. Whichever of the two completes the step first leads it, and the other follows.
- Server Only: on the server only. Use it for what must happen once, such as giving an item or adding to a score.
- Local Only: on the player’s machine only. Use it for what only that player should see, such as an interface.
All Machines is right for the click of BP_MySoundAction. The policy decides where the Action’s own graph runs. A data object exists only on the machine of the player who controls the character, so its events, such as a hint, run for that player alone.
Execution Instancing Policy Net Execution Policy The Execution settings of an Action. Net Execution Policy is the setting in this step. -
Choose what the server checks. Open BP_MyDistanceCondition, click Class Defaults and set Server Validation, in the Settings category, to one of these values:
- Default: for a Blueprint Condition the server checks the Condition, and rejects a use that fails it. A Condition written in C++ is not checked under Default. BP_MyDistanceCondition is a Blueprint, so Default already checks its distance, which the server works out from the positions of the two actors.
- Validate: the server checks the Condition whatever its class. Use it for a C++ Condition that tests what the server knows, such as positions.
- Do Not Validate: only the player’s machine checks the Condition. Use it for what only that machine knows, such as what is on the player’s screen. A modified client can then skip the check, so use it only where the check is not a rule that protects the game.
-
Change the state on the server. If your own code changes the state of BP_MySwitch, for example on a timer, call Set Object State on the server only, behind an Is Server branch, as step 4 of Lever and locked door does.
UCISInteractionObjectComponent::SetObjectStatechanges the state only on the machine it runs on. On a client, the change stays local, and the Output Log warns once:called on a client; the change is local only. Call it on the server. -
Set ownership and dormancy. Select CISInteractionObject and, under Interaction Settings, check two settings:
- Transfer Ownership During Use, on, which is the default. During a use the user’s controller owns the object’s actor, and the server gives the previous owner back when the use ends.
- Manage Owner Dormancy, off, which is the default. The object’s actor rests dormant while nobody uses it. The server wakes it for a use and lets it rest again 1 second after the use. The object state, the usable flag and the in-use flag still reach every client. Turn this on only for an object whose Blueprint or C++ code replicates no variables, multicasts or other network functions of its own, whose Blueprints do not write Usable directly, and whose dormancy no other code sets. Otherwise keep it off. BP_MySwitch keeps the default, off. The demo objects turn it on.
-
Test with two players. In the Play options, set Number of Players to 2 and Net Mode to Play As Client, then click Play. Type
log CISLog Login the console, so that the plugin’s refusal lines appear in the Output Log. Press E at the switch in the first player’s window: both players hear the click, and the state of the switch changes on both players’ machines.Then see a refused use. Create BP_MyServerRefusal as a Blueprint Class with
UCISInteractionObjectConditionas its parent, as in step 1 of Your own Condition. Override Check Condition and build the graph below: from the entry’s InteractionObjectComponent pin add Get Owner, add Has Authority on its return value, add NOT Boolean on that, and wire the result to the return node’s Return Value. Wire the entry’s execution pin to the return node. Leave Server Validation at Default. Add BP_MyServerRefusal to Usable Conditions of BP_MySwitch, and press E at the switch in the first player’s window. That player’s machine passes the Condition, because it has no authority over the switch. The server fails the Condition and refuses the use, and the Output Log showsECISUseRejectReason::ConditionFailed. Remove the Condition from the switch when the test is done. The test works only with Net Mode set to Play As Client: a listen-server host has authority over the switch and never passes the Condition.Check ConditionInteraction CharacterCharacter Interaction ComponentInteraction Object ComponentInteraction Object SideGet OwnerTarget is Actor ComponentTargetReturn ValueHas AuthorityTarget is ActorTargetReturn ValueNOT BooleanAReturn ValueBLUEPRINTReturn NodeReturn ValueThe Check Condition graph of BP_MyServerRefusal. It passes on a machine without authority over the object and fails on the server.
Key settings
Section titled “Key settings”The table shows the settings of UCISNetworkSettings from step 2, with their default values.
| Setting | Default | What it does |
|---|---|---|
| Server Validation | On | Whether the server checks every use request of a remote client and rejects a request that fails. Off: the server confirms every request. |
| Distance Tolerance Absolute | 100 | Centimetres the character may stand beyond the object’s Interaction Distance. |
| Distance Tolerance Scale | 0.5 | Fraction of the object’s Interaction Distance the character may stand beyond it. 0.5 means half the distance more. |
| Angle Tolerance Degrees | 30 | Degrees added to the half angle of the side the character uses, and to the half facing angle of the character. |
| Hold Time Tolerance | 0.3 | Seconds by which a hold measured on the server may be shorter than the object’s use time. |
Check that it works
Section titled “Check that it works”- With the two players of step 7, both players hear the click, and the state of the switch changes on both players’ machines when one of them presses E at it.
- With BP_MyServerRefusal in place, a press of E by the first player is refused: the switch stays as it was on every machine, and the Output Log shows the server’s line,
ServerRequestUse from <character>: the use of <object> is rejected (ECISUseRejectReason::ConditionFailed), key <key>. - A use that the player’s machine blocks itself, because the character is too far from the switch or faces it at the wrong angle, writes nothing. The server log lines appear only when the server refuses a request that the player’s machine allowed.
If something is off
Section titled “If something is off”-
The other players cannot see or use the switch, and its state reads empty on their machines: Replicates is off on BP_MySwitch. Turn it on under Class Defaults, in Replication (step 1).
-
Only one player hears the click: Net Execution Policy of BP_MySoundAction is not All Machines (step 3).
-
The Output Log warns that a change is local only: your code calls Set Object State on a client. Put the call behind an Is Server branch (step 5).
-
No
CISLoglines appear: the category shows only warnings by default. Typelog CISLog Login the console and play again. -
A refused use usually writes a line on the server. No server line appears when the server cannot find the object at all, for example after it was destroyed, and when the server runs its own use of that character. Then the player may see the state snap back with no server line. The player’s machine writes a second line only while its use still waits for the server’s answer. In the editor, with every player in one process, both appear in the same Output Log.
ServerRequestUse from <character>: the use of <object> is rejected (ECISUseRejectReason::<reason>), key <key>.ClientRejectUse on <character>: the server rejected use <key> (ECISUseRejectReason::<reason>).This line appears only while the player’s use still waits for the server’s answer. An Action that finishes at once, such as BP_MySoundAction, has already ended by then: the player’s machine writes no line at the Log level and puts the switch back to the server’s state.
The reason is a value of
ECISUseRejectReason, and the table below says what to check for each one.
| Reason | What to check |
|---|---|
ObjectInvalid | The server cannot find the object. The object or its actor was destroyed or removed on the server. |
NotUsable | The object cannot be used now. Check the Usable flag of the object: a Blueprint, or a call of Set Usable, turned it off. |
Occupied | Another character is using the object. Check that every Action finishes, because a use lasts until Finish Action runs. |
NoActionForState | No action of the side matches the object’s state. Check the Required State Tag of each action, and the Initial Object State of the object. |
OutOfRange | The character stands farther from the object than its Interaction Distance, plus the tolerances of step 2. Check Interaction Distance, and the tolerances in the Key settings. |
BadAngle | The character does not face the object within half of its Interaction Angle, or the object’s override of it, plus Angle Tolerance Degrees. Check those settings. |
BadSide | The character does not stand within the requested side, or the side does not exist on the server. Check Interaction Angle Min, Interaction Angle Max and Angle Tolerance Degrees. Sides are not replicated, so every machine must build them from the same class defaults and Blueprint. |
ConditionFailed | A Condition checked on the server failed. Check the Visible Conditions and the Usable Conditions of the object, and the Server Validation of each Condition (step 4). A distance is measured from the server’s copy of the character, so give the Condition a small margin, as in Your own Condition. |
HoldTooShort | The button was released before the object’s use time. Check the use time: Override Object Use Time of the object, or the character’s Time to Use Object. The server accepts a shorter hold by Hold Time Tolerance. |
