Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

[SOLVED] Am I Doing This Right?

Discussion in 'Scripting' started by DRRosen3, Nov 14, 2014.

  1. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    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.

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GrenadeLaser : MonoBehaviour {
    5.  
    6.     private LineRenderer line;
    7.     private float laserTime = 3f;
    8.     private float laserTimer;
    9.  
    10.     void Awake() {
    11.         line = gameObject.GetComponentInChildren<LineRenderer>();
    12.         line.enabled = false;
    13.     }
    14.  
    15.     void OnTriggerEnter(Collider other){
    16.         if(other.gameObject.CompareTag("Enemy")){
    17.             FireLaser();
    18.         }
    19.     }
    20.  
    21.     void Update () {
    22.    
    23.     }
    24.  
    25.     private IEnumerator FireLaser(){
    26.         line.enabled = true;
    27.         laserTimer += Time.deltaTime;
    28.         while(laserTimer < laserTime){
    29.             Ray ray = new Ray(transform.position, transform.forward);
    30.             RaycastHit hit;
    31.  
    32.             line.SetPosition(0, ray.origin);
    33.             if(Physics.Raycast(ray, out hit, 100)){
    34.                 line.SetPosition(1, hit.point);
    35.             }else{
    36.                 line.SetPosition(1, ray.GetPoint(100));
    37.             }
    38.  
    39.             yield return null;
    40.         }
    41.  
    42.         line.enabled = false;
    43.     }
    44.  
    45. }
    46.  
    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.
     
    Last edited: Nov 14, 2014
  2. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    StartCouroutine(FireLaser());
     
  3. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
  4. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    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.

    Code (CSharp):
    1.     using UnityEngine;
    2.     using System.Collections;
    3.    
    4.     public class PokeBallLaser : MonoBehaviour {
    5.    
    6.         private LineRenderer line;
    7.         private float laserTime = 3f;
    8.         private float laserTimer;
    9.    
    10.         void Awake() {
    11.             line = gameObject.GetComponentInChildren<LineRenderer>();
    12.             line.enabled = false;
    13.         }
    14.    
    15.         void OnTriggerEnter(Collider other){
    16.             if(other.gameObject.CompareTag("Enemy")){
    17.                StartCoroutine( FireLaser());
    18.             }
    19.         }
    20.    
    21.         void Update () {
    22.        
    23.         }
    24.    
    25.         private IEnumerator FireLaser(){
    26.             line.enabled = true;
    27.        
    28.             while(laserTimer < laserTime){
    29.                    laserTimer += Time.deltaTime;
    30. Ray ray = new Ray(transform.position, transform.forward);
    31.                 RaycastHit hit;
    32.  
    33.    
    34.                 line.SetPosition(0, ray.origin);
    35.                 if(Physics.Raycast(ray, out hit, 100)){
    36.                     line.SetPosition(1, hit.point);
    37.                 }else{
    38.                     line.SetPosition(1, ray.GetPoint(100));
    39.                 }
    40.    
    41.                 yield return 0;
    42.             }
    43.    
    44.             line.enabled = false;
    45.         }
    46.    
    47.     }
    48.    
    49.  
     
  5. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    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.
     
  6. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Alright. Well I made those changes, but it's still instantiating the grade with the line renderer (laser) already enabled.
     
  7. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    What's a grade? Where is your instantiation code?
     
  8. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    Sorry...that should have said grenade. x_x

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GrenadeThrow : MonoBehaviour {
    5.  
    6.     public GameObject grenade;
    7.     public float throwPower;
    8.  
    9.     void Start () {
    10.    
    11.     }
    12.  
    13.     void Update () {
    14.         if(Input.GetButtonDown("Fire1")){
    15.             GameObject clone;
    16.             clone = (GameObject) Instantiate(grenade, transform.position, transform.rotation);
    17.             clone.GetComponent<Rigidbody>().velocity = transform.TransformDirection(Vector3.forward * throwPower);
    18.             clone.GetComponent<Rigidbody>().AddTorque(0, 0, 10);
    19.         }
    20.     }
    21. }
     
  9. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    Does your grenade prefab have it enabled when you drag it into the scene view?
     
  10. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    No. The empty game object that has the line renderer component is enabled, but the line renderer itself is not.
     
  11. Korno

    Korno

    Joined:
    Oct 26, 2014
    Posts:
    518
    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!
     
  12. DRRosen3

    DRRosen3

    Joined:
    Jan 30, 2014
    Posts:
    681
    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...

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class GrenadeLaser : MonoBehaviour {
    5.  
    6.     public float throwTime;
    7.  
    8.     private LineRenderer line;
    9.     private float laserTime = 5f;
    10.     private float laserTimer = 0f;
    11.  
    12.     void Start() {
    13.         line = gameObject.GetComponentInChildren<LineRenderer>();
    14.         line.enabled = false;
    15.     }
    16.  
    17.     void OnCollisionEnter(Collision col){
    18.         if(col.gameObject.tag == "Terrain"){
    19.             Destroy(gameObject);
    20.         }
    21.         if(col.gameObject.tag == "Enemy"){
    22.             StartCoroutine(FireLaser());
    23.         }
    24.     }
    25.  
    26.     void Update () {
    27.  
    28.     }
    29.  
    30.     private IEnumerator FireLaser(){
    31.         line.enabled = true;
    32.         while(laserTimer < laserTime){
    33.             laserTimer += Time.deltaTime;
    34.             Ray ray = new Ray(transform.position, transform.forward);
    35.             RaycastHit hit;
    36.  
    37.             line.SetPosition(0, ray.origin);
    38.             if(Physics.Raycast(ray, out hit, 100)){
    39.                 line.SetPosition(1, hit.point);
    40.             }else{
    41.                 line.SetPosition(1, ray.GetPoint(100));
    42.             }
    43.  
    44.             yield return null;
    45.         }
    46.         laserTimer = 0f;
    47.         line.enabled = false;
    48.     }
    49.  
    50. }