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

Question How to draw line between 2 hits?

Discussion in 'Scripting' started by lw_wh, Mar 10, 2023.

  1. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Hello,
    I'm trying to draw a straight line between 2 hits on objects in my quest vr game and get the length of this line.
    How can i do that?
    I now have this. But it didn't work. I get no response.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class Line : MonoBehaviour
    6. {
    7.     RaycastHit hit;
    8.     Transform p0 = null;
    9.     Transform p1 = null;
    10.     Transform container;
    11.  
    12.     Vector3 h0;
    13.     Vector3 h1;
    14.     int i = 0;
    15.     float distance;
    16.  
    17.     // Start is called before the first frame update
    18.     void Start()
    19.     {
    20.    
    21.     }
    22.  
    23.     // Update is called once per frame
    24.     void Update()
    25.     {
    26.         if(Input.GetKey(KeyCode.JoystickButton1))
    27.         {
    28.             if(Physics.Raycast(transform.position, transform.forward, out hit) && Input.GetKey(KeyCode.JoystickButton2))
    29.             {
    30.                 if(!p0 && !p1)
    31.                 {
    32.                     p0 = hit.transform;
    33.                     h0 = hit.point;
    34.                     return;
    35.                 }
    36.                 if(p0 && !p1)
    37.                 {
    38.                     p1 = hit.transform;
    39.                     h1 = hit.point;
    40.                     return;
    41.                 }
    42.                 if(p0 && p1)
    43.                 {
    44.                     LineRenderer line = new GameObject("Line " +i.ToString()).AddComponent<LineRenderer>();
    45.                     line.transform.parent = container;
    46.                     line.startWidth = 0.05f;
    47.                     line.endWidth = 0.05f;
    48.                     line.startColor = Color.green;
    49.                     line.endColor = Color.red;
    50.                     line.positionCount = 2;
    51.                     line.SetPosition(0, h0);
    52.                     line.SetPosition(1, h1);
    53.                     distance = Vector3.Distance(h0,h1);
    54.                
    55.                     p1 = null;
    56.                     p0 = null;
    57.  
    58.                     Debug.Log("Distance: " + distance);
    59.                 }
    60.             }
    61.             }
    62.         }
    63.     }
    64. }
    Can somebody help me with this?
    thanks
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    How to report your problem productively in the Unity3D forums:

    http://plbm.com/?p=220

    This is the bare minimum of information to report:

    - what you want
    - what you tried
    - what you expected to happen
    - what actually happened, especially any errors you see
    - links to documentation you used to cross-check your work (CRITICAL!!!)

    You may edit your post above.

    If you have no idea what your code is doing, time to start debugging!

    You must find a way to get the information you need in order to reason about what the problem is.

    Once you understand what the problem is, you may begin to reason about a solution to the problem.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling
    Debug.Log()
    statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    If you are working in VR, it might be useful to make your on onscreen log output, or integrate one from the asset store, so you can see what is happening as you operate your software.

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    When in doubt, print it out!(tm)

    Note: the
    print()
    function is an alias for Debug.Log() provided by the MonoBehaviour class.
     
  3. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Yes, excuse me. You are wright. I will give more information and will place also soon the logs in the code in this form.
    I tested first with a debug.log in the first if(input mouseclick) (because i first test with mouse, than in vr) or i get reaction. And i get reaction. But in the second if i get with 1 click 4 time a debug log ("click1") and after the second click i get ("click2") but the distance is always 0. First and second click seems on the same place.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    That's great! Now find out how the two are being set the same.

    Are you inadvertently setting both?

    Is one copying to the other?

    Was something wrong with the first click originally?

    etc etc etc

    You gotta chase it to ground because nobody here can do it for you.
     
  5. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    I'm testing. First clicking left mouse click somewhere, than right click somewhere else. Because when i use only leftclick both the ifs will be fired in the void update. I get a response with the same coordinates (strange coordinates) also when a hit another place and 3 seconds later.

    Code (CSharp):
    1.     void Update()
    2.     {
    3.         if (Physics.Raycast(transform.position, transform.forward, out hit) && (Input.GetKey(KeyCode.Mouse0)))
    4.         {
    5.             if (!p0 && !p1)
    6.             {
    7.                 p0 = hit.transform;
    8.                 h0 = hit.point;
    9.                 Debug.Log("h0 ingevuld");
    10.                 Debug.Log(h0);
    11.                 //return;
    12.             }
    13.         }
    14.  
    15.         if (Physics.Raycast(transform.position, transform.forward, out hit) && (Input.GetKey(KeyCode.Mouse1)))
    16.         {
    17.             if (p0 && !p1)
    18.             {
    19.                 p1 = hit.transform;
    20.                 h1 = hit.point;
    21.                 Debug.Log(h1);
    22.                 Debug.Log("h1 ingevuld");
    23.                 //return
    24.             }
    upload_2023-3-13_11-25-29.png
     
  6. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Making progress. I now see i a purple line and get a distance (i think its distance:) in the log. But its better when i must hit the same button instead of 2 different one.
    And after getting the distance i must clear(destroy) the line with a button. Thats not a big problem. Changing 2 different buttons to 1 is a bigger issue.


    Code (CSharp):
    1.     RaycastHit hit;
    2.     Transform p0 = null;
    3.     Transform p1 = null;
    4.     Transform container;
    5.     Vector3 h0;
    6.     Vector3 h1;
    7.     int i = 0;
    8.     float distance;
    9.  
    10.     void Update()
    11.     {
    12.         if (Physics.Raycast(transform.position, transform.forward, out hit) && (Input.GetKey(KeyCode.Mouse0)))
    13.         {
    14.             if (!p0 && !p1)
    15.             {
    16.                 p0 = hit.transform;
    17.                 h0 = hit.point;
    18.                 Debug.Log("h0 ingevuld");
    19.                 Debug.Log(h0);
    20.                 //return;
    21.             }
    22.         }
    23.  
    24.         if (Physics.Raycast(transform.position, transform.forward, out hit) && (Input.GetKey(KeyCode.Mouse1)))
    25.         {
    26.             if (p0 && !p1)
    27.             {
    28.                 p1 = hit.transform;
    29.                 h1 = hit.point;
    30.                 Debug.Log(h1);
    31.                 Debug.Log("h1 ingevuld");
    32.                 //return
    33.             }
    34.              
    35.             if (p0 && p1)
    36.             {
    37.                 LineRenderer line = new GameObject("Line " + i.ToString()).AddComponent<LineRenderer>();
    38.                 line.transform.parent = container;
    39.                 line.startWidth = 100f;
    40.                 line.endWidth = 100f;
    41.                 line.startColor = Color.green;
    42.                 line.endColor = Color.red;
    43.                 line.positionCount = 2;
    44.                 line.SetPosition(0, h0);
    45.                 line.SetPosition(1, h1);
    46.                 distance = Vector3.Distance(h0, h1);
    47.  
    48.                 p1 = null;
    49.                 p0 = null;
    50.  
    51.                 Debug.Log("Distance: " + distance);
    52.  
    53.             }
     
    Last edited: Mar 13, 2023
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Your main issue here is that GetKey returns true while the key is held down. It is true as long as the key is down which is usually several frames. When you want to detect a single key press, you want to use GetKeyDown instead. This will only return true for one frame. The frame that the key was pressed down first. The key needs to be relased and pressed again in order to be true again.

    It also doesn't make much sense to do two identical raycasts. It makes more sense to do something like this:

    Code (CSharp):
    1.  
    2.     void Update()
    3.     {
    4.         if (Input.GetKeyDown(KeyCode.Mouse0))
    5.         {
    6.             if (Physics.Raycast(transform.position, transform.forward, out hit))
    7.             {
    8.                 if (!p0)
    9.                 {
    10.                     p0 = hit.transform;
    11.                     h0 = hit.point;
    12.                 }
    13.                 else
    14.                 {
    15.                     h1 = hit.point;
    16.                     LineRenderer line = new GameObject("Line " + i.ToString()).AddComponent<LineRenderer>();
    17.                     line.transform.parent = container;
    18.                     line.startWidth = 100f;
    19.                     line.endWidth = 100f;
    20.                     line.startColor = Color.green;
    21.                     line.endColor = Color.red;
    22.                     line.positionCount = 2;
    23.                     line.SetPosition(0, h0);
    24.                     line.SetPosition(1, h1);
    25.                     distance = Vector3.Distance(h0, h1);
    26.                     p0 = null;
    27.                 }
    28.             }
    29.         }
    30.     }
     
  8. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Thanks for the explenation and the shorter way. Last thing i gone do is to use the distance and place that somewhere in my menu. And create a button to delete the line.
     
  9. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Hello,
    I have a question. I placed the script under a other GameObject (button). First it was under the Main Camera, but i get not the world coordinates (0,0,345) and the line does not come on the places a shoot. The lenght and distance was good but the line was further away.
    Now i get x,y,z coordinates(world i think). But h0 and h1 stays the same and the distance is than 0. Destroying the line (gameobject) is also going wrong. He finds the line but doesnt destroy it.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5. using TMPro;
    6.  
    7. public class Meetlint : MonoBehaviour
    8. {
    9.     RaycastHit hit;
    10.     Transform p0 = null;
    11.     Transform container;
    12.     Vector3 h0;
    13.     Vector3 h1;
    14.     //int i = 0;
    15.     float distance;
    16.     float distanceschaal;
    17.     public GameObject Line;
    18.     public GameObject Dropdown;
    19.     public TMPro.TextMeshProUGUI Afstand;
    20.  
    21.     public void Meten()
    22.     {
    23.         if (GameObject.Find("Line") != null)
    24.         {
    25.             GameObject.Destroy(Line);
    26.             Debug.Log("delete line");
    27.         }
    28.         else
    29.         {
    30.             Debug.Log("er is geen lijn");
    31.         }
    32.     }
    33.  
    34.  
    35.     void Update()
    36.     {
    37.         if (Input.GetKeyDown(KeyCode.Mouse1))
    38.         {
    39.             if (Physics.Raycast(transform.position, transform.forward, out hit))
    40.             {
    41.                 if (!p0)
    42.                 {
    43.                     p0 = hit.transform;
    44.                     h0 = hit.point;
    45.                     Debug.Log("h0 ingevuld");
    46.                     Debug.Log(h0);
    47.                 }
    48.                 else
    49.                 {
    50.                     h1 = hit.point;
    51.                     Debug.Log("h1 ingevuld");
    52.                     Debug.Log(h1);
    53.                     LineRenderer line = new GameObject("Line").AddComponent<LineRenderer>();
    54.                     line.transform.parent = container;
    55.                     line.startWidth = 10f;
    56.                     line.endWidth = 10f;
    57.                     line.startColor = Color.green;
    58.                     line.endColor = Color.red;
    59.                     line.positionCount = 2;
    60.                     line.SetPosition(0, h0);
    61.                     line.SetPosition(1, h1);
    62.                     distance = Vector3.Distance(h0, h1);
    63.                     Dropdown = GameObject.FindWithTag("Dropdown");
    64.                     if (Dropdown.transform.localScale.x == 0f)
    65.                     {
    66.                         Debug.Log("Distance: " + distance);
    67.                         distanceschaal = distance;
    68.                         Afstand.text = distanceschaal.ToString();
    69.                     }
    70.                     else
    71.                     {
    72.                         Debug.Log("Distance: " + distance);
    73.                         distanceschaal = distance/500f;
    74.                         Afstand.text = distanceschaal.ToString();
    75.                     }
    76.                     p0 = null;
    77.  
    78.                 }
    79.             }
    80.         }
    81.     }
    82. }
    upload_2023-3-15_12-5-36.png
     
    Last edited: Mar 15, 2023
  10. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Why i get the same coordinates again on h0 and h1. I shoot on a different place.
     
  11. FrankvHoof

    FrankvHoof

    Joined:
    Nov 3, 2014
    Posts:
    258
    Are you actually moving the camera in between your two hits?
    Because you're simply shooting a ray straight out of the front of the camera.
    Clicking in different positions on the screen will thus still give you the same ray.
     
  12. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    I find it little bit confusing, because i want to use my lefthand laser with the x (JoystickButton4) button to hit something not from the camera (see picture below). Now i have my script placed in a empty Gameobject outside the XR RIG.. Must i place it in the lefthand controller? Or is that not important.
    upload_2023-3-18_9-50-10.png
     
  13. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    Hello Frank, How can i fix this. I get the same coordinates every time. Doesnt matter in which gameobject i place the script. I also use a gameobject.transform.position = hit.point and the gameobject is placed on the same place. And
    hit.transform.name gives me the same name.
     
    Last edited: Mar 20, 2023
  14. lw_wh

    lw_wh

    Joined:
    Nov 1, 2021
    Posts:
    21
    It works now. The problem was that testing in Unity is going wrong (my videocard is not good enough for the Oculus app and then also for the preview mode of Unity). After building on the Quest it is perfect with the right button(JoystickButton2) and placing the script under the lefthand controller which has that button.

    Code (CSharp):
    1.    void Update()
    2.     {
    3.         if (Input.GetKeyDown(KeyCode.JoystickButton2))
    4.         {
    5.             if (Physics.Raycast(transform.position,transform.forward, out hitData))
    6.             {
    7.                 if (hitData.collider.gameObject.tag == "Water")
    8.                 {