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 Code (CSharp): 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 Code (CSharp): 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); } } }
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
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 Code (CSharp): 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); } }
Code (CSharp): 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.
It's just a vector. Pass it to the command as an argument Code (csharp): 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.