So I’m making a multiplayer card game, based in Triple Triad using Netcode. I have a Card NetworkBehaviour with an attribute called IsBlue, which determines the color of the background for the card (and player currently owning the card)
public class Card : Interactible //Interacbile is a NetworkBehaviour
{
...
public NetworkVariable<bool> IsBlue = new NetworkVariable<bool>(false);
...
void Update()
{
if (IsChangingSides.Value)
{
ChangeSides();
}
}
....
public override void OnNetworkSpawn()
{
CardName.OnValueChanged += (FixedString64Bytes previousValue, FixedString64Bytes newValue) => { ChangeCardMaterial(); };
IsBlue.OnValueChanged += (bool previousValue, bool newValue) =>
{
Debug.Log("Changed Color!");
ChangeCardMaterial();
};
...
private void ChangeSides()
{
....
ChangeColorClientRpc(!IsBlue.Value);
IsChangingSides.Value = false;
RevealCardClientRpc();
}
...
[ClientRpc]
public void ChangeColorClientRpc(bool isBlue)
{
Debug.Log(name);
IsBlue.Value = isBlue;
ChangeCardMaterial();
}
....
}
When I first start the game, I randomly decide which player will be the first one and change the value of their IsBlue variable individually inside the server, then I register a listener for the OnValueChanged event, which updates the material for each card. This is working like a charm
public class GameController : NetworkBehaviour
{
...
public Hand[] PlayerHands;
...
private void SetupCards()
{
foreach (Hand playerHand in PlayerHands)
{
foreach (Card card in playerHand.cards)
{
...
card.IsBlue = card.OwningPlayer.IsBlue;
...
}
}
}
...
}
Now, when playing, after a player makes a move and takes the enemy’s card, the card is supposed to change colors, but when I change the IsBlue value for the card, it changes on all of the other cards too! wht’s worse, the OnValueChanged listener for the variable is never called!
public class Player : NetworkBehaviour
{
...
//This is the entry point for players using their card, this triggers ther est of the process
[ServerRpc(RequireOwnership = false)]
public void SelectInteractibleServerRpc(NetworkObjectReference interactibleNetworkReference,
ServerRpcParams serverRpcParams = default)
{
NetworkObject rawInteractible;
bool couldFetchIteractible = interactibleNetworkReference.TryGet(out rawInteractible);
if (couldFetchIteractible)
{
Interactible interactible = rawInteractible.gameObject.GetComponent<Interactible>();
if (IsPlaying.Value && (rawInteractible.OwnerClientId == serverRpcParams.Receive.SenderClientId || interactible is BoardSlot))
{
...
interactible.ToggleSelect();
....
}
...
}
...
}
....
}
public class BoardSlot : Interactible //Interacbile is a NetworkBehaviour
{
private Card OccupyingCard;
public BoardSlot TopSlot;
...
private void CalculateMove()
{
if (TopSlot != null && TopSlot.OccupyingCard != null && TopSlot.OccupyingCard.BottomValue.Value < OccupyingCard.TopValue.Value && TopSlot.OccupyingCard.IsBlue.Value != OccupyingCard.IsBlue.Value)
{
TopSlot.OccupyingCard.IsChangingSides.Value = true;
Debug.Log("Brute Force Taken!");
}
...
}
As a footnote, I am now changing the value inside an RPC because, as mentioned above, when I tried changing it inside the server itself, it was just changing the value for the variable for all Card NetworkObjects in scene, never calling the listener so the materials where never updating. I decided to create a ClientRpc and manually chagne the material, but the issue of all cards having their NetworkVariable changed at the same time persisted when I change the variable inside the ClientRpc
Am I doing something wrong? Or am I just the unluckiest person in the world to stumble upon two bugs at the same time? Help please