Hello, I am making a multiplayer (Netcode for GOs) game with procedurally generated terrain (in “chunks”), and have been tackling a problem for a few days now.
I use a GameObject called a Chunk Loader (not instantiated, but already in the scene), which has a NetworkObject
and a NetworkBehavior
(A subclass called ChunkLoader
)
In the ChunkLoader
, I’ve added a PlayerChunkRequests
(custom class), which holds a dictionary of chunks requested by players (Vector2Int
s) and the players that are asking for them (List<ulong>
), and has methods for Adding and Removing requests.
For some reason, the requests object always seems to reset, the frame after the dictionary is updated, and the requested chunks are deleted! I have added a public int count
field to the PlayerChunkRequests
class that would count the number of requests. It seems the count
variable also resets.
These are all references to the requests object:
-
A request is added when a player/client asks for a chunk to be loaded, from a server RPC.
-
The
Update()
function on the server checks the list of requests and starts threads to instantiate the chunk. -
It is removed when the chunk has loaded, which hasn’t happened.
Here is the relevant code (I’ve deleted a lot of irrelevant methods and fields):
using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
using UnityEngine;
using Unity.Netcode;
using TMPro;
public class ChunkLoader : NetworkBehaviour
{
public PlayerChunkRequests requests = new PlayerChunkRequests();
void Update() {
// Will check requests (doesn't work)
if(IsServer) {
UpdateTextClientRpc(requests.count); // This always shows zero
foreach(Vector2Int chunkPos in requests.Get().Keys) { // This never iterates
Request request = requests.Get()[chunkPos];
if(!request.processing) {
request.processing = true;
RequestMapData(OrderReady, chunkPos);
}
}
}
}
// Asks the server for a chunk
public void Load(Vector2Int chunkPos) {
if(IsClient) {
if(!clientChunks.Contains(chunkPos)) {
clientChunks.Add(chunkPos);
LoadChunkServerRpc(chunkPos);
}
}
}
// Adds to request. This works, but doesn't show next frame
[ServerRpc]
public void LoadChunkServerRpc(Vector2Int chunkPos) {
requests.Add(chunkPos, OwnerClientId);
}
}
// Holds lists of players and tells the Update() function that the request is being processed. (With the flag)
public class Request {
public List<ulong> players = new List<ulong>();
public bool processing = false;
public Request(ulong player) {
players.Add(player);
}
}
// The requests class
public class PlayerChunkRequests {
Dictionary<Vector2Int, Request>
requests = new Dictionary<Vector2Int, Request>();
public int count = 0;
public void Add(Vector2Int chunkPos, ulong player) {
if(requests.ContainsKey(chunkPos)) {
if(!requests[chunkPos].players.Contains(player))
requests[chunkPos].players.Add(player);
count++;
}
else requests.Add(chunkPos, new Request(player));
// This works
}
public Dictionary<Vector2Int, Request> Get() {
return requests; // How can it not work?
}
}
This is my first post/question, and I’m not very good at explaining things, but do try your best!
Also, yes, I do write spaghetti code. Do feel free to criticize me on this “design”, if you want.