Row, The Boat

Online multiplayer rowing game.

1
2

This game was created in a small Game Jam we had at school.

Concepting
We had to create a mobile game that had to have more input than just the regular tapping and tilting. We had a small brainstorm session and eventually somebody came up with the idea to make a game where you had to row a boat with your phone.
This was well received and we started working the concept out a little more. After it was more clear what everyone had to do we started working on the game.

Developing
Eventually we had alot of things working including the movement with the phone and used Unity Networking for the multiplayer, however you had to fill in an IP address to connect to. This is not very convenient for people who are on their phone so we had to try something else. We looked at Photon Networking, which I already had a little experience on and thought it was doable to create what we had with the Photon framework. It was alot tougher than we hoped it would be, but eventually we got things working.

Current situation
After the Game Jam was over we kept working on the project and still continue to do so. We still have great plans to also enable alot of players to join one room and all row in a viking ship together.


Reflecting
I found it pretty challenging to create this multiplayer game, because of the way objects existed on both clients and some scripts had to be disabled or other people could control your character. However I did enjoy tackling this problem a whole lot.
When a player connects

    public override void OnPhotonPlayerConnected(PhotonPlayer player)
    {
        Debug.Log("Player connected");
        if (!PhotonNetwork.isMasterClient) return;
        this.Invoke("WaitForFirstPlayer", 5);
        if (this._boot.Paddles == null || this._boot.Paddles.Count == 0)
        {
            // TODO: Send RPC to client.
            Debug.Log("No Paddles avaiable bro");
            return;
        }
        Debug.Log("Spawn");
        Paddle paddleToAssign = this._boot.NextPaddle;
        GameObject spawnedPlayer = PhotonNetwork.Instantiate("Roeier", paddleToAssign.transform.position, Quaternion.identity, 0);
        spawnedPlayer.transform.SetParent(this._boot.transform);
        this._boot.AssignPlayer(spawnedPlayer.GetComponent<PhotonRoeier>());
        spawnedPlayer.transform.position = paddleToAssign.transform.position;
        PhotonView tempPlayerView = spawnedPlayer.GetPhotonView();
        PhotonView tempPaddleView = paddleToAssign.gameObject.GetPhotonView();
            
        this.photonView.RPC("AssignPaddle", player, tempPlayerView.viewID, tempPaddleView.viewID, (int)tempPaddleView.GetComponent<Paddle>().RowSide);
    }
This RPC call is then received by the connecting client on the same GameObject and sets the PaddleViewId in the PhotonRoeier script so that the method Roei(float force) actually sends the AddForce RPC call to the Master client.
    /// <summary>
    /// Called on connecting client
    /// </summary>
    [PunRPC]
    public void AssignPaddle(int playerID, int paddleID, int rowside)
    {
        Debug.Log("assigning paddle");
        PhotonRoeier myPlayer = PhotonView.Find(playerID).gameObject.GetComponent<PhotonRoeier>();
        this._roeiButtonHandler.Roeier = myPlayer;
        myPlayer.PaddleViewId = paddleID;
        myPlayer.Side = (RowTiltController.RowSide)rowside;
    }
    public void Roei(float force)
    {
        if (this.PaddleViewId == 0) return;
        this._paddleSoundController.PlayRandomPaddleSound ();
        this._targetRPC.RPC("AddForce", PhotonTargets.MasterClient, this.PaddleViewId, force);
    }
    [PunRPC]
    public void AddForce(int paddleViewId, float force)
    {
        Paddle paddle = PhotonView.Find(paddleViewId).GetComponent<Paddle>();
        this._boot.AddForce(paddle.transform.position, force);
    }
As you can see we used Unity Physics with a Rigidbody to move our boat. This was done, because it was really easy to implement and it made it alot more realistic than having to manually write an algorithm that looks at the position of the player who is rowing and applying the correct force. The Paddle is a child of the boat, so the position of the Paddle always stays at the same position from the boat.

Click here to play with the Unity Webplayer.

Note: Unity Webplayer does not work on Google Chrome.

Click here to play with WebGL.

Note: Networking games will perform worse on WebGL.