Moving forward: Enhancing the Multiplayer Shooter Game
With the foundations laid by implementing networking and player movement through Photon and Unity, the next step is adding more features to the game. Let's take a closer look at the recent additions.
New Features Added
Loading Screen
A loading screen has been added to provide players with visibility on the connection status when joining the game.
Weapon Implementation
A weapon has been introduced to the game to allow players to engage in some form of combat. For initial implementation, this is a free model from Sketchfab.
The Fire method is used for the weapon firing mechanic:
void Fire()
{
Ray ray = new Ray(camera.transform.position, camera.transform.forward);
RaycastHit hit;
if(Physics.Raycast(ray.origin, ray.direction, out hit, 100f))
{
PhotonNetwork.Instantiate(hitEffect.name, hit.point, Quaternion.identity);
if(hit.transform.gameObject.GetComponent<Health>() != null)
{
hit.transform.gameObject.GetComponent<PhotonView>().RPC("TakeDamage", RpcTarget.All, damage);
}
}
}
Shooting Animations
A shooting animation has been added so that when the player fires the weapon an animation plays. When shooting, the animation plays and the ammo decreases (in this case ammo is shown in the bottom right).
Reloading Mechanism
If the player presses the "R" key during the game, the weapon reloads. There is also a reloading animation created that plays. During reloading the shooting is disabled, the ammo increases.
The reload method handles the reloading mechanics, including updating ammo counts:
void Reload()
{
animation.Play(reloadAnimation.name);
if (magAmmo > 0)
{
mag--;
ammo = magAmmo;
}
magText.text = mag.ToString();
amoText.text = ammo + " / " + magAmmo;
}
Respawning functionality
Originally, the player could not respawn in the game, however now respawning has been added when players reach zero health. Health starts at 100 and decreases based upon a damage amount taken during gameplay.
Player Health System
A health system has been implemented to monitor the players health status. When the player is hurt by another in the game, their health decreases.
Realm Switching
Due to the concept of the game being around the ability for players to travel between two separate realms, realm switching was implemented. During the game, players can press the "V" key to transform their position to the second realm. In this case, the second realm is just a second plane in Unity. It should become invisible or visible based on what realm the player is located in.
This is the script created for switching realms:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Photon.Pun;
public class MoveOnKeyPress : MonoBehaviourPun
{
public float yoffset = 52f;
public float doffset = 50f;
private bool inFirstRealm = true; //Have a bool to check if we are in the second realm or not
void Update()
{
//If we are in the second realm, we can't go back to the first realm
if (photonView.IsMine)
{
if (Input.GetKeyDown(KeyCode.V))
{
if (inFirstRealm)
{
photonView.RPC("Move", RpcTarget.AllBuffered, yoffset);
}
else
{
photonView.RPC("MoveDown", RpcTarget.AllBuffered, doffset);
}
}
}
}
[PunRPC]
void Move(float yoffset)
{
Vector3 curerntPos = transform.position;
curerntPos.y += yoffset;
transform.position = curerntPos;
inFirstRealm = false; //If we are in the second realm, set the bool to true
}
[PunRPC]
void MoveDown(float doffset)
{
Vector3 curerntPos = transform.position;
curerntPos.y -= doffset;
transform.position = curerntPos;
inFirstRealm = true; //If we are in the first realm, set the bool to false
}
}
How it works:
Upon pressing the "V" key, the script checks if the player is in the first realm or not.
If in the first realm, an RPC (Remote Procedure Call) is used to move the players position to the second realm using the
move
method.If in the second realm, another RPC is invoked to move the player back down to the first realm using the
moveDown
method.
Weapon Movement
A slight weapon sway has been incorporated to simulate realistic movement in the game. This is the WeaponSway
script that was added:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WeaponSway : MonoBehaviour
{
public float swayClamp = 0.09f;
public float smoothing = 3.0f;
private Vector3 origin;
void Start()
{
origin = transform.localPosition;
}
void Update()
{
Vector2 input = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));
input.x = Mathf.Clamp(input.x, -swayClamp, swayClamp);
input.y = Mathf.Clamp(input.y, -swayClamp, swayClamp);
Vector3 target = new Vector3(-input.x, -input.y, 0);
transform.localPosition = Vector3.Lerp(transform.localPosition, target + origin, Time.deltaTime * smoothing);
}
}
Summary of the variables used:
swayClamp
defines the maximum amount of sway allowed in any direction.smoothing
- controls the rate at which the weapon returns to its original position.origin
- stores the original position of the weapon at the start of the game.
Source Control
This code has been kept up-to-date using GitHub. The full code can be found here.
Acknowledgements
Special thanks to Lakshya Tyagi for the creation of the map, which will be implemented in future updates.
Thanks for reading this article!
Molly
Subscribe to my newsletter
Read articles from Molly directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by