2

I am making an online multiplayer game in Unity with Mirror Networking. In this script I am trying to shoot a bullet by calling, from the client, a command on the server ( CmdFire() ) that instantiate a projectile from a shot position using the rotation of the player camera. The issue that I have is that when I try to shoot a bullet from the client machine he disconnect where if the host tries to shoot the projectile is not visible to the client. This is my code:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;
public class Shooter : NetworkBehaviour
{
public GameObject projectilePrefab;
public Transform shootPos;
public Camera playerCamera;
bool canShoot = true;
public AudioSource shotSound;
[Command]
void CmdFire()
{
     GameObject projectile = Instantiate(projectilePrefab, shootPos.position, playerCamera.transform.rotation);
     NetworkServer.Spawn(projectile);
    
}

// Update is called once per frame
void Update()
{
    if (!hasAuthority) return;
    
    if (Input.GetButton("Fire1"))
    {
        if (canShoot)
        {
            canShoot = false;

            GenerateRayCast();
            CmdFire();

            StartCoroutine(FireDelay());
            shotSound.Play();
        }

    }
}
Transform GenerateRayCast()
{
    playerCamera = transform.Find("CameraMountPosition").Find("Camera").GetComponent<Camera>();

    Ray ray = new Ray(shootPos.transform.position, playerCamera.transform.forward * 500);
    Debug.DrawRay(shootPos.transform.position, playerCamera.transform.forward * 500, Color.red, 2f);
    RaycastHit hit;
    if (Physics.Raycast(ray, out hit))
    {
        Debug.LogError("SERVER: Player shot: " + hit.collider.name);

        if (hit.collider.CompareTag("Player"))
        {
           //deal damage 
        }

    }
    return hit.transform;

}
// Cooldown before shooting again
IEnumerator FireDelay()
{
    yield return new WaitForSeconds(2);
    canShoot = true;
}
}
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
gNt
  • 79
  • 1
  • 9
  • Despite that your `GenerateRaycast` is pretty inefficient (don't use `Find` and `GetComponent` over and over again!) .. is your prefab a) network ready - does it have a `NetworkIdendity` and b) is it registered as a spawn able prefab ? – derHugo May 05 '21 at 04:14
  • @derHugo The prefab already had the NetworkIdentity comoponent, but was not registered as spawnable prefab. Anyway, afeter registering it nothing changed: the client keeps disconnecting when shooting. About the Find/GetComponent how should I get the Camera as it gets attached only when the player connects to the server? – gNt May 05 '21 at 06:29
  • To the find thing: as you say it gets attached when the player spawns => cache it **once** in the `Start` of that player .. the disconnect I don't see an obvious reasons for that .. do you see any errors? – derHugo May 05 '21 at 06:41
  • @derHugo Ok I notice that error: `Exception in MessageHandler: UnassignedReferenceException The variable playerCamera of Shooter has not been assigned.` . I checked in the scene and seems that the MainCamera gets attacched only on the Host. That is the code i run in Start() of the Player script `Transform cameraTransform = Camera.main.gameObject.transform; cameraTransform.parent = CameraMountPoint.transform; cameraTransform.position = CameraMountPoint.transform.position; cameraTransform.rotation = CameraMountPoint.transform.rotation;` – gNt May 05 '21 at 06:54
  • I forgot to mention the code above is runned in an `If(isLocalPlayer) { //attach camera}` – gNt May 05 '21 at 07:06
  • and how is your player spawned exactly? – derHugo May 05 '21 at 08:10
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/231969/discussion-between-gnt-and-derhugo). – gNt May 05 '21 at 09:07

1 Answers1

1

I ended up changing the whole way the player shoots projectiles.

First of all I avoided using the player camera to understand the direction for spawning the projectile and I used another gameObject that was basically having the same behaviour of the camera but that was placed IN the player prefab.

The other thing I did was using non-network identity projectiles. So i spawned the projectile both in the Client and in the Server.

void Fire()
{
    if (!base.hasAuthority) return;

    //if is client spawn on here
    if (!base.isServer)
    {
        Projectile p = Instantiate(projectilePrefab, shootPos.position, shootPos.rotation);
    }

    //spawn on the server
    CmdFire(shootPos.position, shootPos.rotation);
}
gNt
  • 79
  • 1
  • 9