#MultiScene setup

1 messages · Page 1 of 1 (latest)

olive pelican
#

How do i do stuff accross scenes like i have one lobby scene and there i want to add the host and join button once clicked it should be taken into another scene

olive pelican
#

also need to send some player and game info to the other scene as well

primal zinc
#

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.

vague bridge
#

I like using scriptable objects for cross scene data.
Another quick and super dirty option is to use Player Prefs.

olive pelican
#

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

vague bridge
#

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.

olive pelican
#

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

vague bridge
#

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>>

olive pelican
#

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

vague bridge
#

You can do NetworkVariable<Dictionary<>> as well. I believe the Key Values still have to be INetworkSerializable though

olive pelican
#

what if its my custom class

#

is there any docs on how to make your own classes NetworkSerializable

vague bridge
#

Technically you can make classes inherent from INetworkSerializable. But they won't work with Network Variables

olive pelican
#

Thanks

#

i think for the list i use

#

NetworkList<> ?

#

but i get this

vague bridge
olive pelican
#

it is

#

let me send the new codwe

vague bridge
olive pelican
#

i tried using new ()

#

doesnt seem to work

primal zinc
vague bridge
#

actually I don't think an array will work in a Network List

olive pelican
#

tbh i have never bothered using an array cuz there are no add and such funcs there would it still be fine?

olive pelican
#

let me try

#

didnt work

vague bridge
olive pelican
#

oh

#

wait thats a thing

#

first time hearing it

#

same issue

vague bridge
#

from the docs

olive pelican
#

is this safe tho?

vague bridge
#

its not unsafe. just unmanaged

olive pelican
#

as in

#

would there be a more cleaner way to do it?

vague bridge
#

NativeArray doesn't require any additional settings

olive pelican
#

but would u do something like this in prod?

#

also still didnt work

vague bridge
primal zinc
#

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

olive pelican
#

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

olive pelican
#

is it cuz of the already existing errors

#

okay just for the sake off it

#

imma see if arrays work

primal zinc
olive pelican
#

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

vague bridge
olive pelican
#

😭 notlikethis

#

why does it still not work

#

it doesnt recompile

primal zinc
olive pelican
#

let me try to restart

vague bridge
olive pelican
olive pelican
#

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>

vague bridge
#

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<>>

olive pelican
#

which shold i prefer tho?

#

also yea works now thanks a bunch

vague bridge
# olive pelican which shold i prefer tho?

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)

olive pelican
#

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

vague bridge
olive pelican
#

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?

olive pelican
#

why is the length of the list teams 0 on the client even tho i sync it accrss the server

olive pelican
#

this is the updated code

#

why are the variables not synced

olive pelican
#

okay i did a shitton of more debugging

#

the dict as well as the list both are not being syced notlikethis

primal zinc
olive pelican
#

and what bout the dict

#

that isnt synced either

primal zinc
primal zinc
# olive pelican and what bout the dict

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.

primal zinc
#

Yes, but also remove the initialization at declaration as well.

olive pelican
# primal zinc The whole purpose of NetworkVariable/NetworkList is that the Owner/Authority set...
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

primal zinc
olive pelican
#

and then also why is that from the host client i can see the values being updated

primal zinc
primal zinc
olive pelican
#
    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

primal zinc
#

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:

https://docs.unity3d.com/Packages/com.unity.netcode.gameobjects@2.6/manual/basics/networkvariable.html#onvaluechanged-example:~:text=[Rpc(SendTo.Server)] public void ToggleServerRpc() { // this will cause a replication over the network // and ultimately invoke `OnValueChanged` on receivers State.Value %3D !State.Value%3B }

olive pelican
#

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

primal zinc
#

for the NetworkList or the NetworkVariable?

olive pelican
#

Both

primal zinc
#

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.

olive pelican
#

Hmm I didn't need to do that for network variable int

#

But let me check

primal zinc
#

NetworkVariable with simple types is a lot different than NetworkList or a NetworkVariable that is a collection like a Dictionary.

olive pelican
#

client

#
    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);
    }
primal zinc
olive pelican
#

each log comes from respective clients

primal zinc
olive pelican
#
    [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

primal zinc
#

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>

olive pelican
#

should i share the gitrepo?

primal zinc
#

No thanks, that's alright.

vague bridge
#

You'll also want to subscribe to each network variable's . OnValueChange event to get notified when they change.

olive pelican
vague bridge
#

NetworkList is not a NetworkVariable<List>

olive pelican
#

hmm let me try that ig

vague bridge
#

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

olive pelican
#

okay it only happens when i add CheckDiretyState

vague bridge
olive pelican
olive pelican
#

here if i uncomment it

#

i get the error

vague bridge
vague bridge
olive pelican
#

but then why do i even need that i just send a serverrpc on player join and change the var on the server

vague bridge
#

The server is the one that has to call CheckDirtyState

olive pelican
# vague bridge Make sure this is only ever running on the server
    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

vague bridge
olive pelican
#

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);
    } 
}
vague bridge
#

Ok, then those IsServer checks are unnecessary.

#

I would remove the Singleton from TeamManager.

#

When the network object spawns Instance could get recreated