Cypher Networking

So after all the assets were created, now came the meat of the problems- the interesting bits I was itching to learn and solve. I needed to take everything and work it out to be a multiplayer game somehow both sounded simple and incredibly hard in my head. I had set up the project with PhotonPun2 and their stuff from the very beginning so there weren’t any setup problems as per se. The biggest goal setting out was getting a session, a room setup, and then getting two players to be able to see each other on the same screen. Thankfully given Unity’s situation with refactoring their networking API, there was an abundant resource of networking tutorials both on sites like Udemy, and on youtube. Photon has some amazing things it can do with its callbacks!

To start, since I just wanted to make sure things would work in the sandbox, I bypassed doing the “create a room” bit and went straight to enter a shared world/lobby, and surprisingly it worked out pretty well. Getting photon to recognize Eaglor and Bonaparte as player characters was a breeze with their pre-setup scripts, and also getting Photon to sync animation was as simple as a checkbox ticked. The first thing I noted that I needed to fix was that I was able to control the enemy player (oops). I needed to find a way of assigning a client to a single character, and Photon made it incredibly easy to do so with their given API. I essentially made a setup/bring up a script for each character and attached it to them. This script checked whether the player’s character was controlled by the client’s view. If it wasn’t, it would disable the suspect scripts that were enabling one client to control another. It kind of looked like this:

if (photonView.IsMine) 
{
        gameObject.GetComponent<UnityComponentHere>.enabled = true;

}

else 
{
    gameObject.GetComponent<UnityComponentHere>.enabled = false;
}

In other words, each player obviously was different. Assigning a photon view component to an object kept track of which player “owned” that specific game object. I could compare and see if that object was controlled by me and enable it to be used on level start! So after this, I decided that this test of seeing whether things would work went somewhat swimmingly. Remembering that I somewhat hacked together the lobby and room creation aspect of the game, I went ahead and did it right. I made it such that players can create their rooms, join and exit them, and along with that the UI would respond appropriately letting the player know what was going on.

The one thing you might have noticed that I missed was the team selections and team play aspect of the game. After making the lobby and room selection scenes and testing it so that players can join rooms and enter them to play the game, I decided to add a team element to the game. To do this, I made use of Photon’s Photon.Pun.Utility script since it already had some good looking tools for separating players into teams. I just had to make sure my damage calculations first checked in with this (what I can only assume to be a custom property) value on the player before making any adjustments to things like health or shield values. I did have some interesting issues with it though- it never used to save the chosen team appropriately, sometimes it used to lose the appropriate team on scene exit and when loading the scene, so I ended up making a workaround by banging it in the head a second time on scene load and all was well after that.

Speaking of custom properties, I also had to do character selection. After all, we did have two characters to choose from! The utility script had already given me teams, but I needed a second custom property to keep track of which character the game scene had to load in for the player, so I made a second custom property inside the same team selection script. Simply put, the custom properties were a hashtable of key-value elements, I set the value on the menu side of the game. I simply retrieved my custom element in the game scene and instantiated the right prefab from the right client. It looked like this:

In Character Select Menu:

private ExitGames.Client.Photon.Hashtable _myCustomProperties = new ExitGames.Client.Photon.Hashtable();

public void SetPlayerTypeEaglor() {

    _myCustomProperties["CharacterType"] = "eaglor";
    PhotonNetwork.LocalPlayer.CustomProperties = _myCustomProperties;
    
}

In the Game Manager script (used for win conditions and instantiation of gameObjects):

if ((string)player.CustomProperties["CharacterType"] == "bonaparte" && Bonaparte != null) {

    if (player.GetTeam() == PunTeams.Team.blue)
    {

        PhotonNetwork.Instantiate(Bonaparte.name, bluespawn2.transform.position, Quaternion.identity);

    }

    if (player.GetTeam() == PunTeams.Team.red)
    {

        PhotonNetwork.Instantiate(Bonaparte.name, redspawn2.transform.position, Quaternion.identity);

    }
}

So, so far we have a pretty good, almost-working sandbox! The only issue right now is that whenever you pop an ability, nobody knows where the projectile (as an example) starts and stops. If forces both players to throw the projectile out! In our current state, if Eaglor shot an arrow, and it hit Bonaparte, Bonaparte wouldn’t know to take damage because it has disabled all of Eaglor’s scripts previously (remember photonView.IsMine). I used RPC functions to get the damage working right as well. RPC functions allow us to tell other clients to call a function/do something! Here’s an example of one.

On the definition side of things:

[PunRPC]
    public void TakeDamage(float _damage) {

        health -= _damage;

    }

How to actually use it:

void OnCollisionEnter(Collision col)
{
    col.gameObject.GetComponent<PhotonView>().RPC("TakeDamage", RpcTarget.AllBuffered, 30f);
}

Notice the RPC functions are decorated with the [PunRPC], it almost looks like something from Unreal in that regard. The decoration is so Photon knows what function is what and that it is infact an RPC function! The RpcTarget.AllBuffered part defines who calls this function!

And with that voila! I made some trailers for capstone that showed off the game since we didn’t have enough space there for playing a multiplayer game! Here is a link!

-Kshaya

Back to Top ↑

Updated: