#MultiScene setup
1 messages · Page 1 of 1 (latest)
also need to send some player and game info to the other scene as well
You would use NetworkSceneManager and to persist player and game info between scenes you can make an object DontDestroyOnLoad or make use of static variables/classes.
I like using scriptable objects for cross scene data.
Another quick and super dirty option is to use Player Prefs.
Okay i figured it out thanks guys it works now
now the issue im suck on is
NetworkVariable is written to, but doesn't know its NetworkBehaviour yet. Are you modifying a NetworkVariable before the NetworkObject is spawned?
coming from https://pastebin.com/UR2nKY7i
A network behavior has to be on a network object.
I'm not sure you can use a NetworkList in that way. Network Variable/List has to be on a NetworkBehaviour. You could make the Team a InetworkSerializable then you can use NetworkList<Team>
I would also avoid using singletons on network objects. They get destroyed and respawned when the scene loads. This can cause issues.
okay im in a bit of a situation here
what im doing here does not give the player the data about the previously joined users
now i want a way to send all the other users in there as well
You'll either need to send the entire list in the RPC somehow, or make the teams list into a NetworkList<Team> or NetworkVariable<List<Team>>
What about the dictionary?
Cant I do something to send my own custom data?
Like serealsize then desearlize so I can send whole list and dicts at once
You can do NetworkVariable<Dictionary<>> as well. I believe the Key Values still have to be INetworkSerializable though
what if its my custom class
is there any docs on how to make your own classes NetworkSerializable
Technically you can make classes inherent from INetworkSerializable. But they won't work with Network Variables
That is because Team is not an INetworkSerializable struct
List is still nullable
Everything in the struct has to be non-nullable as well. Your List players is nullable.
You can use either an array or Native List
actually I don't think an array will work in a Network List
tbh i have never bothered using an array cuz there are no add and such funcs there would it still be fine?
oh
let me try
didnt work
NativeList not NetworkList
from the docs
is this safe tho?
its not unsafe. just unmanaged
NativeArray doesn't require any additional settings
Did it recompile? because it definitely does work
Trying to package data together just for the sake of it because it’s what you’re used to in offline development is usually more trouble than it’s worth IMO
For example, I’m noticing you have 10 references to players, but only a few references to the other variables - so I would probably just split them apart
its more like im working on myself so like im trying to not do it just for it to work but rather to do it like in prod
gives me good learning exp
doesnt matter if its not worth the effort
no it did not
is it cuz of the already existing errors
okay just for the sake off it
imma see if arrays work
What is done in production is what works and what is time efficient.
yea but like i feel like if i can pack data together its less code + cleaner code + more reusable code + efficient
okay arrays dont work either
NativeArray
Not necessarily, that’s why I gave my original warning - I’ve competed multiple projects with NGO and have used INetworkSerializable and NetworkList very very rarely.
let me try to restart
comment out the error line and it will compile
Thanks for the advice tho imma do it here anyways so i atleast learn INetworkSerializable
that will create 100 million more errors
let me just make it a list for now
still the same error
i even recompiled
even restarted
why do i have issues here as well now
Okay cuz i had to do
NetworkVariable<List<ulong>> not NatworkList<Ulong>
oh Team also has to implement IEquatable if its used in NetworkList. see the Complex Types section for an example
NetworkList<> is slightly different from NetworkVariable<List<>>
NetworkVariable now includes delta compression for collection values (NativeList, NativeArray, NativeHashSet, NativeHashMap, List, HashSet, Dictionary, and FixedString types) to save bandwidth by only sending the values that changed. (Note: For NativeList, NativeArray, and List, this algorithm works differently than that used in NetworkList. This algorithm will use less bandwidth for "set" and "add" operations, but NetworkList is more bandwidth-efficient if you are performing frequent "insert" operations.) (#2813)
okay network list it is
thanks a bunch
do i need to imiliment count and other methods
cuz it seems to be giving some errors
No, It has Count
why does this happen
okay so its supposed to be like this new NativeList<ulong>(maxPlayerCount, Allocator.Persistent)
now it seems to work
okay seems to work fine in the editor but crashes in build
how do i figure this out?
why is the length of the list teams 0 on the client even tho i sync it accrss the server
okay i did a shitton of more debugging
the dict as well as the list both are not being syced 
NetworkList has to be initialized in Awake
like how?
and what bout the dict
that isnt synced either
Just like any other initialization. It just has to be done in Awake instead of at declaration.
I'm not sure. You didn't send where you're calling addPlayersToTeam. Probably not directly the issue, but you are adding to the Dictionary on the client side, which is incorrect since it has Server Write Permissions.
It also looks like you're doing that with your NetworkList, which I can't imagine is right either.
The whole purpose of NetworkVariable/NetworkList is that the Owner/Authority sets the value and auto syncs it to everyone else. Meaning you do not have to send that data through an RPC for the client to also set the same data.
like this?
Yes, but also remove the initialization at declaration as well.
public class PlayerInit : NetworkBehaviour
{
[Header("Singletons")]
[SerializeField]
private GameObject _camera;
[SerializeField]
private GameObject _cmCam;
[SerializeField]
private GameObject _vol;
[SerializeField]
private GameObject _ui;
public override void OnNetworkSpawn()
{
if (IsOwner)
{
StartCoroutine(RegisterWithTeamManager());
}
if (!IsOwner)
{
_camera.GetComponent<Camera>().enabled = false;
_camera.GetComponent<CinemachineBrain>().enabled = false;
_camera.GetComponent<AudioListener>().enabled = false;
_camera.GetComponent<Camera>().enabled = false;
_cmCam.GetComponent<CinemachineCamera>().enabled = false;
_vol.GetComponent<Volume>().enabled = false;
_ui.GetComponent<Canvas>().enabled = false;
}
}
private IEnumerator RegisterWithTeamManager()
{
// Wait until TeamManager is ready
while (TeamManager.Instance == null || !TeamManager.Instance.IsSpawned)
{
yield return null;
}
TeamManager.Instance.addPlayersToTeam(GetComponent<NetworkObject>().NetworkObjectId, DataPipe.teamNumber);
}
}
this is here i call it form
Same issues as a I described above. You're setting the NetworkVariable and NetworkList from the client side. These can only be set by the server by default.
but when the player joins i want to send it where should i send it from
and then also why is that from the host client i can see the values being updated
You either have to use an event that listens for when players join/connect that the server can subscribe to and add them to your TeamManager or you can have the client send an RPC to the server to request they be added.
because the host is the server.
so a serverRPC in the same script as i shown
private IEnumerator RegisterWithTeamManager()
{
// Wait until TeamManager is ready
while (TeamManager.Instance == null || !TeamManager.Instance.IsSpawned)
{
yield return null;
}
AddPlayerServerRpc();
}
[ServerRpc]
void AddPlayerServerRpc()
{
TeamManager.Instance.addPlayersToTeam(GetComponent<NetworkObject>().NetworkObjectId, DataPipe.teamNumber);
}
No Luck
You will probably have to debug some of your own systems. But as far as a client requesting the server to set a NetworkVariable, it really is as simple as sending an RPC to the server for them to set the value. Simple example here:
But the data that is written by the host itself isn't being shown on the client either
When the host joins it makes the count to 1
When player joins it should atleast have a count of 1
for the NetworkList or the NetworkVariable?
Both
I don't think the way you're changing the variables triggers a sync automatically. You may have to call .SetDirty(true); on both after you make changes to them.
That's different.
NetworkVariable with simple types is a lot different than NetworkList or a NetworkVariable that is a collection like a Dictionary.
client
host
public void addPlayersToTeam(ulong playerRef, int teamNumber)
{
teamNumber--;
if (teamNumber > teams.Count) return;
if (teams[teamNumber].players.Length >= teams[teamNumber].maxPlayerCount) return;
teams[teamNumber].players.Add(playerRef);
teamMap.Value[playerRef] = teams[teamNumber];
teamMap.SetDirty(true);
teams.SetDirty(true);
if (IsServer) PlayerJoinClientRpc(playerRef, teamNumber);
}
When/where are you debugging these values?
each log comes from respective clients
I meant in terms of your scripts.
[ServerRpc]
private void FireServerRpc(Vector3 origin, Vector3 direction)
{
if (Physics.Raycast(origin, direction, out RaycastHit hit, gunItem.range))
{
if (hit.collider.TryGetComponent(out Health health))
{
PlayerMoment isPlayer = health.GetComponent<PlayerMoment>();
if (
isPlayer && !TeamManager.Instance.friendlyFire &&
TeamManager.Instance.inTeam
(transform.parent.GetComponent<NetworkObject>().NetworkObjectId,
hit.collider.transform.parent.GetComponent<NetworkObject>().NetworkObjectId)
) return;
health.damage(gunItem.bulletDamage);
}
SpawnHitMarkerClientRpc(hit.point);
}
}
[ClientRpc]
private void SpawnHitMarkerClientRpc(Vector3 hitPoint)
{
Debug.Log(TeamManager.Instance.teams.Count);
foreach (TeamManager.Team team in TeamManager.Instance.teams)
{
foreach (ulong player in team.players)
{
Debug.Log(player);
}
}
if (hitMarkerPrefab == null) return;
GameObject marker = Instantiate(hitMarkerPrefab, hitPoint, Quaternion.identity);
Destroy(marker, hitMarkerDuration);
}
its a whole other script
Not entirely sure what's going on. Hard to say without the project in front of me. Best thing I can recommend is going in to an empty single scene and just testing out NetworkList and NetworkVariable<Dictionary>
should i share the gitrepo?
No thanks, that's alright.
With network variable collections like Dictionary or List, you have to call .CheckDirtyState() after making any changes
https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.6/manual/basics/networkvariable.html#using-collections-with-networkvariables
You'll also want to subscribe to each network variable's . OnValueChange event to get notified when they change.
there doesnt seem to be a CheckDiretyState for networklist?
NetworkList is not a NetworkVariable<List>
hmm let me try that ig
As long as the host/server is the one updating a NetworkList, it will sync to the clients. You'll need to sub to OnListChange event to get when the list gets updated to the clients
When you add it to what? The error says that whatever it was already been deallocated,
okay but do i need to reasign those variable i get from current?
public void addPlayersToTeam(ulong playerRef, int teamNumber)
{
teamNumber--;
if (teamNumber > teams.Count) return;
if (teams[teamNumber].players.Length >= teams[teamNumber].maxPlayerCount) return;
teams[teamNumber].players.Add(playerRef);
teamMap.Value[playerRef] = teams[teamNumber];
// teamMap.CheckDirtyState();
if (IsServer) PlayerJoinClientRpc(teamNumber);
}
here if i uncomment it
i get the error
On the clients, no.
Make sure this is only ever running on the server
but then why do i even need that i just send a serverrpc on player join and change the var on the server
The server is the one that has to call CheckDirtyState
public void addPlayersToTeam(ulong playerRef, int teamNumber)
{
teamNumber--;
if (teamNumber > teams.Count) return;
if (teams[teamNumber].players.Length >= teams[teamNumber].maxPlayerCount) return;
teams[teamNumber].players.Add(playerRef);
teamMap.Value[playerRef] = teams[teamNumber];
if (IsServer) teamMap.CheckDirtyState();
if (IsServer) PlayerJoinClientRpc(teamNumber);
}
still the same result
No, I mean this entire function should only be run on the server
Its only called here
private IEnumerator RegisterWithTeamManager()
{
// Wait until TeamManager is ready
while (TeamManager.Instance == null || !TeamManager.Instance.IsSpawned)
{
yield return null;
}
AddPlayerServerRpc();
}
[ServerRpc]
void AddPlayerServerRpc()
{
TeamManager.Instance.addPlayersToTeam(GetComponent<NetworkObject>().NetworkObjectId, DataPipe.teamNumber);
}
}