subscribe for cute lil snakes - watch the next part here ua-cam.com/video/FjOZrSPL_-Y/v-deo.html Wishlist my new game BUMBI on Steam! store.steampowered.com/app/2862470/BUMBI/ small bug fix - in PlayerLength OnNetworkSpawn() after subscribing to the length changed event, put: // If there was another player already in the match, the beginning tails of them won't be updated. These lines check the length of the snake and spawn the tails of the other clients accordingly. if (IsOwner) return; for (int i = 0; i < length.Value - 1; ++i) InstantiateTail(); Also before spawning the Food object make sure to do if (!obj.IsSpawned) obj.Spawn(true); And when despawning you can just do if (NetworkObject.IsSpawned) NetworkObject.Despawn();, and not Destroy it.
You can add this at any time, it’s just so that when a new player joins it can spawn the tails of the other players if they had already grown in length. The section before 1:10:03
Could you pls leave here a document/text with the ObjectNetworkPool script? The original document was updated and is complete different of the one shown in the video, it does not even have an InitializePool function. That would be really helpful
@@mathinho_ns Here you go. Also before spawning object make sure to do if (!obj.IsSpawned) obj.Spawn(true); And when despawning you can just do if (NetworkObject.IsSpawned) NetworkObject.Despawn();, and not Destroy it. using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using Unity.Netcode; using UnityEngine; using UnityEngine.Assertions; /// /// Object Pool for networked objects, used for controlling how objects are spawned by Netcode. Netcode by default will allocate new memory when spawning new /// objects. With this Networked Pool, we're using custom spawning to reuse objects. /// Boss Room uses this for projectiles. In theory it should use this for imps too, but we wanted to show vanilla spawning vs pooled spawning. /// Hooks to NetworkManager's prefab handler to intercept object spawning and do custom actions /// public class NetworkObjectPool : NetworkBehaviour { private static NetworkObjectPool _instance; public static NetworkObjectPool Singleton { get { return _instance; } } [SerializeField] List PooledPrefabsList; HashSet prefabs = new HashSet(); private Dictionary pooledObjects = new Dictionary(); private Dictionary nonPooledObjects = new Dictionary(); private bool m_HasInitialized = false; public void Awake() { if (_instance != null && _instance != this) { Destroy(this.gameObject); } else { _instance = this; } } public override void OnNetworkSpawn() { InitializePool(); } public override void OnNetworkDespawn() { ClearPool(); } public void OnValidate() { for (var i = 0; i < PooledPrefabsList.Count; i++) { var prefab = PooledPrefabsList[i].Prefab; if (prefab != null) { Assert.IsNotNull(prefab.GetComponent(), $"{nameof(NetworkObjectPool)}: Pooled prefab \"{prefab.name}\" at index {i.ToString()} has no {nameof(NetworkObject)} component."); } } } /// /// Gets an instance of the given prefab from the pool. The prefab must be registered to the pool. /// /// /// public NetworkObject GetNetworkObject(GameObject prefab) { return GetNetworkObjectInternal(prefab, Vector3.zero, Quaternion.identity); } /// /// Gets an instance of the given prefab from the pool. The prefab must be registered to the pool. /// /// /// The position to spawn the object at. /// The rotation to spawn the object with. /// public NetworkObject GetNetworkObject(GameObject prefab, Vector3 position, Quaternion rotation) { return GetNetworkObjectInternal(prefab, position, rotation); } /// /// Return an object to the pool (reset objects before returning). /// public void ReturnNetworkObject(NetworkObject networkObject, GameObject prefab) { // Debug.Log("Returning Object"); var go = networkObject.gameObject; go.SetActive(false); pooledObjects[prefab].Enqueue(networkObject); nonPooledObjects[prefab]--; } /// /// Returns how many of the specified prefab have been instantiated but are not in the pool. /// public int GetCurrentPrefabCount(GameObject prefab) { return nonPooledObjects[prefab]; } /// /// Adds a prefab to the list of spawnable prefabs. /// /// The prefab to add. /// public void AddPrefab(GameObject prefab, int prewarmCount = 0) { var networkObject = prefab.GetComponent(); Assert.IsNotNull(networkObject, $"{nameof(prefab)} must have {nameof(networkObject)} component."); Assert.IsFalse(prefabs.Contains(prefab), $"Prefab {prefab.name} is already registered in the pool."); RegisterPrefabInternal(prefab, prewarmCount); } /// /// Builds up the cache for a prefab. /// private void RegisterPrefabInternal(GameObject prefab, int prewarmCount) { prefabs.Add(prefab); var prefabQueue = new Queue(); pooledObjects[prefab] = prefabQueue; for (int i = 0; i < prewarmCount; i++) { var go = CreateInstance(prefab); ReturnNetworkObject(go.GetComponent(), prefab); } // Register Netcode Spawn handlers NetworkManager.Singleton.PrefabHandler.AddHandler(prefab, new PooledPrefabInstanceHandler(prefab, this)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] private GameObject CreateInstance(GameObject prefab) { return Instantiate(prefab); } /// /// This matches the signature of /// /// /// /// /// private NetworkObject GetNetworkObjectInternal(GameObject prefab, Vector3 position, Quaternion rotation) { var queue = pooledObjects[prefab]; NetworkObject networkObject; if (queue.Count > 0) { networkObject = queue.Dequeue(); } else { networkObject = CreateInstance(prefab).GetComponent(); } nonPooledObjects[prefab]++; // Here we must reverse the logic in ReturnNetworkObject. var go = networkObject.gameObject; go.SetActive(true); go.transform.position = position; go.transform.rotation = rotation; return networkObject; } /// /// Registers all objects in to the cache. /// public void InitializePool() { if (m_HasInitialized) return; foreach (var configObject in PooledPrefabsList) { nonPooledObjects[configObject.Prefab] = 0; RegisterPrefabInternal(configObject.Prefab, configObject.PrewarmCount); nonPooledObjects[configObject.Prefab] = 0; } m_HasInitialized = true; } /// /// Unregisters all objects in from the cache. /// public void ClearPool() { foreach (var prefab in prefabs) { // Unregister Netcode Spawn handlers NetworkManager.Singleton.PrefabHandler.RemoveHandler(prefab); } pooledObjects.Clear(); } } [Serializable] struct PoolConfigObject { public GameObject Prefab; public int PrewarmCount; } class PooledPrefabInstanceHandler : INetworkPrefabInstanceHandler { GameObject m_Prefab; NetworkObjectPool m_Pool; public PooledPrefabInstanceHandler(GameObject prefab, NetworkObjectPool pool) { m_Prefab = prefab; m_Pool = pool; } NetworkObject INetworkPrefabInstanceHandler.Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation) { var netObject = m_Pool.GetNetworkObject(m_Prefab, position, rotation); return netObject; } void INetworkPrefabInstanceHandler.Destroy(NetworkObject networkObject) { m_Pool.ReturnNetworkObject(networkObject, m_Prefab); } }
I don't know how many tiems I've come to this tutorial in the last 3-4 months while trying to learn netcode for gameobjects. I'm so grateful for your content @samyam! For everyone else, like and subscribe! If you are working with NGO in Feb 2024, update to version 1.8.0, lots of quality of life improvements. Specially regarding how they handle RPCs, check the docs!
For people having problem using Pool, she's using version 1.1, you gotta change when following this tutorial. Took me a while to realize. Thanks for the content! Please if you can, show us the version of the libraries u are using, those libraries change versions very fast and sometimes we cannot watch full video because we get stuck due to versions. Just a humble suggestion, anyways, thanks for the content!!!
Very cool introduction - Netcode for Gameobjects is demanding, i use it myself and Sam did a great job explaining the concepts and the important parts to start with it.
44:32 You are a god send! I had so much trouble trying to understand this concept, searching everywhere to understand how to think when programming. But you explained it perfectly AND WITH VISUALS!!!
I already saved it👍🏻 in a Video List for studying it when I enter the Multiplayer stage, making a Prototype for my Portfolio. Thank You for keeping this level of Professionalism 👔😄
Just starting to tackle the multiplayer functionality in my game, and this is the first video I came across. Got some snacks to munch on while I binge the rest of your content. Looking forward to becoming a patron in the future, love your work.
Only 48 minutes of this great video and I have learned so much more than in any other course. Thank you so much for this. Guess I'll have to throw around more praise at the end of the video. But if the quality holds up, it's more than deserved 👍
42:48 💀 the work that UA-cam educators go through to teach us... much appreciated @samyam! I'm following along and I can't help but get excited every time something works on my end just like it did on your video. Can't wait to apply all this to my game idea ***insert Kermit excited GIF***
Awesome tutorial! Doing a tutorial on client side prediction would be a life saver. The way you explain things is so much easier to follow than many other tutorials.
btw @samyam as a keyboard shortcut junkie I love that you are always saying the keyboard shortcuts out loud. I used Carnac to automatically display any keyboard shortcuts on the screen and it works pretty good. That way others will see it as I do the shortcuts.
Not sure if mentioned in the comments yet but I just finished the object pool section and Unity has already updated the script for object pooling on their doc page. You no longer have to create the non pooled object variable as they replaced the queue with an object pool object which keeps track of how many active and inactive objects are in the scene. No fault to the creator of the video as she is doing a wonderful job teaching, just we all know unfortunately unity updates stuff every week it seems haha. But just wanted to point that out if anyone is having any issues following on the object pool section.
Are you saying when we place the line "NetworkObjectPool.Singleton.InitializePool();" that can be ignored? Or does it need to be replaced with "NetworkObjectPool.Singleton.RegisterPrefabInternal(prefab, 30);" as I saw someone else suggest? In that instance, RegisterPrefabInternal() would also have to be changed to 'public.'
@@christophergraf5929 You can just delete the line "NetworkObjectPool.Singleton.InitializePool();" because in the updated version the initialization is already carried out with the OnNetworkSpawn method public override void OnNetworkSpawn() { // Registers all objects in PooledPrefabsList to the cache. foreach (var configObject in PooledPrefabsList) { RegisterPrefabInternal(configObject.Prefab, configObject.PrewarmCount); } }
I think I might've caught a bug, but this is my first time using NGO and Coroutines so I'm not sure that I'm correct. The SpawnOverTime() Coroutine is called from within SpawnFoodStart() which begins the while loop that will periodically spawn food. What I'm noticing is that the while loop breaks immediately if you start the game with a Server as opposed to a Host since ConnectedClients.Count is 0 at the time SpawnOverTime() is called. From that point forward, the game no longer spawns any food even after clients connect because SpawnOverTime() is never called again. Regardless, this is a phenomenal video that you clearly put an insane amount of effort into and I really appreciate it! Subscribing immediately.
I love this tutorial! I just wanted to point out that Jetbrains has a feature you an enable in the Preferences to automatically clean up imports. With this enabled as soon as you save the script, it will automatically remove any unused import. So no more manually deleting! :)
My version of Network Manager doesn't allow you to put prefabs in the network prefabs list. According to the internet: You have to create a Network Prefabs List scriptable object, add your prefabs there and add that list to the Network Manager. It was easy to do though.
I think it is good to mention, that when you call NetworkManager.Singleton.StartClient() and NetworkManager.Singleton.StartServer() in different scenes, than there will be created more than one NetworkManager Instances! I took me hours to figure this out!
Reaaally nice video. I kinda wanted a programming challenge and I think multiplayer is a BIG ONE and this video was a great start. Thank you for your content :D Obs: Your voice looks like that TikTok ad "You wanna crush 2023?" lol
Your networking description at the beginning of this was great and even held my ADHD 9yr olds attention until you got to TCP and UDP. you should break that out into it’s own video
This was a very helpful tutorial, thanks a lot for the effort. As I've already used Unity Netcode for GameObjects I can say you've done a great job teaching the general concepts by example
Hi SamYam, I love your video , and I have always been curious as to how coders like dani and yourself manage to learn all of these networking concepts. For me personally, when I open any documentation, my mind just explodes, so i guess do you just push through and read all of the documentation or do you utilize any other sources? oh and what about how you learnt the concept of client-side prediction?
OnNetworkspawn seems very buggy for objects pre placed in the scene documentation says you can replace objects but when pressing play mode it does not work reliably...
In the authoritative movement section, I don't understand why you don't use the MovePlayerClient function and the player can still move. In my project I'm following yours, if I do the same as you, only the player on the host can move smoothly and the player on the client can move uncontrollably.
Amazing video. One small query : After lobby, i have to move to the Level Selection scene which selects which level to choose. That level scene is an addressable which is being downloaded from cloud. But net code does not seem to work with addressable scene. Any advice? I am thinking two options : 1) Use RPC to manually load the addressable scene on all clients 2) Make all the contents of the scene an addressable prefab and then include the empty scene in build settings which can be loaded through netcode. Then instantiate the adressable when the scene is loaded by netcode. Thanks in advance 😃
Also for the network stats monitor you need Unity 2021.2 or later. Any earlier version will not compile due to version dependencies in the assemblies. Our team had to learn this the hard way lol, super useful tool though.
37:15 I have used your source code but I am getting the error: Assets\_Scripts\PlayerController.cs(21,13): error CS0246: The type or namespace name 'PlayerLength' could not be found (are you missing a using directive or an assembly reference?)
Hi, can you help me? Why my objectPool doesnt hide objects for client, only for server, rewatched the moment many times, and dont know, why i have this problem
In Netcode GameObjects version 1.3.1 they added this: Network prefabs are now stored in a ScriptableObject that can be shared between NetworkManagers, and have been exposed for public access. By default, a Default Prefabs List is created that contains all NetworkObject prefabs in the project, and new NetworkManagers will default to using that unless that option is turned off in the Netcode for GameObjects settings. Existing NetworkManagers will maintain their existing lists, which can be migrated to the new format via a button in their inspector. (#2322) Does this mean that I no longer need to add my prefab to the Network Prefabs List, because as soon as I assign the Network Object it is added to the default List? I updated mid project and now I can't add stuff to the list... :(
Of course they update it right after my tutorial 😂 From the description it seems that you just have to make the object a prefab with the NetworkObject component attached and it will work, which is honestly better in the long-run.
@@samyam Honestly I believe it was because I started working through this video. I feel like everytime I start to learn Netcode with Unity, an update happens that breaks it and I quit. I tried to put it into the default Network Prefabs list, however, it does not seem to spawn them on start. My newb guess would be something along the lines of being in a list and needing to be called from the list now instead of just spawning, but I am so new to this I won't find the answer for at least another month or two after my knowledge catches up... to this one little problem. :D
@@samyam I think you're right, you just add it to the list and it worked. I had another issue due to upgrades and stuff. It randomly fixed itself, so I can't tell you what was wrong or how I fixed it so I will chalk it up to rebooting 3 times.
currently it's 1.5.2v of Netcode and i can't go further from 25 min because of the list of NetcodeGameobjects.. will wait for somebody to make a new tutorial as i really want to learn multiplayer part, and seems like there are many changes made in this 6 month. But like and subscribe is yours ))
How do we start another instance of server when the current server is full Is it possible to automatically run another game instance on a dedicated hosted server?
I have a slight problem with prefabs reference to themselves. After Instantiating reference changes to the instance of the prefab. So some pooled object can’t return himself to the pool because it has different prefab reference than the one that stored in NetworkObjectPool. What can we do with that? Change the key in ObjectPool to string?
if we have a lot of enemy prefab we need to put them all on network prefab? like i have 6 type of enemy prefab but they spawn like 50-60 times, need i put them all 50-60 on the network prefab section ( on 21:40 ) or just one of them (the original one prefab) works?
i got a error saying after getting the pacage: "Asembly with name ......"(the name of the package) alreadyy exists, for those of you who also got this, just open file explorer and open the project file and delete all the projects except Assets, Project Settings, user Settings, and the .sln
Hey Samyam! Was wondering if you've used any of the Photon tools before? (apologies if you mentioned it in the video and I missed it) I've been using "Photon Unity Networking 2" for a long time but seeing the activity around other devs and Unity Netcode, my interest is piqued. Is there a particular reason you chose this solution over Photon or any other? Thank in advance!
Nearly of all games are using server,client technique where there is one server and multiple clients. We need this, but there's literally zero video about this on UA-cam.
Awesome tutorial, I'm applying this to a 3D game which uses complex rotation transforms and got an issue where rotation axes were not synchronizing correctly. If anyone else gets this issue, the fix is to update to Netcode for GameObjects 1.5.1 in unity 2023 which allows quaternion synchronization instead of euler synchronization.
Can you give me a hint? I can't add other prefabs to the online game (like you added food). I have "NetcodeForGameObject 1.4.0" installed. It differs in that you can't just add a prefab to the "Network Prefabs List". Prefabs can only be added to a special asset "DefaultNetworkPrefabs". The "Network Prefabs List" only accepts this asset. The problem is that the "Network Prefabs List" is automatically cleared for some reason when the host starts up. So I can't add/synchronize other prefabs to the network game.
Good course. I am following it and I hope to learn to create some multiplayer game. To develop multiplayer games like this for Android and Apple, do you think a Mac Mini M2 with 8gb of RAM can be enough? or would it have to have 16gb of ram? Greetings.
How would you tackle changing the color of the snakes based on a separate scene where you can choose any color? I'm struggling to synchronize the color in all the clients....
I had the same issue. Actually I made an almost 200-line comment explaining how to get around that. But it seems that my comment got filtered out by the spam filter. Let's see if it makes through.
@@abdulkadiraktas5529 On the link samyam provided, it took me to the GitHub page and there, not only you can see the latest code, but also the changes made to the file through the weeks.
I don't understand why there is a seperate script lying around in the documentation (ClientNetworkTransform) - instead of including it as a boolean flag in the NetworkTransform or whatever? I am totally confused by this
Hi, I am doing a mini version of Hearthstone as a university project, and I need to build the backend for the multiplayer with .Net Core, do you have any course on how to make a multiplayer with .Net Core? or any suggestions for good tutorials for that?
Hey samyam, first time viewer. I have a couple question. When playing as a host, I noticed that there is a very brief period after calling the Spawn function in the food spawner where the food game object is active, but it is not yet technically recognized as "spawned". If the food spawns on the snake, since the game object is active but not "spawned", then calling the Despawn function in the OnTriggerEnter2D callback gives an error saying that the object isn't spawned. I was able to fix the error by adding a check to see if it was spawned before despawning, but should I bother with adding this check if I don't plan to host? There's also the issue of the food spawning over multiple tail objects, but I was able to fix that by checking to see if the collider was already entered on the same Time.time and simply return from the OnTriggerEnter2D callback if it was. However, my solution feels "jerry-rigged" to me. Does this seem like an appropriate solution to you?
You are seriously the best out there. Your explanations are easy to follow and straight to point. Thank you for all the tutorials you made so far. Also I wanted to ask a question. Whenever I install the cinemachine package in my project, it crashes the project every time I open it. Whenever I remove the package, everything works well. Any solution for this.
Thank you!! Hard to tell without seeing the console, what Unity version and Cinemachine version do you use? You can join our Discord and ask in the help chat 😁
After uncommenting the NetworkObject.Despawn() I get a InvalidOperationException: Trying to release an object that has already been released to the pool. error on the host. But if I don't do that the food doesn't disappear on the Client. Does anyone have a solution?
When using the client authoritative solution and using the default position threshold (0.001), movements from either two players (host or client) sometimes cause the displayed position to be incorrect for the other one. usually this is very noticeable and is a large difference in position. Setting it to 0 fixes it but that doesn't seem efficient. Should I instead use server authoritative or is there a possible solution?
on my screen and version the list of prefabs is called network prefab listS and i have to add a prefab list instead of a gameobject can someone please help me
You can make a Network Prefab List in your Assets by Right Clicking > Create >Netcode> Network Prefabs List I believe and put the prefabs you want in there, then you can put that list into your network manager
I still couldn't be able to understand IsOwner bool. So since both players have "PlayerController"; the host is ticked as owner and client is not. So our number 1 player update will work since he is an owner. But since number 2 player is not an owner, it's update wont execute right? So how it can still move then? Like you said networking is mindset and i could not be able to have this mindset on this example. Can you explain it to me once again please? :)
Anyone know if Netcode for GameObjects supports cross-platform communication (e.g. iOS & Windows)? I have a game using Lobby, Relay and Netcode for GameObjects and it works great if all the players are on the same platform (either iOS or Windows). But if players are on different platforms I'm not seeing OnClientConnectedCallback and RPCs don't seem to work across the platforms. I have confirmed that clients on all the platforms are connecting to the same IP and Port and that the transport protocol version is the same. Lobby seems to work fine so players can see Lobbies from other platforms and join them.
Great Tutorial with a lot of personal tips on the side :) Very nice... * I do wonder though if somehow i missed something or this just wasn't really implemented yet : when a player gets eaten player & tails are gone as expected in that client. On the other clients none of these are destroyed ! Same on the server. There is just dead bodies all over ?!?:) * & since the tails were collapsing over each other when the head stops, i changed the tail update method, private void Update() { deltaPos = followTransform.position - transform.position; deltaPos.z = 0f; if (deltaPos.magnitude < distance) return; transform.position += deltaPos * Time.deltaTime * moveStep; transform.up = deltaPos.normalized; // Added 'legs' to each tail-segment needed this transform .up }
subscribe for cute lil snakes - watch the next part here ua-cam.com/video/FjOZrSPL_-Y/v-deo.html
Wishlist my new game BUMBI on Steam! store.steampowered.com/app/2862470/BUMBI/
small bug fix - in PlayerLength OnNetworkSpawn() after subscribing to the length changed event, put:
// If there was another player already in the match, the beginning tails of them won't be updated. These lines check the length of the snake and spawn the tails of the other clients accordingly.
if (IsOwner) return;
for (int i = 0; i < length.Value - 1; ++i)
InstantiateTail();
Also before spawning the Food object make sure to do if (!obj.IsSpawned) obj.Spawn(true); And when despawning you can just do if (NetworkObject.IsSpawned) NetworkObject.Despawn();, and not Destroy it.
Can you please provide minute mark of this bug?
You can add this at any time, it’s just so that when a new player joins it can spawn the tails of the other players if they had already grown in length. The section before 1:10:03
Could you pls leave here a document/text with the ObjectNetworkPool script? The original document was updated and is complete different of the one shown in the video, it does not even have an InitializePool function. That would be really helpful
@@mathinho_ns
Here you go. Also before spawning object make sure to do if (!obj.IsSpawned) obj.Spawn(true); And when despawning you can just do if (NetworkObject.IsSpawned) NetworkObject.Despawn();, and not Destroy it.
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using Unity.Netcode;
using UnityEngine;
using UnityEngine.Assertions;
///
/// Object Pool for networked objects, used for controlling how objects are spawned by Netcode. Netcode by default will allocate new memory when spawning new
/// objects. With this Networked Pool, we're using custom spawning to reuse objects.
/// Boss Room uses this for projectiles. In theory it should use this for imps too, but we wanted to show vanilla spawning vs pooled spawning.
/// Hooks to NetworkManager's prefab handler to intercept object spawning and do custom actions
///
public class NetworkObjectPool : NetworkBehaviour
{
private static NetworkObjectPool _instance;
public static NetworkObjectPool Singleton { get { return _instance; } }
[SerializeField]
List PooledPrefabsList;
HashSet prefabs = new HashSet();
private Dictionary pooledObjects = new Dictionary();
private Dictionary nonPooledObjects = new Dictionary();
private bool m_HasInitialized = false;
public void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(this.gameObject);
}
else
{
_instance = this;
}
}
public override void OnNetworkSpawn()
{
InitializePool();
}
public override void OnNetworkDespawn()
{
ClearPool();
}
public void OnValidate()
{
for (var i = 0; i < PooledPrefabsList.Count; i++)
{
var prefab = PooledPrefabsList[i].Prefab;
if (prefab != null)
{
Assert.IsNotNull(prefab.GetComponent(), $"{nameof(NetworkObjectPool)}: Pooled prefab \"{prefab.name}\" at index {i.ToString()} has no {nameof(NetworkObject)} component.");
}
}
}
///
/// Gets an instance of the given prefab from the pool. The prefab must be registered to the pool.
///
///
///
public NetworkObject GetNetworkObject(GameObject prefab)
{
return GetNetworkObjectInternal(prefab, Vector3.zero, Quaternion.identity);
}
///
/// Gets an instance of the given prefab from the pool. The prefab must be registered to the pool.
///
///
/// The position to spawn the object at.
/// The rotation to spawn the object with.
///
public NetworkObject GetNetworkObject(GameObject prefab, Vector3 position, Quaternion rotation)
{
return GetNetworkObjectInternal(prefab, position, rotation);
}
///
/// Return an object to the pool (reset objects before returning).
///
public void ReturnNetworkObject(NetworkObject networkObject, GameObject prefab)
{
// Debug.Log("Returning Object");
var go = networkObject.gameObject;
go.SetActive(false);
pooledObjects[prefab].Enqueue(networkObject);
nonPooledObjects[prefab]--;
}
///
/// Returns how many of the specified prefab have been instantiated but are not in the pool.
///
public int GetCurrentPrefabCount(GameObject prefab)
{
return nonPooledObjects[prefab];
}
///
/// Adds a prefab to the list of spawnable prefabs.
///
/// The prefab to add.
///
public void AddPrefab(GameObject prefab, int prewarmCount = 0)
{
var networkObject = prefab.GetComponent();
Assert.IsNotNull(networkObject, $"{nameof(prefab)} must have {nameof(networkObject)} component.");
Assert.IsFalse(prefabs.Contains(prefab), $"Prefab {prefab.name} is already registered in the pool.");
RegisterPrefabInternal(prefab, prewarmCount);
}
///
/// Builds up the cache for a prefab.
///
private void RegisterPrefabInternal(GameObject prefab, int prewarmCount)
{
prefabs.Add(prefab);
var prefabQueue = new Queue();
pooledObjects[prefab] = prefabQueue;
for (int i = 0; i < prewarmCount; i++)
{
var go = CreateInstance(prefab);
ReturnNetworkObject(go.GetComponent(), prefab);
}
// Register Netcode Spawn handlers
NetworkManager.Singleton.PrefabHandler.AddHandler(prefab, new PooledPrefabInstanceHandler(prefab, this));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private GameObject CreateInstance(GameObject prefab)
{
return Instantiate(prefab);
}
///
/// This matches the signature of
///
///
///
///
///
private NetworkObject GetNetworkObjectInternal(GameObject prefab, Vector3 position, Quaternion rotation)
{
var queue = pooledObjects[prefab];
NetworkObject networkObject;
if (queue.Count > 0)
{
networkObject = queue.Dequeue();
}
else
{
networkObject = CreateInstance(prefab).GetComponent();
}
nonPooledObjects[prefab]++;
// Here we must reverse the logic in ReturnNetworkObject.
var go = networkObject.gameObject;
go.SetActive(true);
go.transform.position = position;
go.transform.rotation = rotation;
return networkObject;
}
///
/// Registers all objects in to the cache.
///
public void InitializePool()
{
if (m_HasInitialized) return;
foreach (var configObject in PooledPrefabsList)
{
nonPooledObjects[configObject.Prefab] = 0;
RegisterPrefabInternal(configObject.Prefab, configObject.PrewarmCount);
nonPooledObjects[configObject.Prefab] = 0;
}
m_HasInitialized = true;
}
///
/// Unregisters all objects in from the cache.
///
public void ClearPool()
{
foreach (var prefab in prefabs)
{
// Unregister Netcode Spawn handlers
NetworkManager.Singleton.PrefabHandler.RemoveHandler(prefab);
}
pooledObjects.Clear();
}
}
[Serializable]
struct PoolConfigObject
{
public GameObject Prefab;
public int PrewarmCount;
}
class PooledPrefabInstanceHandler : INetworkPrefabInstanceHandler
{
GameObject m_Prefab;
NetworkObjectPool m_Pool;
public PooledPrefabInstanceHandler(GameObject prefab, NetworkObjectPool pool)
{
m_Prefab = prefab;
m_Pool = pool;
}
NetworkObject INetworkPrefabInstanceHandler.Instantiate(ulong ownerClientId, Vector3 position, Quaternion rotation)
{
var netObject = m_Pool.GetNetworkObject(m_Prefab, position, rotation);
return netObject;
}
void INetworkPrefabInstanceHandler.Destroy(NetworkObject networkObject)
{
m_Pool.ReturnNetworkObject(networkObject, m_Prefab);
}
}
@@samyam Very Very thank you
I don't know how many tiems I've come to this tutorial in the last 3-4 months while trying to learn netcode for gameobjects. I'm so grateful for your content @samyam!
For everyone else, like and subscribe!
If you are working with NGO in Feb 2024, update to version 1.8.0, lots of quality of life improvements. Specially regarding how they handle RPCs, check the docs!
Multiplayer game incoming.
Great video Sam
mana valley coop mode?? thx 😁
One of the best Unity Multiplayer tutorials ive seen, gives almost all Basics you need for a Unity Multiplayer Game
But how did you figure it out? Since you did this 2 months ago, you were using a different NetworkObjectPool.cs than in the video.
Components:
FoodObj: 1:14:41
poolManagerObj: 1:19:24 1:28:54
playerCanvasObj: 1:34:00
gamevOver : 2:00:00
server canvas: 2:04:50
connection handle: 2:15:50
So many good tips scattered throughout this video. Amazing!
Thank you 🙏☺️
For people having problem using Pool, she's using version 1.1, you gotta change when following this tutorial. Took me a while to realize. Thanks for the content! Please if you can, show us the version of the libraries u are using, those libraries change versions very fast and sometimes we cannot watch full video because we get stuck due to versions. Just a humble suggestion, anyways, thanks for the content!!!
Very cool introduction - Netcode for Gameobjects is demanding, i use it myself and Sam did a great job explaining the concepts and the important parts to start with it.
Thanks so much! 😁
44:32 You are a god send! I had so much trouble trying to understand this concept, searching everywhere to understand how to think when programming. But you explained it perfectly AND WITH VISUALS!!!
Thank you! It confused me too at first and no one seemed to explain it well for me to understand
I already saved it👍🏻 in a Video List for studying it when I enter the Multiplayer stage, making a Prototype for my Portfolio.
Thank You for keeping this level of Professionalism 👔😄
I cannot belive I just happened to stumble across this hidden gem of a video! Great job!!!
Just starting to tackle the multiplayer functionality in my game, and this is the first video I came across. Got some snacks to munch on while I binge the rest of your content. Looking forward to becoming a patron in the future, love your work.
Thank you!
Only 48 minutes of this great video and I have learned so much more than in any other course. Thank you so much for this. Guess I'll have to throw around more praise at the end of the video. But if the quality holds up, it's more than deserved 👍
How did you figure it out when using a different NetworkObjectPool.cs than she has in the video?
42:48
💀 the work that UA-cam educators go through to teach us... much appreciated @samyam! I'm following along and I can't help but get excited every time something works on my end just like it did on your video. Can't wait to apply all this to my game idea ***insert Kermit excited GIF***
Glad I can help 😄
Awesome tutorial! Doing a tutorial on client side prediction would be a life saver. The way you explain things is so much easier to follow than many other tutorials.
Great job on the video. Always love how thorough your tutorials are! I'd also like to see some of the more Advanced techniques!
btw @samyam as a keyboard shortcut junkie I love that you are always saying the keyboard shortcuts out loud. I used Carnac to automatically display any keyboard shortcuts on the screen and it works pretty good. That way others will see it as I do the shortcuts.
Thanks! I considered it but I thought it might be annoying in a tutorial to have it pop up constantly. I’ll think about it!
@@samyam Oh! That makes sense. I guess that would be a ton of pop ups 😅
Not sure if mentioned in the comments yet but I just finished the object pool section and Unity has already updated the script for object pooling on their doc page. You no longer have to create the non pooled object variable as they replaced the queue with an object pool object which keeps track of how many active and inactive objects are in the scene. No fault to the creator of the video as she is doing a wonderful job teaching, just we all know unfortunately unity updates stuff every week it seems haha. But just wanted to point that out if anyone is having any issues following on the object pool section.
Thanks!
i cant seem to find where that is located
Are you saying when we place the line "NetworkObjectPool.Singleton.InitializePool();" that can be ignored? Or does it need to be replaced with "NetworkObjectPool.Singleton.RegisterPrefabInternal(prefab, 30);" as I saw someone else suggest? In that instance, RegisterPrefabInternal() would also have to be changed to 'public.'
@@christophergraf5929 You can just delete the line "NetworkObjectPool.Singleton.InitializePool();" because in the updated version the initialization is already carried out with the OnNetworkSpawn method
public override void OnNetworkSpawn()
{
// Registers all objects in PooledPrefabsList to the cache.
foreach (var configObject in PooledPrefabsList)
{
RegisterPrefabInternal(configObject.Prefab, configObject.PrewarmCount);
}
}
I think I might've caught a bug, but this is my first time using NGO and Coroutines so I'm not sure that I'm correct. The SpawnOverTime() Coroutine is called from within SpawnFoodStart() which begins the while loop that will periodically spawn food. What I'm noticing is that the while loop breaks immediately if you start the game with a Server as opposed to a Host since ConnectedClients.Count is 0 at the time SpawnOverTime() is called. From that point forward, the game no longer spawns any food even after clients connect because SpawnOverTime() is never called again.
Regardless, this is a phenomenal video that you clearly put an insane amount of effort into and I really appreciate it! Subscribing immediately.
I noticed same bug and end up modify it to while(true) for the food spawner works without breaking.
I love this tutorial! I just wanted to point out that Jetbrains has a feature you an enable in the Preferences to automatically clean up imports. With this enabled as soon as you save the script, it will automatically remove any unused import. So no more manually deleting! :)
Omg this is so useful thank you!
Samyam, I love you! Such great explanation in such a comprehensive way. I am learning so much from your channel. Please keep up the good work ❤
thank you! ☺️
Sam's the best and ye remember me when you are famous LOL
Clear and concise guidance that I will definitely be referencing over and over :)
I've watched ALL of the NGO youtube tutorials. this is by far and large my favorite one on youtube
Thank you! 😄
the way this tutorial is so goated !! I keep coming back to reference code and understand things better :) tysm for explaining the logic thoroughly
My version of Network Manager doesn't allow you to put prefabs in the network prefabs list. According to the internet: You have to create a Network Prefabs List scriptable object, add your prefabs there and add that list to the Network Manager. It was easy to do though.
Thank you!
how? pleasee...how to create that network prefabs list scriptable object? i have no clue, since mine didnt have any features to do that
my hero
This was the best Tutorial i have encountered yet.
ThankYou Samyam.
I think it is good to mention, that when you call NetworkManager.Singleton.StartClient() and NetworkManager.Singleton.StartServer() in different scenes, than there will be created more than one NetworkManager Instances! I took me hours to figure this out!
Your explanation of servers was more clear than my professor's
Thank you so much for the in depth tutorial! I would love to see more about client side prediction as it is a very important aspect of multiplayer!
this was well explained, thankyou, id also vote for that client prediction video
Reaaally nice video. I kinda wanted a programming challenge and I think multiplayer is a BIG ONE and this video was a great start. Thank you for your content :D
Obs: Your voice looks like that TikTok ad "You wanna crush 2023?" lol
I’m not familiar with that ad 😂
This was extremely interesting, thank you. I've put it on my "saved" list for future re-watching.
Your networking description at the beginning of this was great and even held my ADHD 9yr olds attention until you got to TCP and UDP. you should break that out into it’s own video
Amazing job, I love all the work and details you put into the video, comments, and description.
thank you! 😁
This was a very helpful tutorial, thanks a lot for the effort.
As I've already used Unity Netcode for GameObjects I can say you've done a great job teaching the general concepts by example
Thank you so much!
I just started with this tutorial but I needed to tell you that you are very good explaining and so fun :) Let's see how it goes.
Hi SamYam, I love your video , and I have always been curious as to how coders like dani and yourself manage to learn all of these networking concepts. For me personally, when I open any documentation, my mind just explodes, so i guess do you just push through and read all of the documentation or do you utilize any other sources? oh and what about how you learnt the concept of client-side prediction?
Best Explanation for networking ❤
How do you handle host migration, or is it possible in netcode for gameobjects without lobby or relay?
Whenever I do multiplayer, this will certainly come in handy. 🤓
I would love a video on implementing client side prediction/ reconciliation! :)
I can't add the player prefab to the list, but it gets added to the player prefab. How to solve?
OnNetworkspawn seems very buggy for objects pre placed in the scene documentation says you can replace objects but when pressing play mode it does not work reliably...
In the authoritative movement section, I don't understand why you don't use the MovePlayerClient function and the player can still move. In my project I'm following yours, if I do the same as you, only the player on the host can move smoothly and the player on the client can move uncontrollably.
Amazing video.
One small query :
After lobby, i have to move to the Level Selection scene which selects which level to choose.
That level scene is an addressable which is being downloaded from cloud.
But net code does not seem to work with addressable scene.
Any advice?
I am thinking two options :
1)
Use RPC to manually load the addressable scene on all clients
2)
Make all the contents of the scene an addressable prefab and then include the empty scene in build settings which can be loaded through netcode. Then instantiate the adressable when the scene is loaded by netcode.
Thanks in advance 😃
Amazing work Sam thank you so much for putting all of this together !
Thanks Valem! 😄
Also for the network stats monitor you need Unity 2021.2 or later. Any earlier version will not compile due to version dependencies in the assemblies. Our team had to learn this the hard way lol, super useful tool though.
Thanks for the tip!
37:15 I have used your source code but I am getting the error: Assets\_Scripts\PlayerController.cs(21,13): error CS0246: The type or namespace name 'PlayerLength' could not be found (are you missing a using directive or an assembly reference?)
This girl is PRO.. Thank you for your knowledge sharing! :)
Thanks a lot. Best explanation I've heard on youtube
Hi, can you help me? Why my objectPool doesnt hide objects for client, only for server, rewatched the moment many times, and dont know, why i have this problem
This is great! I would love to see a client-side prediction video!
In Netcode GameObjects version 1.3.1 they added this: Network prefabs are now stored in a ScriptableObject that can be shared between NetworkManagers, and have been exposed for public access. By default, a Default Prefabs List is created that contains all NetworkObject prefabs in the project, and new NetworkManagers will default to using that unless that option is turned off in the Netcode for GameObjects settings. Existing NetworkManagers will maintain their existing lists, which can be migrated to the new format via a button in their inspector. (#2322) Does this mean that I no longer need to add my prefab to the Network Prefabs List, because as soon as I assign the Network Object it is added to the default List? I updated mid project and now I can't add stuff to the list... :(
Of course they update it right after my tutorial 😂 From the description it seems that you just have to make the object a prefab with the NetworkObject component attached and it will work, which is honestly better in the long-run.
@@samyam Honestly I believe it was because I started working through this video. I feel like everytime I start to learn Netcode with Unity, an update happens that breaks it and I quit. I tried to put it into the default Network Prefabs list, however, it does not seem to spawn them on start. My newb guess would be something along the lines of being in a list and needing to be called from the list now instead of just spawning, but I am so new to this I won't find the answer for at least another month or two after my knowledge catches up... to this one little problem. :D
Don’t lose hope! If anything join our Discord in the description and ask in the help channel!
@@samyam I think you're right, you just add it to the list and it worked. I had another issue due to upgrades and stuff. It randomly fixed itself, so I can't tell you what was wrong or how I fixed it so I will chalk it up to rebooting 3 times.
currently it's 1.5.2v of Netcode and i can't go further from 25 min because of the list of NetcodeGameobjects.. will wait for somebody to make a new tutorial as i really want to learn multiplayer part, and seems like there are many changes made in this 6 month. But like and subscribe is yours ))
Exactly what I needed, Thank you :D
I really enjoyed this, thank you 🙂
Omg, if you dont make a new video, this is the best netcode tutorial!
How do we start another instance of server when the current server is full
Is it possible to automatically run another game instance on a dedicated hosted server?
Yes i’m the next video of this i’ll show how to use UGS and matchmaker which will manage this for you
@@samyam Thank you so much.
But when can we expect that video ?
@@RizuHaque Most likely in April :) If you are in a hurry check out CodeMonkey’s recent videos
I have a slight problem with prefabs reference to themselves. After Instantiating reference changes to the instance of the prefab. So some pooled object can’t return himself to the pool because it has different prefab reference than the one that stored in NetworkObjectPool. What can we do with that? Change the key in ObjectPool to string?
if we have a lot of enemy prefab we need to put them all on network prefab? like i have 6 type of enemy prefab but they spawn like 50-60 times, need i put them all 50-60 on the network prefab section ( on 21:40 ) or just one of them (the original one prefab) works?
So fell in love with your magic voice))
don't you use the MovePlayerClient function?
Amazing Work! would it be possible if you could do more Tutorials on unity's AR Foundation like scale and rotate the placed object in the AR Scene?
Thank you for bringing such excellent tutorials, which cover almost all aspects. It was a very enjoyable learning experience! Thank you very much!
i got a error saying after getting the pacage: "Asembly with name ......"(the name of the package) alreadyy exists, for those of you who also got this, just open file explorer and open the project file and delete all the projects except Assets, Project Settings, user Settings, and the .sln
Hey Samyam! Was wondering if you've used any of the Photon tools before? (apologies if you mentioned it in the video and I missed it)
I've been using "Photon Unity Networking 2" for a long time but seeing the activity around other devs and Unity Netcode, my interest is piqued. Is there a particular reason you chose this solution over Photon or any other?
Thank in advance!
I tried Photon once years ago but I haven't tried it recently!
@samyam Food Networked Object has not been hide after the player has been reached
Nearly of all games are using server,client technique where there is one server and multiple clients. We need this, but there's literally zero video about this on UA-cam.
Love it thanks Samyam.
Amazing! I was thinking in make a videogame for my university project and I found this video so helpful :)
Stuck on 24:47 , why I cannot put the prefab to Network Prefabs List? I have added the Netwrok Object component on the prefab. Unity 2022.3.6f1
Solution: In the project file, right click, Netcode, make the NetworkPrefabList SO, put your GO there, and put this SO on the Network Manager
My goodness this all is so complex. how does someone learn to write this on their own as you, in the first place? 🤯🤯
You show a shooter, but would you not use photon for a shooter?
Awesome tutorial, I'm applying this to a 3D game which uses complex rotation transforms and got an issue where rotation axes were not synchronizing correctly.
If anyone else gets this issue, the fix is to update to Netcode for GameObjects 1.5.1 in unity 2023 which allows quaternion synchronization instead of euler synchronization.
Can you give me a hint? I can't add other prefabs to the online game (like you added food). I have "NetcodeForGameObject 1.4.0" installed. It differs in that you can't just add a prefab to the "Network Prefabs List". Prefabs can only be added to a special asset "DefaultNetworkPrefabs". The "Network Prefabs List" only accepts this asset. The problem is that the "Network Prefabs List" is automatically cleared for some reason when the host starts up. So I can't add/synchronize other prefabs to the network game.
Good course.
I am following it and I hope to learn to create some multiplayer game.
To develop multiplayer games like this for Android and Apple, do you think a Mac Mini M2 with 8gb of RAM can be enough? or would it have to have 16gb of ram?
Greetings.
Love the videos! Subscribed. I had a question though. Is it not a bad idea to call an RPC in Update? (every frame potentially 100+fps). 2:09:35
what do you think mate use your fuckin brain
How is the movement done using the new input system? how does the input manager change when doing it multiplayer from doing it single player?
How would you tackle changing the color of the snakes based on a separate scene where you can choose any color? I'm struggling to synchronize the color in all the clients....
Great tutorial. Very detailed and efficient. I learned a lot. Thanks!
on 1:20:52 I get "NetworkObjectPool does not contain a definition for 'InitializePool' "
I had the same issue. Actually I made an almost 200-line comment explaining how to get around that. But it seems that my comment got filtered out by the spam filter. Let's see if it makes through.
For that particular line that you mentioned I did this instead:
NetworkObjectPool.Singleton.RegisterPrefabInternal(prefab, 30);
@@richardgomes7d thank you, it works. i want to ask one more question how did you find the right code
@@abdulkadiraktas5529 On the link samyam provided, it took me to the GitHub page and there, not only you can see the latest code, but also the changes made to the file through the weeks.
Samyam added it to the links in the description. It is titled Networked Object Pooling.
I don't understand why there is a seperate script lying around in the documentation (ClientNetworkTransform) - instead of including it as a boolean flag in the NetworkTransform or whatever? I am totally confused by this
Hi, I am doing a mini version of Hearthstone as a university project, and I need to build the backend for the multiplayer with .Net Core, do you have any course on how to make a multiplayer with .Net Core? or any suggestions for good tutorials for that?
Hey samyam, first time viewer. I have a couple question. When playing as a host, I noticed that there is a very brief period after calling the Spawn function in the food spawner where the food game object is active, but it is not yet technically recognized as "spawned". If the food spawns on the snake, since the game object is active but not "spawned", then calling the Despawn function in the OnTriggerEnter2D callback gives an error saying that the object isn't spawned. I was able to fix the error by adding a check to see if it was spawned before despawning, but should I bother with adding this check if I don't plan to host?
There's also the issue of the food spawning over multiple tail objects, but I was able to fix that by checking to see if the collider was already entered on the same Time.time and simply return from the OnTriggerEnter2D callback if it was. However, my solution feels "jerry-rigged" to me. Does this seem like an appropriate solution to you?
Wow nice
your voice so sweat ❤️ best of luck✨
You are seriously the best out there. Your explanations are easy to follow and straight to point. Thank you for all the tutorials you made so far.
Also I wanted to ask a question. Whenever I install the cinemachine package in my project, it crashes the project every time I open it. Whenever I remove the package, everything works well.
Any solution for this.
Thank you!! Hard to tell without seeing the console, what Unity version and Cinemachine version do you use? You can join our Discord and ask in the help chat 😁
@@samyam Sure I'll do that
woops just solved it never mind (thanks for the good tutorial btw)
My tail prefab didn't follow tha head prefab 😢 instead it moving opposite of thr player
Hı,Can i use that for multiplayer card game?
Awesome tutoring! Thank you for that video 😁
Heya! Fantastic tutorial, I really enjoyed it.
Thank you!
After uncommenting the NetworkObject.Despawn() I get a InvalidOperationException: Trying to release an object that has already been released to the pool. error on the host. But if I don't do that the food doesn't disappear on the Client. Does anyone have a solution?
1:46:24 will that rpc be called two times if player will hit another player head by head?
Such a great video :)
Thank you so much
When using the client authoritative solution and using the default position threshold (0.001), movements from either two players (host or client) sometimes cause the displayed position to be incorrect for the other one. usually this is very noticeable and is a large difference in position. Setting it to 0 fixes it but that doesn't seem efficient. Should I instead use server authoritative or is there a possible solution?
on my screen and version the list of prefabs is called network prefab listS and i have to add a prefab list instead of a gameobject can someone please help me
Im having the same problem
You can make a Network Prefab List in your Assets by Right Clicking > Create >Netcode> Network Prefabs List
I believe and put the prefabs you want in there, then you can put that list into your network manager
@@samyam thanks
@@samyam thank you so much that's exactly what I was looking for
I still couldn't be able to understand IsOwner bool. So since both players have "PlayerController"; the host is ticked as owner and client is not. So our number 1 player update will work since he is an owner. But since number 2 player is not an owner, it's update wont execute right? So how it can still move then? Like you said networking is mindset and i could not be able to have this mindset on this example. Can you explain it to me once again please? :)
Anyone know if Netcode for GameObjects supports cross-platform communication (e.g. iOS & Windows)? I have a game using Lobby, Relay and Netcode for GameObjects and it works great if all the players are on the same platform (either iOS or Windows). But if players are on different platforms I'm not seeing OnClientConnectedCallback and RPCs don't seem to work across the platforms. I have confirmed that clients on all the platforms are connecting to the same IP and Port and that the transport protocol version is the same. Lobby seems to work fine so players can see Lobbies from other platforms and join them.
Great Tutorial with a lot of personal tips on the side :) Very nice...
* I do wonder though if somehow i missed something or this just wasn't really implemented yet :
when a player gets eaten player & tails are gone as expected in that client. On the other clients none of these are destroyed ! Same on the server. There is just dead bodies all over ?!?:)
* & since the tails were collapsing over each other when the head stops, i changed the tail update method,
private void Update() {
deltaPos = followTransform.position - transform.position;
deltaPos.z = 0f;
if (deltaPos.magnitude < distance) return;
transform.position += deltaPos * Time.deltaTime * moveStep;
transform.up = deltaPos.normalized; // Added 'legs' to each tail-segment needed this transform .up
}
How to spawn object at the position i want when I start host it spawns in center
How to fix it?