[SOLVED] Am I Doing This Right?

What I’m trying to accomplish is having a line renderer (my laser) fire if the orb it’s attached to collides with a certain enemy. So the player throws the grenade, and if it collides with an enemy, I want the laser to fire. This is the code I’ve written.

using UnityEngine;
using System.Collections;

public class GrenadeLaser : MonoBehaviour {

    private LineRenderer line;
    private float laserTime = 3f;
    private float laserTimer;

    void Awake() {
        line = gameObject.GetComponentInChildren<LineRenderer>();
        line.enabled = false;
    }

    void OnTriggerEnter(Collider other){
        if(other.gameObject.CompareTag("Enemy")){
            FireLaser();
        }
    }

    void Update () {
    
    }

    private IEnumerator FireLaser(){
        line.enabled = true;
        laserTimer += Time.deltaTime;
        while(laserTimer < laserTime){
            Ray ray = new Ray(transform.position, transform.forward);
            RaycastHit hit;

            line.SetPosition(0, ray.origin);
            if(Physics.Raycast(ray, out hit, 100)){
                line.SetPosition(1, hit.point);
            }else{
                line.SetPosition(1, ray.GetPoint(100));
            }

            yield return null;
        }

        line.enabled = false;
    }

}

The enemy models have a sphere collider on them and the grenades mesh collider is set to be the trigger…and it also has a sphere collider on it so it doesn’t fall through the world. The grenade has a child that is an empty game object attached to it that serves as the fire point for the laser. And the script above is attached to the grenade itself. And obviously I have a different script that handles throwing the grenade. The reason I’m asking am I doing this right is because during testing when the player throws the grenade, and it clearly strikes the enemy, the laser doesn’t fire.

StartCouroutine(FireLaser());

Made that change @A.Killingbeck and now the laser is always on.

laserTimer += Time.deltaTime;

Needs to be in the loop or it will fire forever, also StartCoroutine is correct. Yield return 0 will make the coroutine continue next frame.

    using UnityEngine;
    using System.Collections;
    
    public class PokeBallLaser : MonoBehaviour {
    
        private LineRenderer line;
        private float laserTime = 3f;
        private float laserTimer;
    
        void Awake() {
            line = gameObject.GetComponentInChildren<LineRenderer>();
            line.enabled = false;
        }
    
        void OnTriggerEnter(Collider other){
            if(other.gameObject.CompareTag("Enemy")){
               StartCoroutine( FireLaser());
            }
        }
    
        void Update () {
        
        }
    
        private IEnumerator FireLaser(){
            line.enabled = true;
        
            while(laserTimer < laserTime){
                   laserTimer += Time.deltaTime;
Ray ray = new Ray(transform.position, transform.forward);
                RaycastHit hit;

    
                line.SetPosition(0, ray.origin);
                if(Physics.Raycast(ray, out hit, 100)){
                    line.SetPosition(1, hit.point);
                }else{
                    line.SetPosition(1, ray.GetPoint(100));
                }
    
                yield return 0;
            }
    
            line.enabled = false;
        }
    
    }

Your not updating laserTimer within your loop. So it will never reach the end condition. Also, yield return null is the preferred method Korno. Unitys coroutine system deals with objects. So yield return 0 will cause extra memory allocations due to the boxing which will occur.

Alright. Well I made those changes, but it’s still instantiating the grade with the line renderer (laser) already enabled.

What’s a grade? Where is your instantiation code?

Sorry…that should have said grenade. x_x

using UnityEngine;
using System.Collections;

public class GrenadeThrow : MonoBehaviour {

    public GameObject grenade;
    public float throwPower;

    void Start () {
   
    }

    void Update () {
        if(Input.GetButtonDown("Fire1")){
            GameObject clone;
            clone = (GameObject) Instantiate(grenade, transform.position, transform.rotation);
            clone.GetComponent<Rigidbody>().velocity = transform.TransformDirection(Vector3.forward * throwPower);
            clone.GetComponent<Rigidbody>().AddTorque(0, 0, 10);
        }
    }
}

Does your grenade prefab have it enabled when you drag it into the scene view?

No. The empty game object that has the line renderer component is enabled, but the line renderer itself is not.

That`s interesting and makes sense thinking about it. Strangely a lot of the example code I have seen does a yield return 0; to wait for the next frame. Thanks for the information!

Solved it myself. Although Korno and A.Killingbeck did help! ^^; The problem is that I was using OnTRIGGEREnter… OnCOLLISIONEnter is what I should have been using. The code now looks like this…

using UnityEngine;
using System.Collections;

public class GrenadeLaser : MonoBehaviour {

    public float throwTime;

    private LineRenderer line;
    private float laserTime = 5f;
    private float laserTimer = 0f;

    void Start() {
        line = gameObject.GetComponentInChildren<LineRenderer>();
        line.enabled = false;
    }

    void OnCollisionEnter(Collision col){
        if(col.gameObject.tag == "Terrain"){
            Destroy(gameObject);
        }
        if(col.gameObject.tag == "Enemy"){
            StartCoroutine(FireLaser());
        }
    }

    void Update () {

    }

    private IEnumerator FireLaser(){
        line.enabled = true;
        while(laserTimer < laserTime){
            laserTimer += Time.deltaTime;
            Ray ray = new Ray(transform.position, transform.forward);
            RaycastHit hit;

            line.SetPosition(0, ray.origin);
            if(Physics.Raycast(ray, out hit, 100)){
                line.SetPosition(1, hit.point);
            }else{
                line.SetPosition(1, ray.GetPoint(100));
            }

            yield return null;
        }
        laserTimer = 0f;
        line.enabled = false;
    }

}