Change the material of a random player in the room?

Options

Hi, I'm currently working on a game and for one of the game-modes one player at random should be chosen to be infected and their material should change to another material that I already have made.

I've already tried getting an integer from a random range between 0 and the amount of connected players and then applying the material change to the result but this didn't work and just changed everyone's material to the Infected material.

The way I'm trying to change the material is by first targeting the parent of the actual player and then getting the mesh-renderer component in it's children and then setting the material to the infected material.

transform.GetComponentInChildren<MeshRenderer>().material = infected;

This script is applied to the parent therefore I can just use transform.

I also want these changes to be seen by other players which is why I'm running it through a RPC call that is targeting all players. Here is my code so far.

Note: CheckForButtonRun(); is being called in my Start function. And it is only meant to check if were in the right game-mode before choosing an infected player.

public void CheckForButtonRun() 
 {

    Scene currentScene = SceneManager.GetActiveScene();

    string sceneName = currentScene.name;




    if (sceneName == "Main")

    {

      checkforMaster();

    }

  }




  public void checkforMaster()

  {

    if (PhotonNetwork.IsMasterClient)

    {

      pickInfected();

    }

  }




  public void pickInfected()

  {

    whichPlayerIsInfected = Random.Range(1, PhotonNetwork.CurrentRoom.PlayerCount);

    PV.RPC("RPC_syncInfected", RpcTarget.All, whichPlayerIsInfected);

    Debug.Log("Infected is " + whichPlayerIsInfected);

  }




  [PunRPC]

  public void RPC_syncInfected(int playerNumber)

  {

    whichPlayerIsInfected = playerNumber;

    becomeInfected(whichPlayerIsInfected);

  }




  public void OnPhotonSerializeView(PhotonStream stream, PhotonMessageInfo info)

  {

    if (stream.IsWriting)

    {

      stream.SendNext(isInfected);

    }

    else

    {

      this.isInfected = (bool)stream.ReceiveNext();

    }

  }




  public void becomeInfected(int infectedNumber)

  {

    if (PhotonNetwork.LocalPlayer == PhotonNetwork.PlayerList[infectedNumber])

    {

      isInfected = true;

      transform.GetComponentInChildren<SkinnedMeshRenderer>().material = infected;

    }

  }

 

Best Answers

  • devonlively
    edited December 2021 Answer ✓
    Options

    "used for like storing a players total kills and deaths?"


    Yes, that is a use-case. you can use it to store other information such as who is infected; I don't believe it's stored in the registry. If you set it at the beginning of every match, that shouldn't matter in your use case.


    If you did want to store some information, you could simply save it to playerprefs (or whatever saving method you use) and then when the game loads, you just store the saved info into the hashtable for later use.


    Note: Don't use a hashtable in an update. this should be accessed on a single frame use basis otherwise you may overload your banwidth.

  • lafe
    lafe
    Answer ✓
    Options

    To put it simply what I did was get a random int from 1 to PhotonNetwork.PlayerList.Length so I have the number of players in the room and then whatever the random int that I got was who I would infect. From there I just ran an rpc function that targeted all the players (this rpc function was inside of a if PV.IsMine statement and then changed the material inside of that function.

    On some occasions no one would get infected (No-ones material was changed), to fix this I simply made a bool that turns true when the material change function is called and if it never becomes true in the update function I made an if statement where if that bool isn't true run it again until someone is infected.

    There is probably a way better way to do this than I did but it's all I could find.

Answers

  • Try using a hashtable instead of rpc-ing information around. a hashtable is basically like storage that transfers between scenes, and is not lost from memory until you remove it (for the most part)

  • lafe
    Options


    Wouldn't a hash-table be used for like storing a players total kills and deaths? I'm not trying to choose an infected player and then they are always infected every time. I just want to get a random player and make them infected. A new player is chosen and infected every time the game-mode is started.

  • devonlively
    edited December 2021 Answer ✓
    Options

    "used for like storing a players total kills and deaths?"


    Yes, that is a use-case. you can use it to store other information such as who is infected; I don't believe it's stored in the registry. If you set it at the beginning of every match, that shouldn't matter in your use case.


    If you did want to store some information, you could simply save it to playerprefs (or whatever saving method you use) and then when the game loads, you just store the saved info into the hashtable for later use.


    Note: Don't use a hashtable in an update. this should be accessed on a single frame use basis otherwise you may overload your banwidth.

  • lafe
    Options

    Seems like that would work but I found a solution already. Thanks for the help man.

  • Tobias
    Options

    Feel invited to post the answer to your own question.

  • Yes, I would love to hear how you accomplished it too.

  • lafe
    lafe
    Answer ✓
    Options

    To put it simply what I did was get a random int from 1 to PhotonNetwork.PlayerList.Length so I have the number of players in the room and then whatever the random int that I got was who I would infect. From there I just ran an rpc function that targeted all the players (this rpc function was inside of a if PV.IsMine statement and then changed the material inside of that function.

    On some occasions no one would get infected (No-ones material was changed), to fix this I simply made a bool that turns true when the material change function is called and if it never becomes true in the update function I made an if statement where if that bool isn't true run it again until someone is infected.

    There is probably a way better way to do this than I did but it's all I could find.