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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Line Of Sight - How To Go About It?

Discussion in 'Scripting' started by ATLAS-INTERACTIVE, Jan 8, 2017.

  1. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    Over the past few days, I have decided that I need an easy way to tell whether an object is in the camera's line of sight, or, more specifically whether is can be seen or not.

    My ideas was to use an elaborate array of raycasts that cast to a length of 200 or something, and creating an array of objects caught by it, but that doesn't technically provide any way of checking if an object is actually being looked at, it just provides the devs with, basically, a list of objects.

    What I am looking to do, is have an easy way to check whether an object is visible, but as this is not something Unity has any tutorials on despite being quite a basic feature in theory, I am guessing it is a little less simple in practice.

    so, I am here to ask about methods others have used, or any recommendations/pointers anyone can give me, or even a working model which would provide me with a simple detection method to build off of.

    Thanks in advance for any posts :)
     
  2. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    There's no need for an elaborate array...Just a single RaycastAll. The array returned is in order the ray hit.
     
    AlexiTheHusky likes this.
  3. ATLAS-INTERACTIVE

    ATLAS-INTERACTIVE

    Joined:
    Mar 3, 2014
    Posts:
    1,421
    This would only cover a VERY narrow area of the viewport, the purpose of the array would be to cast a ray every 0.1 squared (assuming the viewport was calculated on a 0,1 scale) to create a grid-style layout.

    Having a system which returns multiple objects along just 1 path isn't too useful for this purpose.

    If you meant something else, sorry :p
     
  4. Laperen

    Laperen

    Joined:
    Feb 1, 2016
    Posts:
    1,065
  5. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    Thought that wasn't guaranteed.
     
  6. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    It's not in any tutorials, because it really is a non trivial problem.

    To check if an object is visible at all you have to check the object pixel by pixel to see if any were rendered. As far as I'm aware there isn't a cheap way to do that.

    Maybe some sort of fancy shader magic might work. Basicly something that can set a flag if it draws any pixels on the object of concern. Transparency will be an issue, and will require more magic.

    Otherwise fake it with half a dozen raycasts and be done.
     
    Joe-Censored likes this.
  7. Dameon_

    Dameon_

    Joined:
    Apr 11, 2014
    Posts:
    542
    True fact. Not actually verifying the distances will probably lead to bugs. I'm too used to prototyping with RaycastAll.

    Grid-style layout? I really think you're overthinking this. You should know two parts of the equation.
    1) What's looking
    2) What it's looking for
    You need the third part
    3) Can it see what it's looking for

    A raycast from what's looking to what it's looking for tells you number 3.

    Attempting to find the objects in the first place with raycasts is silly. You know the objects are there, you just need to test if they can be seen. For efficiency's sake, you can have a trigger collider that maintains a list of objects around or in front of the player.
     
    Kiwasi and ericbegue like this.
  8. passerbycmc

    passerbycmc

    Joined:
    Feb 12, 2015
    Posts:
    1,739
    i would do 2 things, do the math to figure out what is in the current players camera frustum, than simply raycast to each object found, to make sure it is not being blocked by an other object.

    to see if something is in the view frustrum you can use WorldToScreenPoint, and simply check if its location is between 0 and the screen width and height
     
  9. GroZZleR

    GroZZleR

    Joined:
    Feb 1, 2015
    Posts:
    3,201
    Use OnBecameVisible and its invisible counterpart combined with a simple FOV check should be good enough.
     
  10. DroidifyDevs

    DroidifyDevs

    Joined:
    Jun 24, 2015
    Posts:
    1,724
    Note that the editor camera will trigger OnBecameVisible as visible as well as the game camera. Also, for some reason it doesn't show in my Console more than 2 times, even though it works.

    Here's how I used it to pause animations that weren't visible in my scene:

    Code (CSharp):
    1. void OnBecameInvisible()
    2.     {
    3.         IsVisible = false;
    4.         //save animation state to use when visible again
    5.         PreviousStaticFrameAnimationState = StaticFrameAnimationState;
    6.         StaticFrameAnimationState = 0;
    7.         Debug.Log("Invisible");
    8.     }
    9.  
    10.     void OnBecameVisible()
    11.     {
    12.         IsVisible = true;
    13.         StaticFrameAnimationState = PreviousStaticFrameAnimationState;
    14.         Debug.Log("Visible");
    15.     }
    Yet "Visible" and "Invisible" show only once in my console, no matter how many times I change the camera's view points. However, the bool (IsVisible) changes, and the Profiler shows a performance boost when I narrow my camera's FOV, so it does work.

    Overall I think it is a very strangely made but incredibly useful function.
     
  11. MV10

    MV10

    Joined:
    Nov 6, 2015
    Posts:
    1,889
    You also have to check the Z, it'll return a position for objects behind the camera. I did it this way using WorldToViewportPoint:

    Code (csharp):
    1.     public static bool IsVisibleToCamera(Transform transform)
    2.     {
    3.         Vector3 visTest = Camera.main.WorldToViewportPoint(transform.position);
    4.         return (visTest.x >= 0 && visTest.y >= 0) && (visTest.x <= 1 && visTest.y <= 1) && visTest.z >= 0;
    5.     }
     
  12. AlexiTheHusky

    AlexiTheHusky

    Joined:
    Jan 11, 2020
    Posts:
    3
    Code (CSharp):
    1.  
    2.         public static bool IsDirectLineBetweenTheseTwo(GameObject one, GameObject two)
    3.         {
    4.             var ray = new Ray(one.transform.position, two.transform.position - one.transform.position);
    5.          
    6.             var hits = Physics.RaycastAll(ray,ray.direction.magnitude);
    7.             if (hits.Length > 0)
    8.             {
    9.                 foreach (var hit in hits)
    10.                 {
    11.                     //Ignore the two input objs
    12.                     if (hit.collider.gameObject == one || hit.collider.gameObject == two) continue;
    13.                    
    14.                     //Debug.DrawLine(one.transform.position, hit.collider.transform.position,Color.red,1);
    15.                     //Debug.DrawLine(one.transform.position, two.transform.position, Color.blue, 1);
    16.                     //Debug.Log($"Interferred by {hit.collider.gameObject.name}");
    17.                     return false;
    18.                 }
    19.             }
    20.             //Debug.DrawLine(one.transform.position, two.transform.position, Color.green,1);
    21.             return true;
    22.         }
     
  13. vasanijeet48

    vasanijeet48

    Joined:
    Mar 29, 2020
    Posts:
    6

    Hey!!
    There is a video series by sebastian league on this try it out

    https://www.youtube.com/playlist?list=PLFt_AvWsXl0dohbtVgHDNmgZV_UY7xZv7