only host can shoot?

Hi im trying to setup 4 directional shooting for my characters in a multiplayer game
but only the host can shoot?
where am i going wrong

Main movement script

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class PlayerMovement : NetworkBehaviour {
    public Vector2 speed = new Vector2(1, 1);
    public GameObject Playercamera;
    private Animator anim;

    public int Direction;

    public override void OnStartLocalPlayer()
    {
        Playercamera.SetActive(true);
        anim = transform.FindChild("Character").GetComponent<Animator>();
    }
    // Update is called once per frame
    void Update () {
        if (!isLocalPlayer)
            return;
        float inputX = Input.GetAxis("Horizontal");
        float inputY = Input.GetAxis("Vertical");
        // Prepare the movement for each direction
        Vector2 movement = new Vector3(speed.x * inputX, speed.y * inputY, 0);
        movement *= Time.deltaTime;// Makes the movement relative to time
        transform.Translate(movement);// Moves the object
        DirectionCheck();
    }

     void DirectionCheck()
    {
        float inputX = Input.GetAxis("Horizontal");
        float inputY = Input.GetAxis("Vertical");
        //Taking the input And figuring out what direction were facing
        if (inputX > 0.2 || inputX < -0.2 || inputY > 0.2 || inputY < -0.2)
        {
            anim.SetBool("Walking", true);
            if (inputX > 0)
            {
                Direction = 1;
                anim.SetFloat("InputX", 1f);
                anim.SetFloat("InputY", 0f);
            }
            else if (inputX < 0)
            {
                Direction = 2;
                anim.SetFloat("InputX", -1f);
                anim.SetFloat("InputY", 0f);
            }
            else if (inputY > 0)
            {
                Direction = 3;
                anim.SetFloat("InputY", 1f);
                anim.SetFloat("InputX", 0f);
            }
            else if (inputY < 0)
            {
                Direction = 4;
                anim.SetFloat("InputY", -1f);
                anim.SetFloat("InputX", 0f);
            }
        }
        else
        {
            anim.SetBool("Walking", false);
        }
    }

}

and this is how im doing the shooting
it appears the direction variable i have does not seem to send or do anything on players other than the host

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Shoot : NetworkBehaviour
{
    public GameObject bulletPrefab;
    public GameObject ProjectileSpawnPointT;
    public GameObject ProjectileSpawnPointB;
    public GameObject ProjectileSpawnPointL;
    public GameObject ProjectileSpawnPointR;

    public PlayerMovement pm;
    // Use this for initialization
    void Start () {
       
    }
    public override void OnStartLocalPlayer()
    {
        //pm = GetComponent<PlayerMovement>();
    }
    // Update is called once per frame
    void Update () {
        if (!isLocalPlayer){
            return;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdFire();
        }
    }
    [Command]
    void CmdFire()
    {
        if(pm.Direction == 1)
        {
            var pos = ProjectileSpawnPointR.transform.position;
            var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
            bullet.GetComponent<Rigidbody2D>().AddForce(transform.right * 200);
            NetworkServer.Spawn(bullet);
            Destroy(bullet, 2.0f);
        }
        else if (pm.Direction == 2)
        {
            var pos = ProjectileSpawnPointL.transform.position;
            var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
            bullet.GetComponent<Rigidbody2D>().AddForce(-transform.right * 200);
            NetworkServer.Spawn(bullet);
            Destroy(bullet, 2.0f);
        }
        else if (pm.Direction == 3)
        {
            var pos = ProjectileSpawnPointT.transform.position;
            var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
            bullet.GetComponent<Rigidbody2D>().AddForce(transform.up * 200);
            NetworkServer.Spawn(bullet);
            Destroy(bullet, 2.0f);
        }
        else if (pm.Direction == 4)
        {
            var pos = ProjectileSpawnPointB.transform.position;
            var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
            bullet.GetComponent<Rigidbody2D>().AddForce(-transform.up * 200);
            NetworkServer.Spawn(bullet);
            Destroy(bullet, 2.0f);
        }
    }
}

anyone got any idea?

Is the ‘Shoot’ script attached to the player? In my experience, Cmd only works properly when sent from the player object

Commands are called on the host’s instance of the GameObject. So you have to pass the direction to the command if it’s not synchronized in any way. (Basically, when a client does this it’s just using the default value of 0 so nothing happens).

is that not what im doing with the
if(pm.Direction == 1)

or do i have to instead set a variable in the shoot script when i change direction instead of having other scripts access the player movment

You’re only doing that on the client instance of the script. The host has no idea what value the client is setting it to because it isn’t synchronized.

Try it - debug the value of Direction in both the Command and Update :slight_smile:

I have updated my shoot script to allow me to shoot in any direction. but still on ebverything but the host the actual bullet willl always only go one direction

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Shoot : NetworkBehaviour
{
    public GameObject bulletPrefab;
    public GameObject ProjectileSpawnPointBase;
    public GameObject ProjectileSpawnPoint;

    // Use this for initialization
    void Start () {
       
    }
    public override void OnStartLocalPlayer()
    {
     
    }
    void FixedUpdate()
    {
        if (!isLocalPlayer)
        {
            return;
        }
        Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        ProjectileSpawnPointBase.transform.rotation = Quaternion.LookRotation(Vector3.forward, mousePos - transform.position);
    }
    // Update is called once per frame
    void Update () {
        if (!isLocalPlayer){
            return;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            CmdFire();
        }
    }
    [Command]
    void CmdFire()
    {
          var pos = ProjectileSpawnPoint.transform.position;
          var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
          bullet.GetComponent<Rigidbody2D>().AddRelativeForce(ProjectileSpawnPoint.transform.up * 200);
          NetworkServer.Spawn(bullet);
          Destroy(bullet, 2.0f);
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;

public class Shoot : NetworkBehaviour
{
    public GameObject bulletPrefab;
    public GameObject ProjectileSpawnPointBase;
    public GameObject ProjectileSpawnPoint;

    // Use this for initialization
    void Start () {
       
    }
    public override void OnStartLocalPlayer()
    {
     
    }
    void FixedUpdate()
    {
      
    }
    // Update is called once per frame
    void Update () {
        if (!isLocalPlayer){
            return;
        }
        if (Input.GetKeyDown(KeyCode.Space))
        {
            Vector3 mousePos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
            ProjectileSpawnPointBase.transform.rotation = Quaternion.LookRotation(Vector3.forward, mousePos - transform.position);
            CmdFire(ProjectileSpawnPoint);
        }
    }
    [Command]
    void CmdFire(GameObject spawnpoint)
    {
        var pos = spawnpoint.transform.position;
        var bullet = (GameObject)Instantiate(bulletPrefab, pos, Quaternion.identity);
        bullet.GetComponent<Rigidbody2D>().AddRelativeForce(spawnpoint.transform.up * 200);
        NetworkServer.Spawn(bullet);
        Destroy(bullet, 2.0f);
    }
}

ok so im now passing in the values to it but now i get this error

NetworkWriter ProjectilePoint (UnityEngine.GameObject) has no NetworkIdentity
UnityEngine.Networking.NetworkWriter:Write(GameObject)
Shoot:CallCmdFire(GameObject)
Shoot:Update() (at Assets/Scripts/Shoot.cs:33)

You can’t pass non-networked GameObjects around in Commands and RPCs. If all you need is the position, pass a Vector3 instead.

i had tried that. but how do i then pass the correct rotation?

how would i then get the equivilent to spawnpoint.transform.up

What about sending 2 Vector3s ? :slight_smile: 1 for position & 1 for rotation (if you need the rotation, too). :slight_smile:

It’s just a vector. Pass it to the command as an argument

CmdFire(spawnpoint.transform.up);

[Command]
void CmdFire(Vector3 spawnPoint)
{

}

Why send a Vector3 for rotation when you can send a Quaternion?

Edit: re-reading everything again. Send two arguments in your Command. One for the position and one for the rotation. Use the transform values from the local player when you’re checking input.

thankyou ve

thankyou very much. learnt alot from this.

1 Like