#player info syncing

1 messages · Page 1 of 1 (latest)

golden mirage
#

are you using Network Variables or RPCs to send the client selections?

full raft
#

network variables

#

everything is done in the OnClientConnected method

#

i use playerprefs

#

for the character prefab

#

and the name

#
GameObject player = Instantiate(characterButtonHandler.Prefabs[PlayerPrefs.GetInt("prefabIndex")].characterPrefab);
#

It works on my computer locally

#

no matter how many clients i have

#

but for connections from the outside it doesnt

golden mirage
#

player prefs are only stored locally. the server will have no idea what the remote player prefab or name are

full raft
#

the Prefabs array is local

#

and the prefab index is also locally stored via playerprefs

golden mirage
#

the server will still need to know what is getting spawned. At the very least an array index will need to be sent over the network

full raft
#

how would i implement that?

golden mirage
#

I have a client send a RPC with the index of the character to spawn

full raft
#

yikes

#

seems harder than said, atleast here in my code

verbal geode
#

@full raft why don't you have each client set their own info?

golden mirage
#

You can use a network variable with owner write permissions

#

just depends on when you are setting those variables

full raft
verbal geode
#

a name string?

#

What else

full raft
#

prefabIndex and username which are set in playerprefs

#

string and int

verbal geode
#

Why are you using playerprefs again?

full raft
#

the character selection menu is a different menu , you select your character then you go into the join menu

#

so i need it locally saved till the server needs it

#

so the character selection itself has nothing to do with the server

#

all the server needs is the index

#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class CharacterButtonHandler : MonoBehaviour
{
    [SerializeField]private List<Button> characterButtons = new List<Button>();
    [SerializeField] public List<Character> Prefabs = new List<Character>();
    [SerializeField] private GameObject[] takenUI = null;
    [SerializeField] public JoinMenu joinMenu = null;
    [SerializeField] GameObject MainMenu = null;
    public Animator animator;
    private void Start()
    {
        animator = GetComponent<Animator>();
        foreach (Button button in characterButtons)
        {
            button.onClick.AddListener(() => joinMenu.SetPlayerGameObject(characterButtons.IndexOf(button)));
            button.onClick.AddListener(() => SetButtonTaken(characterButtons.IndexOf(button)));
        }
    }

    private void SetButtonTaken(int index)
    {
        foreach(Button button in characterButtons)
        {
            takenUI[characterButtons.IndexOf(button)].SetActive(false);
        }
        takenUI[index].SetActive(true);
    }

    private void Awake()
    {
        SetButtonTaken(PlayerPrefs.GetInt("prefabIndex",0));
    }

    public void InitiateAnimationReturn()
    {
        
        animator.SetBool("Return", true);
        MainMenu.SetActive(true);
    }
    public void DisableMenu()
    {
        animator.SetBool("Return", false);
       
        gameObject.SetActive(false);
    }

}


#

everything here is local

verbal geode
#

Fair enough as a solution

#

but all the more reason for each client to sync their own info

#

If clients are setting their info offline, no reason for the server to have to retrieve and sync that

#

will save you a lot of headache if each client just syncs their own stuff, less calls

full raft
#

Yeah i mean i'd need to give the OnClientConnected method extra parameters and just do the playerprefs.get stuff befotehand and then pass it to that method

verbal geode
#

for clients to sync their info?

full raft
#

Only issue is im using the onclientconnected callback aswell for this to work

full raft
#

i can do
PlayerPrefs.GetString("username")
PlayerPrefs.GetInt("prefabIndex")
in the HostOrConnect function

#

so it gets called locally

#

but then i'd need to keep passing on these values

#

and since i use callbacks

#

no idea how i would do so

verbal geode
#

Make username and prefabIndex NetworkVariables

#

on your player script

golden mirage
#

if you are selecting character after connecting to the host then it would be way easier to use network variables

full raft
#

player name already is

#
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.Networking;
using Unity.Netcode;
using TMPro;
using UnityEditor;
using Unity.Netcode.Transports.UTP;
using Unity.Collections;
using System;

public class DisplayPlayerName : Unity.Netcode.NetworkBehaviour
{
    public NetworkVariable<NetPlayerName> PlayerName = new NetworkVariable<NetPlayerName>(new NetPlayerName() { username = "" });

    public override void OnNetworkSpawn()
    {
        Debug.Log("Spawned");
        base.OnNetworkSpawn();

        if (IsServer)
        {
            PlayerName.OnValueChanged += OnPlayerNameChanged;
            string username = PlayerPrefs.GetString("username");
            PlayerName.Value = new NetPlayerName() { username = username };
        }
        UpdatePlayerNameUI(PlayerName.Value.username.ToString());
    }

    private void OnPlayerNameChanged(NetPlayerName previousValue, NetPlayerName newValue)
    {
        Debug.Log($"Player {OwnerClientId} changed name from {previousValue.username} to {newValue.username}");
        UpdatePlayerNameUI(newValue.username.ToString());
    }

    public void SetPlayerName(string name)
    {
        if (IsServer)
        {
            PlayerName.Value = new NetPlayerName() { username = name };
        }
    }

    private void UpdatePlayerNameUI(string name)
    {
        GetComponentInChildren<TMP_Text>().text = name;
    }
}

public struct NetPlayerName : INetworkSerializable, System.IEquatable<NetPlayerName>
{
    public FixedString64Bytes username;

    public bool Equals(NetPlayerName other)
    {
        return username.Equals(other.username);
    }

    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref username);
    }
}

#

this is for the player tag

#

and im seeing just now, i also used player prefs here

#

which probably wouldn't work

#

man i don't know, im lost, lol.

golden mirage
#

that will work fine. you have to set the network variable to owner write permissions

#

You can also simplify that with NetworkVariable<FixedString64Bytes> PlayerName = new(writePerm: NetworkVariableWritePermission.Owner);

verbal geode
#

I think you just need to forget about PlayerPrefs after Networking starts as well, it's the root of the problem with your info getting mixed up

#

Just have each player set their info to PlayerPrefs offline in the menu, and when they join assign the info from PlayerPrefs to two NetworkVariables

#

and then forget about PlayerPrefs

#

because you have NetworkVariables syncing your info for that player

golden mirage
#

I would only use player prefs if you need it to persist offline or between scenes.