| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
This provides you with an "out of the box" project template to get started with Netcode for GameObjects.
With unity there are two different scene loading "modes":
The "Bootstrap Usage Pattern" involves having one (1) scene, typically set to index 0 of the Build Settings-->Scene in Build list, that is the only scene loaded in single mode for the entire duration of your runtime instance. All other scenes are always loaded additively.
There are several additional features in this implementation that provides you with a "good starting point" without having to completely start from scratch. If you are looking for a project that you can clone/download, build, run, and be able to start a network session without having to build your own UI, handle starting up and shutting down the NetworkManager, and to have a more WYSIWYG way of loading scenes...then this might be exactly what you are looking for!
As time permits, I will be updating this project with additional documentation, improving the existing code base, and in the "near future" I will be adding additional commonly used/created generic netcode "aware" components to help accelerate you into the world of Netcode for GameObjects!
(please be patient)
:)

When you first build and run (or enter play mode) this project you will be presented with a simple UI that provides you with the option of starting a new (network) session or exiting (i.e. exit playmode or exit the application for builds).

When you select "New Session" it provides you with the option to start the new session as a server, host, or client.

If you select "Start Host" it will:
You will also notice two buttons that only appear on the host or server side:
Both of these buttons have a NetcodeButton component attached to the GameObject. The NetcodeButton is just an example component of how you can pretty much make "anything" netcode aware.
Additionally, if you look at the top right corner you will see an "X" button. When clicked, it will trigger a series of events that will "roll back" to the previous menu interface. If you are rolling back to a menu interface (scene) that does not require "server synchronization" (i.e. no network session) from an scene that does require "sever synchronization" (i.e. an established network session), then it will automatically handle the netcode shutdown sequence. If it is a host or a server, then it disconnects all clients and upon all cients being disconnected it will then shutdown its local NetworkManager and transition back to the "non-server synchronized" scene (typically a UI scene). Alternately, you will discover that if you progress forward (i.e. from the Session Menu into a network session) where you are progressing from a scene that does not require server synchronization to one that does, it will automatically handle starting the NetworkManager for you.
Part of this Bootstrap Pattern has a heavy focus on:


The BootStrap scene is fairly straight forward. It contains the NetworkManager and a "BootStrapSceneLoad" object that defines the resolution (or any other property specific to your project that you might add to it) as well as the first scene to be loaded additively. The default setting for the template is to load the "DefaultActiveScene" SceneEntry ScriptableObject.

With Unity there can only be one "currently active scene" at a time but you can still have "many scenes" loaded (additively). When a scene is the currently active scene this means that, by default, any time you instantiate a new GameObject it will be instantiated in the currently active scene. Once instantiated you can migrate a GameObject into any other scene that is loaded. So, when you think about the "currently active scene" you should always remember the default instantiation target scene is the currently active scene. The only caveat to this rule is if the GameObject is already defined within the a scene being loaded. Under this case the GameObject will default to the scene it was placed in via the Unity editor.
A "SceneEntry" is derived from ScriptableObject that provides you with the ability to build logical relationships between other SceneEntries, Buttons, and Scripts. SceneEntries have to be associated with a NetcodeSceneLoader component in order for them to function properly.
To better understand the relationship between SceneEntry components and a NetcodeSceneLoader component, the below screenshot shows you the DefaultActiveScene's contents:

If you look at the SceneLoader object inspector view above, you will see that within the SceneEntry list is an actual reference to the DefaultActiveScene's SceneEntry, and then there are 4 more SceneEntry references in that list. If you were to look at any one of the other 4 SceneEntry assets in the inspector view, you would see that they are all set to "Load (the) Scene When" the NetcodeSceneLoader.Start method is invoked. (this property name and associated enum types will most likely be changed when I come up with better names for them). Below is a screenshot of the MainMenu SceneEntry:

You might feel confused at this point, but the following "logical flow" might help clear things up:
At this point there is one more concept to understand about a SceneEntry, which we will look at the SessionMenu SceneEntry for this. The SessionMenu is the menu interface that provides you with the option to start a server, host, or client. When a scene is loaded additively, all of the GameObjects instantiated will typically be immediately "visible" unless you have some form of script to disable them during the Start method (or the like). With a SceneEntry you have an additional handy method you can invoke to "show or hide" all GameObjects instantiated when the scene is loaded (i.e. in-scene placed NetworkObjects). This is accomplished via the SceneEntry.EnableSceneObjects method.

Looking at the inspector view of the SessionMenu SceneEntry, we can see that the "On Loaded Trigger" UnityEvent has a single entry that will invoke the SceneEntry.EnableSceneObjects method and pass a "false" to that method (checkbox un-checked) which will disable all GameObjects instantiated when the SessionMenu is loaded.
The idea behind this is that we are "pre-loading" certain scenes that we know we will use at some point in the "near" future but we don't want anything within the loaded scenes to be visible or to consume any processing cycles until we are "ready". If you refer back to the MainMenu SceneEntry above, you will see that it has no On Loaded Trigger Events which means the main menu will be visible by default. Let's walk through the loading process once more with a little more detail:

Looking at the above screenshot of the MainMenu scene's New Session button, we can see the button's "On Click" actions list contains two "actions" that will invoke the:
And with that...we switched between "scenes" without having to load a scene when the button is clicked or unload a scene if we want to bring another "scene into view". This is one, of several, benefits that comes with using a Bootstrap usage pattern (and this project template). You can even "pre-design" your scene flows without having to have all content populated within the scenes, and as you add content to scenes it is relatively easy to determine "does this scene need to have a network session (i.e. be synchronized by the server) or not?" and it simplifies the loading and unloading of scenes to the point where you don't even have to write any code to do this!
Included in the project template, there are 3 types of buttons:
All of the buttons share a common useful feature that helps expedite creating a new button instance.

If you look in the prefab folder, you will see a GenericButton prefab. As a temporary example of how naming works and with the MainMenu scene open, drag and drop the GenericButton into the MainMenu scene and then place it under the MainMenuCanvas. Change its RectTransform 'X' and 'Y' properties to 0 and 90 like in the screenshot below:

Now, right click on the newly created GenericButton prefab instance and rename it to "Test Button" (include the space). Once you are done, focus in on the button and you will notice the button text has changed to the name of the button.

This is just a "mini-time saver" feature that allows you to skip the typical last step of having to then set the visual name of the button in the child Text object of the button. You can delete this new button if you want now.

Looking at the GenericButtonScript properties of the "ExitSample" button within the the MainMenu scene, we can see the two properties are checked:
Looking at the Button properties of the "New Session" button, you will notice the "Exit Application" property is unchecked (we don't want to do this when we click it), and then we just use the button component's OnClick to handle disabling the MainMenu associated GameObjects and enabling the SessionMode associated GameObjects.
Not only does this button start the NetworkManager instance in a specific mode (server, host, or client), it also provides an example of how to create a "conditional" button that will perform a different set of sript logic based on the settings of the component's properties. Open the SessionMenu scene and select the "Start Host" button to view the SessionModeButton properities in the inspector view:

Open the SessionModeButton in your preferred IDE or refer to the below script:
public class SessionModeButton : GenericButtonScript
{
public enum SessionModes
{
Client,
Host,
Server,
None
}
public delegate bool StartSessionModeDelegateHandler();
[Tooltip("Will start a specific session mode or if set to None will act like a normal button.")]
public SessionModes SessionMode;
public UnityEvent<SessionModes> OnSessionModeAction;
private Dictionary<SessionModes, StartSessionModeDelegateHandler> SessionModeActions;
protected override void OnButtonClicked()
{
if (CanInvokeSessioinModeAction())
{
if (SessionModeActions == null)
{
InitializeSessionModeActions();
}
InvokeSessionModeAction();
}
}
protected bool CanInvokeSessioinModeAction()
{
return NetworkManager.Singleton && (SessionMode == SessionModes.None ||
(!NetworkManager.Singleton.IsListening && SessionMode != SessionModes.None));
}
private void InvokeSessionModeAction()
{
if (NetworkManager.Singleton != null)
{
if (SessionMode != SessionModes.None && !NetworkManager.Singleton.IsListening)
{
SessionModeActions[SessionMode].Invoke();
NetworkManager.Singleton.SceneManager.SetClientSynchronizationMode(UnityEngine.SceneManagement.LoadSceneMode.Additive);
NetworkManager.Singleton.SceneManager.DisableValidationWarnings(true);
}
OnSessionModeAction.Invoke(SessionMode);
}
}
private void InitializeSessionModeActions()
{
SessionModeActions = new Dictionary<SessionModes, StartSessionModeDelegateHandler>();
SessionModeActions.Add(SessionModes.Client, NetworkManager.Singleton.StartClient);
SessionModeActions.Add(SessionModes.Host, NetworkManager.Singleton.StartHost);
SessionModeActions.Add(SessionModes.Server, NetworkManager.Singleton.StartServer);
}The InitializeSessiionModeActions ceates a simple Dictionary that is keyed off of the different SessionModeButton.SessionModes types and each type's Value is set to a StartSessionModeDelegateHandler. Of course, you can use this basic approach to create "multi-conditional" actions where you might require more than one configured property. Using this approach can help greatly decrease content creation time as your project evovles.
This button follows the same "conditional button" pattern that the SessionModeButton does, with the exception that it is "netcode aware".
Netcode Aware: A component that is aware of an existing Netcode for GameObjects network session.
Opening the HeadsUpDisplay scene and selecting the "Hide Client HUD", you will see the following properties in the inspector view:

The condition for this button is whether you are:
These three types of buttons provide fundamental building block functionality that can be expanded upon to create almost any kind of conditional button that you might require when working on your project.
Note: You can always use the Button component's OnClick to perform any actions that will always be invoked under all conditions.
(More Components and Content To Come As Time Permits)
| Back | FazBrowse Home | New Git URL |