Why does OnTriggerEnter call on client and master

Options
Whenever I pass over a trigger with the code below fires as though both the client and master are passing over the trigger.

[code]
private void OnTriggerEnter(Collider other)
{
PlayerTracker.Instance.ModifyHealth(PhotonNetwork.player, -10);
}
[/code]

[code]
public void ModifyHealth(PhotonPlayer photonPlayer, int value)
{
PhotonView.RPC("RPC_ModifyHealth", PhotonTargets.MasterClient, photonPlayer, value);
}
[/code]

The trigger does not have a photonview attached. I would expect it to call ModifyHealth on the client which travels into it, which then calls RPC_ModifyHealth on the master passing in client as the PhotonPlayer. This does happen, the trigger is called again passing in the master as PhotonPlayer, even though the master is no where near the trigger.

Comments

  • Distul
    Options
    bumpity
  • Hi @Distul,

    in this case OnTriggerEnter is executed on each client and furthermore each client send the RPC to the MasterClient. According to the code snippet, this object has an attached PhotonView component, so you can add PhotonView.isMine condition at the beginning of the OnTriggerEnter function to avoid processing this callback on each client.
    private void OnTriggerEnter(Collider other)
    {
        if (!PhotonView.isMine)
            return;
    
        // do stuff
    }
  • Distul
    Options

    Hi @Distul,

    in this case OnTriggerEnter is executed on each client and furthermore each client send the RPC to the MasterClient. According to the code snippet, this object has an attached PhotonView component, so you can add PhotonView.isMine condition at the beginning of the OnTriggerEnter function to avoid processing this callback on each client.

    private void OnTriggerEnter(Collider other)
    {
        if (!PhotonView.isMine)
            return;
    
        // do stuff
    }
    This would not work. All objects placed in scene prior to runtime are owned by server. Thus the photonview will always be owned by server regardless of who passes over it.

    However, you sparked a realization in my head and I came up with the following which works.
    
        private void OnTriggerEnter(Collider other)
        {
            PhotonView photonView = other.GetComponent<PhotonView>();
            if (photonView != null && photonView.isMine)
                PlayerTracker.Instance.ModifyHealth(PhotonNetwork.player, -10);
        }
    
    You have to check if the photonview hit on 'other' isMine.
  • Distul
    Options
    But since you want to of course remain authoritative, this would be the proper way of doing it.
    
        private void OnTriggerEnter(Collider other)
        {
            if (!PhotonNetwork.isMasterClient)
                return;
    
            PhotonView photonView = other.GetComponent();
            if (photonView != null)
                PlayerTracker.Instance.ModifyHealth2(photonView.owner, -10);
        }
    
    Then, where as PlayerStats is a collection of each players PhotonPlayer and associated stats for that player.
    
        public void ModifyHealth2(PhotonPlayer photonPlayer, int value)
        {
            int index = PlayerStats.FindIndex(x => x.PhotonPlayer == photonPlayer);
            if (index != -1)
            {
                PlayerStats playerStats = PlayerStats[index];
                playerStats.Health += value;
                if (playerStats.Health