Why does OnTriggerEnter call on client and master

The whole answer can be found below.

Please note: The Photon forum is closed permanently. After many dedicated years of service we have made the decision to retire our forum and switch to read-only: we've saved the best to last! And we offer you support through these channels:

Try Our
Documentation

Please check if you can find an answer in our extensive documentation on PUN.

Join Us
on Discord

Meet and talk to our staff and the entire Photon-Community via Discord.

Read More on
Stack Overflow

Find more information on Stack Overflow (for Circle members only).

Write Us
an E-Mail

Feel free to send your question directly to our developers.

Why does OnTriggerEnter call on client and master

Distul
2017-06-26 06:36:54

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

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



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

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
2017-06-27 05:21:48

bumpity

[Deleted User]
2017-06-29 09:40:59

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
2017-06-30 20:05:34

@Christian_Simon wrote:

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();  
        if (photonView != null && photonView.isMine)  
            PlayerTracker.Instance.ModifyHealth(PhotonNetwork.player, -10);  
    }  

You have to check if the photonview hit on 'other' isMine.

Distul
2017-06-30 20:15:09

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 <= 0)  
                PlayerNetwork.Instance.PlayerDied(photonPlayer);  
        }  
    }  
Back to top