- URP Project Creation: Start by creating a project using the URP template, ensuring cross-platform compatibility.
- Global Volume: Add a Global Volume with a Volume component for post-processing and global visual effects.
- Graphics Quality & Cleanup: Optimize settings by focusing on URP’s high fidelity mode, removing unnecessary quality levels, and cleaning up default URP settings.
- Pause on Error: Enable this option to catch errors during game testing.
- Aspect Ratio: Set the resolution to Full HD (1920x1080).
- VSync: Turn it on to optimize GPU performance during development.
- Create a
.editorconfig
file for consistent C# formatting. Example:CSharp_new_line_before_open_brace = none
- Navigate using key combinations such as
Left Alt + Left Mouse Button
for rotating around objects andRight Mouse Button + WASD
for moving around.
Ensure that post-processing is viewed and adjusted properly in Game View and is enabled in both the Camera and URP Renderer settings.
- Tonemapping: Set to Neutral for a balanced scene.
- Bloom: Add for glow effects, with adjustments to Threshold and Intensity.
- Vignette: Adds subtle darkness at the edges of the screen.
- Anti-Aliasing: High-end smoothing of edges.
- Ambient Occlusion: Improves shadows where objects meet.
Shader Graph allows visual creation of shaders. For example, you can create custom effects like dissolving or outline transitions.
- Create a New Shader:
- Right-click in the project -> Shader Graph -> URP Lit Shader.
- Add a Texture:
- Use
Simple Texture2D
nodes to control shader inputs and outputs, including aBaseMap
for your texture.
- Use
- Animate with Time:
- Use a
Time
node to add dynamic effects, like scrolling textures, by multiplying it with aVector2
parameter for speed.
- Use a
- Output:
- Connect nodes to the UV input to animate the shader effect.
To move or rotate an object based on its facing direction:
// Move in the direction the object is facing
transform.forward = <vector>;
// Rotate smoothly using interpolation
transform.forward = Vector3.Slerp(transform.forward, moveDirection, Time.deltaTime * rotationSpeed);
- Add an Animator component to an object.
- Create an Animator Controller to manage different animations.
- Record and loop animations.
- Transitions: Add conditions to transition between states, with or without exit time.
Cinemachine provides dynamic camera systems in Unity.
- Install it via the Package Manager.
- Add a Virtual Camera and adjust settings such as noise and follow/look at behavior for smooth movement.
Unity’s New Input System offers better control for input management.
- Install via the Package Manager.
- Set up Input Actions for capturing player movements.
- Retrieve values with
ReadValue<Vector2>
in scripts for handling input.
Learn key shortcuts like W
for moving objects, E
for rotating, and using Shift
while rotating to snap to 15-degree increments.
Singleton ensures a class only has one instance globally, often used for managers or game controllers.
-
Setup Singleton:
public static Player Instance { get; private set; } private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; DontDestroyOnLoad(gameObject); }
-
Access Singleton:
Player player = Player.Instance;
Events allow decoupled communication between objects, which enhances modularity.
-
Declare an Event:
public event EventHandler OnSelectedCounterChanged;
-
Trigger Event:
OnSelectedCounterChanged?.Invoke(this, EventArgs.Empty);
-
Subscribe to Event:
Player.Instance.OnSelectedCounterChanged += HandleSelectedCounterChanged;
-
Unsubscribe to prevent memory leaks when the object is destroyed:
Player.Instance.OnSelectedCounterChanged -= HandleSelectedCounterChanged;
- Open Unity and navigate to the Package Manager.
- In the top left corner, select Unity Registry to list all available packages.
- Scroll down to find the package titled Netcode for Game Objects.
Package: com.unity.netcode.gameobjects
Version: 1.2.0
Note: It is highly recommended to install version 1.2.0 for this course to avoid potential issues due to changes in newer versions.
If the latest version differs from 1.2.0, follow these steps to install the exact version manually:
- Click the Plus (+) icon in the top left of the Package Manager window.
- Select Add Package by Name.
- Enter the following details:
Name: com.unity.netcode.gameobjects
Version: 1.2.0
- Double-check for typos and click Add.
- Unity will install Netcode 1.2.0 along with the required dependency:
Dependency: ND Transport 1.3.1
- Once installed, confirm that Netcode for Game Objects version 1.2.0 is listed, along with ND Transport 1.3.1 as a dependency.
- Close the Package Manager.
Changes between versions may be minor (e.g., changes in the location of network prefabs), but it is important to follow this course with Netcode 1.2.0 to avoid confusion.
- Create a new EmptyObject and rename it
NetworkManager
. - Reset the transform of the object.
- Add a new component called
NetworkManager
(Unity's built-in component). - Select Unity Transport as the transport mechanism to allow the game to send packets.
- You will see the Unity Transport component added.
- No need to modify anything, but ensure the address in Unity Transport > Connect Data > Address is set to
127.0.0.1
.
- In
NetworkManager
, add the Player Prefab (the object to instantiate when a player connects). - Add a Network Object component to the Player Prefab.
- Modify the Player Script:
- Change
MonoBehaviour
toNetworkBehaviour
.
- Change
-
In the
NetworkManager
, you will see options:- Start Host (Server + Client)
- Start Server
- Start Client
-
Press Start Host to spawn the player.
- Instead of controlling the start host/client from the Unity Editor, create a UI with two buttons: Start Host and Start Client.
- Create a script to access these buttons and add listeners on click:
- Use
NetworkManager.Singleton.StartHost();
.
- Use
- Ensure the GameScene is at the top of the build order (we don't need
Main
as the first scene for a multiplayer game). - Go to Player Settings > Resolution:
- Set FullScreen Mode to Windowed.
- Enable Run in Background.
- Enable Resizable Window.
- Set the Company Name and Product Name in Player Settings.
To find logs for the game, navigate to:
C:\[User Profile]\AppData\LocalLow\[Company Name]\[App Name]
After building the game, open the log file to view the logs. Press F5
to refresh the logs in real-time.
While using log files is effective, the Quantom Console Asset can provide a better testing experience (paid asset).
Ensure only the owning player can move their character by adding IsOwner conditions in the player script:
if (!IsOwner) {
return;
}
To synchronize movement, add NetworkTransform to the player prefab and adjust the sync settings, like excluding Y-direction movement or scaling.
For client-side synchronization, implement a ClientNetworkTransform
as described in the Unity Multiplayer Documentation:
using Unity.Netcode.Components;
using UnityEngine;
namespace Unity.Multiplayer.Samples.Utilities.ClientAuthority
{
[DisallowMultipleComponent]
public class ClientNetworkTransform : NetworkTransform
{
protected override bool OnIsServerAuthoritative()
{
return false;
}
}
}
To have the server control movement, use a Server RPC:
[ServerRpc(RequireOwnership = false)]
- Add spawned objects to the Network Prefab List in the
NetworkManager
. - Use NetworkObjectReference for complex RPC parameters:
[ServerRpc(RequireOwnership = false)]
private void SetKitchenObjectParentServerRpc(NetworkObjectReference kitchenObjectParentNetworkObjectReference) {
SetKitchenObjectParentClientRpc(kitchenObjectParentNetworkObjectReference);
}
- Install the Lobby package from the Unity Registry.
- Use LobbyService for lobby operations and handle lobby heartbeat to keep it alive:
private void HandleHeartBeat() {
if (IsLobbyHost()) {
heartBeatTimer -= Time.deltaTime;
if (heartBeatTimer < 0f) {
heartBeatTimer = 15f;
LobbyService.Instance.SendHeartbeatPingAsync(joinedLobby.Id);
}
}
}
Fetch lobbies with:
QueryResponse queryResponse = await LobbyService.Instance.QueryLobbiesAsync(queryLobbiesOptions);
For lobby relay code:
joinedLobby.Data[KEY_RELAY_JOIN_CODE].Value;
Enable Relay in Unity Cloud for seamless connections without port forwarding:
Allocation allocation = await RelayService.Instance.CreateAllocationAsync(KitchenGameMultiplayer.MAX_PLAYERS_ALLOWED - 1);
NetworkManager.Singleton.GetComponent<UnityTransport>().SetRelayServerData(new RelayServerData(allocation, "dtls"));
Use Debug Simulator in Unity Transport to simulate latency, jitter, and packet drops. Use the Multiplayer Tools Package for network statistics and monitor them via Profiler.