Hello,
I’m having trouble using Actions for my multiplayer game.
I have a shop, on item purchased I want to invoke a unity Action so my other classes can do their job on item purchased. Before confirming the purchase, I ask the server if the player has enough money, since Rpc’s always return void, I’m using a bool NetworkVariable (HasPlayerEnoughMoney) , which the server sets to true if the player has enough money. If the player has enough money, I send an Action OnItemPurchased. Issue is : I subscribe to this HasPlayerEnoughMoney.OnValueChanged and OnItemPurchased with every player. So for some reason when the host buys an item, it deducts money from other players too. (clients buying doesn’t take money from server) BUT, replacing the OnItemPurchased Action invoke by simple functions calls, works. no issues.
Here are the simple methods : Both scripts are on a player → if we have 2 players, each script will be read 4 times here (owner+copy on both sides.)
private void OnEnable()
{
// HasPlayerEnoughMoney is the bool NetworkVariable which the server sets to true if player has enough money
playerMoneyHandler.HasPlayerEnoughMoney.OnValueChanged += AllowPurchase;
}
private void OnDisable()
{
playerMoneyHandler.HasPlayerEnoughMoney.OnValueChanged -= AllowPurchase;
}
private void AllowPurchase(bool oldValue, bool newValue)
{
if (!IsOwner) { return; }
// IF ENOUGH MONEY TO BUY
if (newValue)
{
// THIS IS THE ISSUE : all players access this section ?? and call action on their side ?
ActionsPlayer.OnItemPurchased?.Invoke(lastCollectibleConsidered); // ISSUE
// SIMPLE FUNCTION CALLS : SOLUTION
//playerMoneyHandler.AddMoney(-lastCollectibleConsidered.CollectibleValue);
//playerMagickHandling.AddMojosRecievedOnCollecting(lastCollectibleConsidered);
//playerInventoryManager.AddCollectibleInInventory(lastCollectibleConsidered);
//playerAbilitiesHandler.AddCollectedScroll(lastCollectibleConsidered);
}
else
{
if (Debug.isDebugBuild) { print("NOT ENOUGH MONEY : "); }
}
}
// INPUT : left mouse click -> confirm buy
private void PlayerWantsToConfirmBuy(InputAction.CallbackContext callbackContext)
{
// SETS NETWORKVARIABLE VALUE TO TRUE IF PLAYER HAS ENOUGH MONEY
if (IsOwner) playerMoneyHandler.HasPlayerEnoughMoneyToBuy(lastCollectibleConsidered.CollectibleValue);
}
this is for example one of the methods that subscribes to OnItemPurchased :
private void OnEnable()
{
Money.OnValueChanged += OnMoneyChanged;
ActionsPlayer.OnItemPurchased+= PayCollectibleValue;
}
private void OnDisable()
{
Money.OnValueChanged -= OnMoneyChanged;
ActionsPlayer.OnItemPurchased-= PayCollectibleValue;
private void AddMoney_Network(float amount)
{
if (Money.Value + amount <= 0.0f) { Money.Value = 0.0f; }
else { Money.Value += amount; }
}
public void AddMoney(float amount)
{
if (IsServer)
{
AddMoney_Network(amount);
}
else
{
if (IsOwner) ManageMoneyOnServerRpc(amount, 1);
}
}
private void PayCollectibleValue(CollectibleScriptableObject collectible)
{
AddMoney(-collectible.CollectibleValue);
}
}
Can someone tell me what I’m doing wrong here please ? I would prefer using actions so I don’t have to make my methods public. Also I don’t understand how the action is been called from 2 different players since I use an input to ask the server if the player has enough money. Input should be read only on the owner player since the copy doesn’t recieve inputs ? Thanks in advance.