Hope you’re all good! I’m working on a multiplayer game using netcode for game objects and I’m stuck on syncing weapon pickup and switching between players. I’ve got it working for single-player, but now I’m struggling to synchronize this across multiple clients.
I need some guidance on how to sync weapon pickup and switching in a multiplayer game. If you’ve got any tips, best practices, or other ways to do it, I’d really appreciate your help.
I’ve been trying to implement a solution based on what I found in the forums, but I’m struggling.
Here’s what I’ve discovered so far:
- Players ask the server if they can pick up a weapon.
- If yes, the server instantiates the weapon on all clients (non-network object).
- The weapon on the ground is hidden.
However, I’m having trouble implementing this. Also, I’ve got a character armature in my game, so attaching the weapon is a bit tricky as I can’t make it a network object.
This is my script for weapon pickup and switching
using System.Collections;
using UnityEngine;
public class WeaponPickupAndDrop : MonoBehaviour
{
public enum WeaponSlot
{
Primary = 0,
Secondary = 1
}
public Camera mainCamera;
public float pickUpRange;
public LayerMask pickUpLayer;
public Transform[] weaponSlots;
public Animator rigController;
public CharacterAiming characterAiming;
GameObject [] equippedWeapon = new GameObject[2];
int activeWeaponIndex;
public void Start()
{
mainCamera = Camera.main;
rigController.updateMode = AnimatorUpdateMode.AnimatePhysics;
rigController.cullingMode = AnimatorCullingMode.AlwaysAnimate;
rigController.updateMode = AnimatorUpdateMode.Normal;
}
GameObject GetWeapon(int index)
{
if(index < 0 || index >= equippedWeapon.Length)
{
return null;
}
return equippedWeapon[index];
}
public GameObject GetActiveWeapon()
{
return GetWeapon(activeWeaponIndex);
}
public void PickUp(GameObject newWeapon)
{
int weaponSlotIndex = (int) newWeapon.GetComponent<GunSystem>().weaponSlot;
var weapon = GetWeapon(weaponSlotIndex);
if(weapon)
{
Destroy(weapon);
}
weapon = newWeapon;
weapon.GetComponent<Recoil>().characterAiming = characterAiming;
weapon.GetComponent<Recoil>().rigController = rigController;
weapon.transform.SetParent(weaponSlots[weaponSlotIndex]);
weapon.transform.localPosition = Vector3.zero;
weapon.transform.localRotation = Quaternion.identity;
//rigController.Play("equip_"+ weapon.GetComponent<GunSystem>().weaponName);
equippedWeapon[weaponSlotIndex] = weapon;
//activeWeaponIndex = weaponSlotIndex;
SetActiveWeapon(weaponSlotIndex);
}
void ToggleActiveWeapon()
{
bool isHolstered = rigController.GetBool("holsterWeapon");
if(isHolstered)
{
StartCoroutine(ActivateWeapon(activeWeaponIndex));
}
else
{
StartCoroutine(HolsterWeapon(activeWeaponIndex));
}
}
void SetActiveWeapon(int weaponSlotIndex)
{
int holsterIndex = activeWeaponIndex;
int activateIndex = weaponSlotIndex;
if(holsterIndex == activateIndex)
{
holsterIndex = -1;
}
StartCoroutine(SwitchWeapon(holsterIndex, activateIndex));
}
IEnumerator SwitchWeapon(int holseterIndex, int activateIndex)
{
yield return StartCoroutine(nameof(HolsterWeapon), holseterIndex);
yield return StartCoroutine(nameof(ActivateWeapon), activateIndex);
activeWeaponIndex = activateIndex;
}
IEnumerator HolsterWeapon(int index)
{
var weapon = GetWeapon(index);
if(weapon)
{
weapon.GetComponent<GunSystem>().enabled = false;
rigController.SetBool("holsterWeapon", true);
do
{
yield return new WaitForEndOfFrame();
}
while(rigController.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f);
}
}
IEnumerator ActivateWeapon(int index)
{
var weapon = GetWeapon(index);
if(weapon)
{
rigController.SetBool("holsterWeapon", false);
rigController.Play("equip_"+ weapon.GetComponent<GunSystem>().weaponName);
do
{
yield return new WaitForEndOfFrame();
}
while(rigController.GetCurrentAnimatorStateInfo(0).normalizedTime < 1.0f);
weapon.GetComponent<GunSystem>().enabled = true;
}
}
void SwitchWeaponByMouse(float scrollValue)
{
if(equippedWeapon[0] != null && equippedWeapon[1] != null)
{
if (scrollValue > 0f)
{
SetActiveWeapon((int)WeaponSlot.Secondary);
}
else if (scrollValue < 0f)
{
SetActiveWeapon((int)WeaponSlot.Primary);
}
}
}
void Update()
{
if(Input.GetKeyDown(KeyCode.F))
{
if(Physics.Raycast(mainCamera.transform.position, mainCamera.transform.forward, out RaycastHit hit, pickUpRange, pickUpLayer))
{
var newWeapon = Instantiate(hit.transform.gameObject);
PickUp(newWeapon);
}
}
if(Input.GetKeyDown(KeyCode.X))
{
ToggleActiveWeapon();
}
if(Input.GetKeyDown(KeyCode.Alpha1))
{
SetActiveWeapon((int)WeaponSlot.Primary);
}
if(Input.GetKeyDown(KeyCode.Alpha2))
{
SetActiveWeapon((int)WeaponSlot.Secondary);
}
if (Input.GetAxis("Mouse ScrollWheel") != 0f)
{
SwitchWeaponByMouse(Input.GetAxis("Mouse ScrollWheel"));
}
}
}