o3de / sig-network

9 stars 8 forks source link

RFC: Scriptable Network Input #6

Closed AMZN-Gene closed 2 years ago

AMZN-Gene commented 2 years ago

Summary:

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).

What is the relevance of this feature?

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.

Feature design description:

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:

image

The second method will be an event called ProcessInput:

Technical design description:

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.

What are the advantages of the feature?

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.

What are the disadvantages of the feature?

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.

How will this be implemented or integrated into the O3DE environment?

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.

Are there any alternatives to this feature?

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

How will users learn this feature?

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.

Are there any open questions?

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.

lsemp3d commented 2 years ago

Since this RFC was written in service of a specific use-case (scripting input), I find it doesn't go into important details regarding what the scripting API will look like for all future networking features exposed to script.

Perhaps it would be worthwhile to split this RFC into two, the first one being the core changes that explain how the networking framework will use the existing engine and scripting paradigms. The second RFC will cover how the input system will be the first system built upon the network scripting framework established in the first RFC.

AMZN-Gene commented 2 years ago

Nice callout! I'll start a task for a separate RFC for how scripting and networking play together as a whole, but I hope we wouldn't need another RFC before completing this one. I think of this as a smaller feature that developers would likely implement themselves on a per-component basis, but we'll do it automatically using code-gen for them for now.

For instance, developers today will start by writing their own multiplayer components in C++, but suppose they say, "Hmm, I think it would be nice to script what happens after the player presses this specific input" Developers today would write their own multiplayer component reflect method (just like any normal component) in order to expose some of their component's properties to script. This RFC is to help devs write that Reflect() method they would have written themselves, except we do it automatically via code-gen.

It's a nice bang-for-buck since it unlocks the ability for users to do things like quickly implement GameJam-y multiplayer scripts or add a level to AutomatedTesting with a script to test what happens when a player using simple input interacts with their latest networking feature. Example, a script that auto-pilots a player into a bunch of networked rigid bodies in order to make sure the collision events happen over the network.

We should have another discussion of 100% Mutliplayer Scripting where the networking-scripting framework becomes super important... that will definitely need its own RFC.

lmbr-pip commented 2 years ago

Moving to RFC archive in https://github.com/o3de/sig-network/pull/14

lmbr-pip commented 2 years ago

RFC accepted by SIG and archived in https://github.com/o3de/sig-network/tree/main/rfcs