A key feature built into Multiplayer Components is the concept of Network Input. Network Input helps digest player input (the human and therefore most unpredictable aspect of the network simulation), in order to keep the simulation on clients and servers in sync.
Currently, Network Input is only available to developers writing C++ components; this RFC proposes exposing Network Input to script (Lua and Script Canvas).
Scriptable Network Input will help save iteration time and allow developers who have limited experience with networking and C++ to build a multiplayer game.
Since scripting doesn't require C++ knowledge or time to recompile, adjustments to the multiplayer controllers can be iterated upon quickly. For example, when receiving keyboard WASD controller input, a designer might decide to add an acceleration curve so that tapping the keyboard moves the character less than it would from holding it down. These types of gameplay edits aren't an exact science and requires dozens of little modification in order to create "good feel". Without scripting support, a designer hoping to modify how keyboard input affects the character controller will need to (1) modify C++ game logic, (2) close down the Editor and Asset Processor, (3) recompile C++, (4) reopen the Editor, and finally (5) reopen and run the test level in order to see the results of their code. If each of these small modifications requires C++, then hours are lost over the course of game development due to recompiling and testing code.
If, alternatively, designers can make changes via script then the time and steps taken are reduced: (1) modify the game logic script, (2) rerun the level to test the change.
In addition to saving time, scripting is typically easier to learn than C++ and thus is easier for studios to find/maintain a scripting dev.
Multiplayer auto-components with NetworkInputs will have the option to enable or disable exposing any of their NetworkInputs to script via an "ExposeToScript" flag. If any NetworkInputs are enabled for scripting, the multiplayer auto-component should generate 2 new methods inside of behavior context.
The first method will be an event which returns a result called CreateInput:
The second method will be an event called ProcessInput:
Step 1: Update Auto-Component XML NetworkInputs to Include "ExposeToScript" Attribute
Step 2: Expose Auto-Component Class {{ ComponentName }}NetworkInput to Behavior Context
Step 3: Expose StickAxis and MouseAxis to Behavior Context
Step 4: Add CreateInput and ProcessInput Event to Multiplayer Auto Component BehaviorContext
After implementing all 4 steps, users will be able to create auto-components with network inputs that are exposed to Lua and Script Canvas and receive event callbacks during the game runtime when it's time to create and process input.
Using script instead of C++ for creating and processing network input will saves time since users don't need to recompile. Also, those less familiar with C++ can still enjoy the ease of sending/receiving user input across the network.
While creating network input is fairly straight forward, scripters who may not have experience with networking could accidently mess up the network simulation if they incorrectly process network input.
For example, if you're creating a first-person-shooter where animations need to stay in sync in order to properly detect where a bullet hit (body, arms, head, etc) then the scripter would need to know to how to update animation in a way that is network safe as opposed to using the existing actor events they've used in the past. At the time of writing this document, there isn't a generic networking solution for EMotion Fx, so scripters will need to know specifically what is and isn't safe to update.
There are no special steps to integrate this feature into your O3DE environment. As long as you have the MultiplayerGem enabled, you'll receive the ability to enable network input for scripting.
There aren't any alternative features, but there are some additional features which could make the user experience a lot better. Each of the following bonus features requires an RFC, and is a general Script Canvas feature which would be handled by sig-content. This could greatly improve the script canvas user experience in general.
Bonus Feature 1: Auto-Exploded Script Canvas Variables
Bonus Feature 2: New Script Canvas Event Result UI
The current Script Canvas node for returning a result is a bit clunky, requiring users to pass in the result on the left hand side of the node.
Instead it would make more sense to produce 2 nodes: the event node and a result node that is data connected (and can't be disconnected). The user would be expected to connect the execution slot at the end of the of the operation.
More notes regarding implementation:
Anyone familiar with Lua or Script Canvas could quickly pick up how to use network input for their multiplayer game.
Teaching Opportunity 1:
Fortunately, Script Canvas is quite nice for discovering new features. I often discover new features just by using the search feature in the Script Canvas node palette. Network input is no exception, by searching the multiplayer component the 2 new methods for CreateInput and ProcessInput will appear in the node palette. These nodes are fairly simple to grasp; CreateInput requires users to return inputs and ProcessInput provides input values for which designers can use to drive the simulation.
Teaching Opportunity 2:
A small video tutorial using Script Canvas to drive a simple network character around using WASD would also be a valuable learning tool.
Script Canvas Networking Context
When writing any multiplayer gameplay logic, whether using C++ or Script Canvas, developers need to be careful to keep the network simulation in sync. However, when it comes to Script Canvas there's an opportunity to limit what is exposed; it is possible to create a new scripting context for networking specifically where only certain methods are exposed to designers when writing networked scripts. Instead of adding a ScriptCanvas component, designers would add a NetworkScriptCanvas component in order to enable the network specific context.
This could help mitigate the potential harm done by bad design logic; however, it's a double edged sword that could severely nerf what's possible via script.
For example, a multiplayer character controller may want to use the Physics API to drive the player; they could use Physics::Character::AddVelocity and Physics::Character::ApplyRequestedVelocity to accurately move the player around based on deltaTime. By using a network context script we could hide the Physics API and instead limit Script Canvas access to the NetworkCharacterComponent (a component which was designed specifically for moving characters on the network). This topic would need further discussion about which Script Canvas nodes should and shouldn't be exposed to a network context.