Grapple Battle is a 3D first-person online multiplayer 1v1 PvP game. You fight on floating islands above a void with swords, grappling hooks, and shurikens.
I always wanted to make a multiplayer PvP game. This is a personal project I made mostly for myself since this is the type of game I would enjoy.
I had quite some time, but a lot got lost in game design, tech design, and playtests.
This project was a lot of fun to make, and I am happy with the final product.
Since this is a solo project, I made everything except for some art, which I got from the Unity asset store. And the sounds that I got from royalty-free audio websites.
This is the first time I made online multiplayer. I used Photon PUN 2 for this, and it was very challenging yet fun, and the multiplayer is what I am most happy with.
Made with - Unity, C#, Photon PUN 2
Released - 11 April 2025
9 week solo project
public class NetworkManager : MonoBehaviourPunCallbacks
{
public CanvasGroup m_MenuUI;
public GameObject m_ConnectingObj;
void Start()
{
m_MenuUI.interactable = false;
m_ConnectingObj.SetActive(true);
// Connecting to the server
if (!PhotonNetwork.IsConnectedAndReady)
{
PhotonNetwork.ConnectUsingSettings();
// Only connect games with the same version
PhotonNetwork.GameVersion = "1.0";
}
else
{
m_MenuUI.interactable = true;
m_ConnectingObj.SetActive(false);
}
}
public override void OnConnectedToMaster()
{
base.OnConnectedToMaster();
m_MenuUI.interactable = true;
m_ConnectingObj.SetActive(false);
}
// Hosting a room with max 2 players
public void CreateRoom()
{
PhotonNetwork.CreateRoom("GameRoom", new Photon.Realtime.RoomOptions() { MaxPlayers = 2 });
}
public override void OnCreatedRoom()
{
base.OnCreatedRoom();
// If the room is made we go to the game view
// Since we are the host we can just use the normak "LoadScene"
SceneManager.LoadScene("Game");
}
// Joining a room
public void JoinRoom()
{
AudioManager.m_Instance.Play("Click");
// Find an existing room, if no rooms exist make one
m_MenuUI.interactable = true;
m_ConnectingObj.SetActive(false);
PhotonNetwork.JoinOrCreateRoom("GameRoom", new Photon.Realtime.RoomOptions() { MaxPlayers = 2 }, null);
}
public override void OnJoinedRoom()
{
base.OnJoinedRoom();
// When room is found go into the room
// Here we use Photons "LoadLevel" since we did not make the room
PhotonNetwork.LoadLevel("Game");
}
// Issue handeling
public override void OnErrorInfo(ErrorInfo errorInfo)
{
base.OnErrorInfo(errorInfo);
// When there is a problem we make sure the player cant do anything
m_MenuUI.interactable = true;
m_ConnectingObj.SetActive(false);
}
}