my son has made a 2 player fps game and is having trouble when each player picks up a pistol and when one of them fires their gun the other players gun fires, also whoever picks up their gun first has the ammo displayed and the other one doesn’t. he has autism and is getting really stressed as he has to hand his work in this friday. please help
So based off the information you’ve shared it seems like somewhere in his code he is calling a method, say ShootGun() and it’s not checking who is making that call thus calling it for all players.
Seems like he needs to add some checks to see who is making the call and make sure that when someone picks up the gun is not calling that same method on both players but only on one.
Going to be hard to provide more help than that.
Some multiplier solutions like PUN and UNET have a property called IsLocalPlayer
. Since the code is running on all scripts on all machines, checking if (IsLocalPlayer)
can help you filter code so only the machine whose keyboard was pressed runs that code.
I think this is happening because the guns don’t have any idea who “owns” them
In your code you have both
if (Input.GetMouseButtonDown(0) && player.hasWeapon)
and
if (player2.usingController)
{
if (triggerState == 0)
{
if (Input.GetAxisRaw("Fire") == 1 && player2.hasWeapon)
{
Its highly likely that those two statements could be true even if the gun it held by the other player and therefore it will fire when the other player presses fire.
You need to check if the Gun is owned by the person pressing fire. Something simple like setting a bool to true if player1 picks up the gun and a bool for if player 2 picks up the gun should work
Then you can do an ownership test as part of your logic. i.e, lets say you create a bool of player1PickedUp and set that to true when the gun is picked up now you can check when checking the GetMouseButtonDown if it is player 1 who owns the gun and if so fire.
if (Input.GetMouseButtonDown(0) && player.hasWeapon && player1PickedUp)
Hope that helps?
I’m going to get him to post his code what he has done later today. Thank you for all your replies
Hello, I’m his son.
To further clarify, the game is split screen multiplayer only, and I’m not using any of Unity’s Networking services.
Here is the full code to my Weapon class, which is attached to the weapons themselves:
public class Weapon : MonoBehaviour
{
public Camera cam;
public ParticleSystem muzzle;
[SerializeField] public Gun gun;
public GameObject currentGun;
private Player player;
private Player2 player2;
private float timeToFire = 0f;
private int triggerState = 0;
// Start is called before the first frame update
void Start()
{
player = FindObjectOfType<Player>();
player2 = FindObjectOfType<Player2>();
currentGun = gameObject;
gun = Gun.CreateInstance(currentGun.name, currentGun, 10, 100, 10, 20, 36, false) as Gun;
gun.instance = gun;
HealthBar.SetAmmo(0);
HealthBar.HideAmmo();
HealthBar.SetAmmo2(0);
HealthBar.HideAmmo2();
}
// Update is called once per frame
void Update()
{
if (player.hasWeapon)
{
cam = player.GetComponentInChildren<Camera>();
HealthBar.ShowAmmo();
HealthBar.SetAmmo(gun.instance.ammo / gun.instance.maxAmmo);
HealthBar.SetAmmoText(gun.instance.ammo.ToString());
}
else if (player2.hasWeapon)
{
cam = player2.GetComponentInChildren<Camera>();
HealthBar.ShowAmmo2();
HealthBar.SetAmmo2(gun.instance.ammo / gun.instance.maxAmmo);
HealthBar.SetAmmoText2(gun.instance.ammo.ToString());
}
if (player2.usingController)
{
if (triggerState == 0)
{
if (Input.GetAxisRaw("Fire") == 1 && player2.hasWeapon)
{
triggerState = 1;
if (!gun.instance.isAutomatic) { Fire2(); }
else
{
if (Time.time >= timeToFire)
{
timeToFire = Time.time + 1f / gun.instance.fireRate;
Fire2();
}
}
}
}
else
{
if (Input.GetAxisRaw("Fire") == 0) { triggerState = 0; }
}
}
if (Input.GetMouseButtonDown(0) && player.hasWeapon)
{
if (!gun.instance.isAutomatic) { Fire(); }
else
{
if (Time.time >= timeToFire)
{
timeToFire = Time.time + 1f / gun.instance.fireRate;
Fire();
}
}
}
}
public void Fire()
{
if ((player.hasWeapon) && gun.instance.ammo > 0f)
{
muzzle.Play();
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out RaycastHit hit, gun.instance.range))
{
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
print(target.name + " takes " + gun.instance.damage + " damage");
target.TakeDamage(gun.instance.damage);
}
}
gun.instance.ammo--;
if (gun.instance.ammo < gun.instance.maxAmmo / 4)
{
UI.lowAmmoText.text = "Low Ammo";
}
else
{
UI.lowAmmoText.text = "";
}
}
else
{
UI.lowAmmoText.text = "No Ammo";
}
}
public void Fire2()
{
if ((player2.hasWeapon) && gun.instance.ammo > 0f)
{
muzzle.Play();
if (Physics.Raycast(cam.transform.position, cam.transform.forward, out RaycastHit hit, gun.instance.range))
{
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
print(target.name + " takes " + gun.instance.damage + " damage");
target.TakeDamage(gun.instance.damage);
}
}
gun.instance.ammo--;
if (gun.instance.ammo < gun.instance.maxAmmo / 4)
{
UI.lowAmmoText.text = "Low Ammo";
}
else
{
UI.lowAmmoText.text = "";
}
}
else
{
UI.lowAmmoText.text = "No Ammo";
}
}
}
I know it’s ugly and impractical, but at this point, I’m just so desperate to get something working at the very least.
My logic here is to make an instance of a ScriptableObject named Gun, and assign that instance to whatever GameObject has this script attached.
In my scene, I have two weapons in different positions. If one player picks up one of the weapons, then it works perfectly fine - the issue comes when the other player picks up the other remaining weapon in which it is being assigned to the same weapon.
I believe the most logical thing to do is to make an array of type Gun to store all the Gun instances, as well as something that points to this being the current weapon, but the problem is that I’m not exactly sure how I would go around this.
If you want me to clarify further, then I’ll be happy to do so.