[Mirror] Laser Co-routine Command?

Hey all I’ve been working on a tractor beam mechanic for my game. Im trying to make the laser show over the network when players are using it. I was trying to use an ifFiring syncvar to snow the line render but i canot make a command a coroutine. Is there another way to make the laser active while a button is held down? Code Below.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Mirror;

public class LaserTest : NetworkBehaviour
{
    [SerializeField] float distance = 250f;
    [SerializeField] LineRenderer line;

    [SerializeField] TextMesh nameText;

    [SyncVar(hook = "OnFireChanged")]
    public bool isFiring = false;


    private void Awake()
    {
        isFiring = false;
    }

    void Start()
    {
        //line = GetComponent<LineRenderer>();
        line.enabled = false;


    }

    // Update is called once per frame
    void Update()
    {
        //temp
        if(nameText != null)
        {
            nameText.transform.LookAt(Camera.main.transform.position);
            nameText.transform.Rotate(0, 180, 0);
        }

        if (isLocalPlayer)
        {
            if (Input.GetButtonDown("Fire1"))
            {
                isFiring = true;
                StopCoroutine("CmdFireLaser");
                StartCoroutine("CmdFireLaser");
            }
        }

        if (isFiring)
        {
            line.enabled = true;
        }
        else
        {
            line.enabled = false;
        }
    }

    [Command]
    IEnumerator CmdFireLaser()
    {
        
        //line.enabled = true;

        while (Input.GetButton("Fire1"))
        {
            RaycastHit hit;
            Ray ray = new Ray(line.transform.position, line.transform.forward);

            line.SetPosition(0, ray.origin);

            if (Physics.Raycast(ray, out hit, distance))
            {
                line.SetPosition(1, hit.point);
                if (hit.rigidbody)
                {
                    //hit.rigidbody.AddForceAtPosition(line.transform.forward * 50, hit.point);
                }

            }
            else
            {
                line.SetPosition(1, ray.GetPoint(distance));
            }



            yield return null;
        }

        //line.enabled = false;
        isFiring = false;
    }
}

First, isFiring and any bool variable will always start at false (except for serialized values).

Even if it didn’t start as false, you should only init it on the local player.


Second, your coroutine should never affect the conditions that decides if it is running. It should not set “ifFiring”


Third, a coroutine that is always running and runs every frame should just be a function called by update. There’s no reason for it to be a coroutine.


Last, your actual bug: checking “Input” on any other player will return the input of the other player. Replace the input check by “isFiring”.

Thank you for the response following that advice this is what i have come up with. It works on the host client but not the any connecting to the host. I want the line render to show on the player that is using it. Im unsure what im doing wrong.

    [SerializeField] float distance = 250f;
    [SerializeField] LineRenderer line;
    [SerializeField] float rateOfFire = 1.5f;

    [SyncVar]
    public bool isFiring = false;

    private void Awake()
    {
        if (isLocalPlayer)
        {
            isFiring = false;
        }
    }

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (isLocalPlayer)
        {

            if (Input.GetButtonDown("Fire1"))
            {
                isFiring = true;
                
            }

            if (Input.GetButton("Fire1"))
            {
                CmdShoot();
            }
            else if (Input.GetButtonUp("Fire1"))
            {
                    
                
                isFiring = false;
            }
            
        }

        if (isFiring)
        {
            line.enabled = true;
        }
        else
        {
            line.enabled = false;
        }
    }

    [Command]
    void CmdShoot()
    {
        Debug.Log("SHOOT!!!!");
        RaycastHit hit;
        Ray ray = new Ray(line.transform.position, line.transform.forward);

        line.SetPosition(0, ray.origin);

        if (Physics.Raycast(ray, out hit, distance))
        {
            line.SetPosition(1, hit.point);

            if (hit.rigidbody)
            {
                //hit.rigidbody.AddForceAtPosition(line.transform.forward * 50, hit.point);
            }

        }
        else
        {
            line.SetPosition(1, ray.GetPoint(distance));
        }
    }