Search Unity

LineRenderer and Raycasting Questions

Discussion in 'Scripting' started by Mirage, Mar 1, 2010.

  1. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    Two questions. I am scripting an AI turret system for a ship and am using lineRenderer and Raycasting as weapon effects. I want the turret to use the target's transform as a fire direction, but I dont want the turret to track the target. I need the turret to pick the point in space where the target is at time = 0 and raycast that direction. What I cant figure out how to do is get a linerenderer to "snap" to the raycast. If the raycast gets interrupted, I want the linerenderer to hit the object. I was hoping for something along the lines of using the vector3 position as a direction and using the raycast distance for the linerenderer distance, but I dont know how to script that.

    Another simpler question is how to broadcast a message to a specific child. I have a gameobject with a script attached that broadcasts the message "Fire". I need this message to be broadcast (or Sent) to a specific child. I tried childname.SendMessage ("Fire"); but that did'nt work. I imagine this is the purpose of the SendMessage command, however the unity manual was not very specific in this area.
     
  2. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Use the version of Physics.Raycast that takes a Ray object as a parameter. Then, use the ray's GetPoint function to get a point a certain distance along the ray.

    You can't use the name of a child object as a variable within the script. You can use transform.Find to get a child object by name. Then, refer to the child transform's gameObject property when you use SendMessage:-
    Code (csharp):
    1. var child: Transform = transform.Find("ChildName");
    2. child.gameObject.SendMessage(...);
     
  3. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    Thanks andeeee, that looks like the right way to do it. Syntax question though... How do you phrase the if (Physics.Raycast(ray,hit,Mathf.Infinity)) { } statement? and what exactialy is the ray variable? Usuialy they are things like Vector3, or transforms. I need to shoot the ray in the "direction" of the target's transform (Vector3 I assume).

    Here is what I have so far. (not working, no line visible, ray.direction never changes either (moving target).


    Code (csharp):
    1. if (Physics.Raycast(ray,hit,Mathf.Infinity))
    2.                { ray.direction = target.transform.position;
    3.             ray.origin = transform.position;
    4.                     Debug.DrawRay (ray.origin,ray.direction,Color.green);
    5.                  //Debug.Log (ray.direction);
    6.                }
     
  4. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    Well I'm stuck... I can't figure out why ray.direction is set to (0.6, 0.0, 0.8 ). That is not the coordinate of the target transform and there is nothing there in the scene view. However if I set the line position to target.position everything works semi-OK. Here is the code I am using, you should be able to copy paste it, function Fire () is a broadcastmessage from my other script.

    Code (csharp):
    1. var line : LineRenderer;
    2. var target : Transform;
    3. var laserDuration : int = 5;
    4. var test : Transform;
    5.  
    6.  
    7. private var fireing : boolean;
    8. private var ray : Ray;
    9. private var hit : RaycastHit;
    10. private var initialTime : float;
    11. private var doOnce : boolean;
    12.  
    13. function Fire ()
    14. {
    15.     fireing = true;
    16.     initialTime = Time.time;
    17. }
    18.  
    19. function Update ()
    20. {
    21.     if ( fireing == true)
    22.     {
    23.         if ( target != null)
    24.         {
    25.             ray.direction = target.position;
    26.             ray.origin = transform.position;
    27.             if (Time.time > initialTime)
    28.             {              
    29.                 if (Physics.Raycast (ray, Mathf.Infinity))
    30.                 {
    31.                     return;
    32.                 }
    33.                
    34.                 else
    35.                 {
    36.                     line.SetPosition(0, transform.position);
    37.                     Debug.Log (ray.direction);
    38.                     line.SetPosition(1, target.position);
    39.                 }
    40.             }
    41.            
    42.             if ( Time.time > (initialTime +laserDuration))
    43.             {
    44.                
    45.                 line.SetPosition(0, transform.position);
    46.                 line.SetPosition(1, target.position);
    47.                 target = null;
    48.                 fireing = false;
    49.                 doOnce = false;
    50.             }
    51.            
    52.         }
    53.     }
    54. }
    55.  
    56.  
    Edit: It seems that the Ray is being normalized. It does change with movement, but not enough to do anything. Perhaps this is the problem?
     
  5. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    *bump

    Is this even the right way to do this? I'm sure someone else has used a raycast of an indefinite length before. All I need is to raycast in the direction of a transform, adjust the length based on hits and stretch a linerenderer between origin and direction. Much like a light shining in the direction of an object; if something gets in the way, the new light "distance" changes.
     
  6. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    I hate to keep bumping this, but it seems like such a simple thing I'm missing. Unity manual is woefully vague on raycasting Vector3's with varying distances. Any ideas how to do this?

    This is my current script:
    Code (csharp):
    1.  
    2. var line : LineRenderer;
    3. static var target : GameObject;
    4. var laserDuration : int;
    5.  
    6. private var timer : float;
    7. private var tracker : LineRenderer;
    8. private var fireing : boolean;
    9. private var ray : Ray;
    10. private var hit : RaycastHit;
    11. private var doOnce : boolean;
    12.  
    13.  
    14. function Fire ()
    15. {
    16.     target = TurretControl.target;
    17.    
    18.     if (fireing == true)
    19.     {
    20.         Debug.Log ("Currently Fireing");
    21.     }
    22.     else
    23.     {
    24.         tracker = Instantiate (line);
    25.         fireing = true;
    26.         timer = Time.time;
    27.         ray.direction = target.transform.position;
    28.     }
    29. }
    30.  
    31. function Update ()
    32. {
    33.     if (fireing == true)
    34.     {
    35.         Physics.Raycast (transform.position, target.transform.position, hit, Mathf.Infinity);
    36.         tracker.SetPosition (0, transform.position);
    37.         if (doOnce == false)
    38.         {
    39.             tracker.SetPosition (1, hit.point);
    40.             Debug.Log (hit.point);
    41.             doOnce = true;
    42.         }
    43.        
    44.         if ((Time.time >= (timer +laserDuration)))
    45.         {
    46.             Debug.Log ("Ceasefire");
    47.             doOnce = false;
    48.             Destroy (tracker);
    49.             fireing = false;
    50.         }
    51.        
    52.     }
    53.  
    54. }
    55.  
    56.  
     
  7. GamersHeaven

    GamersHeaven

    Joined:
    Feb 15, 2010
    Posts:
    88
    But sounds like something i did with my turret script?
    I use an linecast to se if there is an free line of sigth,and if it detects it so does the turret turn towards it.
    Maybe you can use something of my script?

    Code (csharp):
    1.  
    2. /*
    3. Turret targetting uses a linecast to check if the turret have an -
    4. free line of sight towards the player.
    5. The turret and player must be set to ignore raycast ! in the layer panel in the inspector.
    6. RaycastHit = Used to get information back from a raycast.
    7. */
    8. private var hit : RaycastHit;
    9. var speed : int = 3;
    10.  
    11. function Update () { //main loop start
    12.  
    13.  var target = GameObject.FindWithTag("Player") ;
    14.   if (Physics.Linecast(transform.position, target.transform.position, hit)) {
    15.    // to se wath the ray hits = print ("Blocked by " + hit.collider.name);
    16.       }
    17.        else {
    18. // Put the barrel on the top of the model as this look at rotation is restricted to z axis !
    19. //Remove ( , Vector3.forward ) at the end so will you get an all axis smooth look at rotation.
    20. // Also remove  these ( newRotation.x = 0.0;   newRotation.y = 0.0;  )
    21. // Get the target rotation
    22. var newRotation = Quaternion.LookRotation(transform.position - target.transform.position, Vector3.forward);
    23. newRotation.x = 0.0;
    24. newRotation.y = 0.0;
    25. // Smoothly rotate towards the target .
    26. transform.rotation = Quaternion.Slerp(transform.rotation, newRotation, speed*Time.deltaTime);  
    27. }
    28.  
    29. } // main loop end  //
    30.  
     
  8. Mirage

    Mirage

    Joined:
    Jan 13, 2010
    Posts:
    230
    Thanks, but that is'nt quite what I'm trying to do. What I need is a way to raycast a vector3 and get the "direction" for that vector3 and use lineRenderer to stretch a line across the distance between the script's transform and the target's transform. The difficult part is, if the target moves, keeping the ray/line the same direction and changing the distance to infinity. Very similar to shooting a laser pointer at an object, if the object moves, the laser stays on and hits the object behind the first.
     
  9. andeeeee

    andeeeee

    Joined:
    Jul 19, 2005
    Posts:
    8,768
    Sorry for taking a while to get back to you here...

    The ray is defined by its starting position and its direction. You can get the direction from a starting point to a target point by subtracting one from the other:-
    Code (csharp):
    1. var startPoint: Vector3 = transform.position;
    2. var direction: Vector3 = target.position - startPoint;
    3. var ray: Ray = new Ray(startPoint, direction);
    4. var hit: RaycastHit;
    5.  
    6. if (Physics.Raycast(ray, hit)) {
    7.    ...
    8. }
    Then, if you want to get the point a certain distance along the ray, you can use
    Code (csharp):
    1. var distantPoint: Vector3 = ray.GetPoint(distance);