Displaying a gameobject to only certain players

Options
I am trying to display a death message to the player who died and the player who killed them.

To do this I am using PunRPC called from the player who died.

The problem is that while the player who died sees the death message, the player who killed them does not.

// Called with the player dies.
void Die ()
{
    // killByName is the nickname of the player who killed the local player.
    // killedById is the ViewID of the player who killed the local player.
    photonView.RPC(nameof(UpdateDeathText), RpcTarget.All, killedByName, killedById, deathMessage);
}

// Enables the death text. Only visible to the local player and the player who killed them.
[PunRPC]
void UpdateDeathText (string killedByName, int killedById, string deathMessage)
{
    healthBarSprite.parent.gameObject.SetActive(false);

    if (photonView.IsMine) // Local player.
    {
        deathText.gameObject.SetActive(true);
        deathText.text = "<color=#D4CBCC>Killed by " + killedByName + "!</color>";
    }
    else if (killedById == photonView.ViewID) // Player who killed the local player.
    {
        deathText.gameObject.SetActive(true);
        deathText.text = deathMessage;
    }
   // Else we do nothing as the player is not relevant.
}

To my understanding a RPC is called on all players on the network. I got this code working by comparing local players nickname with the nickname of the player who got the kill, but this was only for testing as that style of code would cause problems if two players in the room had the same nickname.

Am I approaching this problem wrong, or am I missing something?

Thanks,
Wzd.

Comments

  • Wzd
    Wzd
    edited September 2020
    Options
    I managed to solve my problem. I'm a little tired right now so my solution might not be the best, but I don't want to waste anyone's time answering this question as I've fixed the problem and my code might be helpful for someone in the future.

    Basically the 'else if' part of my code was all wrong. I needed to use an RPC.

    Do do so, I made the UpdateDeathText into a normal method and created a new RPC method called UpdateDeathTextForPlayerWhoKilled. I then called that RPC from the player who died on the player who got the kill's PlayerHealthController script. Hope that makes sense. Basically I split up my original method and called the new RPC from the local player on the network player.

    The new code looks like this:
    // Enables the death text. Only visible to the local player and the player who killed them.
    void UpdateDeathText (string killedByName, GameObject killedByGameObject, string deathMessage)
    {
        healthBarSprite.parent.gameObject.SetActive(false);
    
        if (photonView.IsMine) // Called on the local player
        {
            deathText.gameObject.SetActive(true);
            deathText.text = "<color=#D4CBCC>Killed by " + killedByName + "!</color>";
        }
            
        // Only called on the player who killed the local player
        photonView.RPC(nameof(UpdateDeathTextForPlayerWhoKilled), killedByGameObject.GetComponent<PhotonView>().Owner, deathMessage);
    
        // Else we do nothing as the player is not relevant.
    }
    
    [PunRPC]
    void UpdateDeathTextForPlayerWhoKilled (string deathMessage)
    {
        healthBarSprite.parent.gameObject.SetActive(false);
    
        deathText.gameObject.SetActive(true);
        deathText.text = deathMessage;
    }
    

    The killedByGameObject is retrieved by finding the gameobject in the scene which matches the view id I passed into the original Die() method.
    GameObject killedByGameObject = PhotonView.Find(killedById).gameObject;
    

    I found these two posts helpful in solving my problem:

    - Finding an item by its photon id
    - tl;dr: "To find a photon view by the id you can use PhotonView.Find(x); (x is the id, an integer). That returns the value of the photon view. To find the game object just add a .gameObject after (x)" - Chubysnow.

    -Photon (PUN) How do I get another gameobjects photon player?
    - tl;dr: Use theGameObjectYouWant.GetComponent<PhotonView> ().owner to get the 'Player' component of the gameobject. You can then pass this into an RPC as the target, causing the RPC to only be called on that gameobject.

    As I said at the start, this solution probably isn't perfect but I don't want to waste anyone's time on a solved problem. If my code or resources can help anyone out in the future that's awesome :D.

    ---

    Ok just a small edit now I'm no longer half asleep.

    - The 'if' check is irrelevant as UpdateDeathText() is now only being called on the local player.
    - I added another RPC to disable the health bar and called this for all players as thats something everyone needs to do.
    - I replaced the GameObject parameter with a Player one because I also get the PhotonView().owner of that gameobject somewhere else, do it just makes sense. If you do this make sure to use the using Photon.Realtime directive.