Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by dylan1812 · Jun 16, 2020 at 03:48 PM · 2draycastraycastingfieldofview

Unity 2D: Visualise a field of view cone

Good Afternoon, I'm trying to implement a field of view cone for my enemy where if the player enters this cone the enemy will chase them. I have worked out the logic for the enemy regarding the player detection. Now I need to visualise the cone in the gameview to show the user the area they will be spotted. An important feature of this cone is that it wont pass through objects with the layer tag "obstacle" this way the player has hiding spots.

The Image below demonstates how I have used raycasts to show the side boundaries of the view cone and also to the vertices of the object from the enemy (this probably isn't ideal since my object might have many vertices and at the moment I need to input the vertex positions manually in the inspector which is tedious). I believe all I need to do is "fill in" the gaps between the raycasts but im unsure how easy this is to do.

Here is the mentioned image (The "G" shape is an obstacle):alt text

And here is the code I have so far:

 using System;
 using System.Collections;
 using System.Collections.Generic;
 using UnityEngine;
 
 public class EnemyFOV : MonoBehaviour
 {
 
     [SerializeField] private List<Vector3> obstacleVertices; // a list of all the obstabcle vertices in the level
     [SerializeField] private List<Vector3> obstacleVerticesInRange = new List<Vector3>(); // a list of the obstacle vertices that will be within the enemy's FOV
     [SerializeField] private float enemyViewDistance; // the max distance the enemy can see
     [SerializeField] [Range(0, Mathf.PI)] private float enemyViewAngle; // the angle above and below the horizontal axis the enemy can see
     [SerializeField] private LayerMask hitLayers; // the layers the enemy can't see through
     [SerializeField] private RaycastHit2D boundLineTop;  // the top bounding line of the cone
     [SerializeField] private RaycastHit2D boundLineBottom; // the bottom bounding line of the cone
 
     // Update is called once per frame
     void Update()
     {
         bool movingRight = GetComponent<EnemyMovement>().movingRight; // get which way the enemy is facing so we know where to search for obstacle vertices
         int sign = 0;
         // get a list off all the obstical vertices in the enemy's FOV
         obstacleVerticesInRange = new List<Vector3>(); // clear the list of vertices in range
         for (int vertexIndex = 0; vertexIndex < obstacleVertices.Count; vertexIndex++) // for each element of the list
         {
             // find the angle between the two positions
             Vector2 direction = new Vector2(obstacleVertices[vertexIndex].x - transform.position.x, obstacleVertices[vertexIndex].y - transform.position.y);
             if (obstacleVertices[vertexIndex].y > transform.position.y)
             {
                 sign = 1;
             }
             else
             {
                 sign = -1;
             }
             float angle = Vector2.Angle(Vector2.right, direction) * sign * (Mathf.PI / 180);
 
             if (Vector3.Distance(obstacleVertices[vertexIndex], transform.position) <= enemyViewDistance && ((movingRight && Mathf.Abs(angle) <= enemyViewAngle) || (!movingRight && Mathf.Abs(Mathf.PI - angle) <= enemyViewAngle))) 
             {
                 obstacleVerticesInRange.Add(obstacleVertices[vertexIndex]); // add the object to the List
                 // Send a raycast from the enemy to the vertex
                 Vector3 origin = transform.position;
                 RaycastHit2D sightLine = Physics2D.Raycast(origin, direction, enemyViewDistance, hitLayers); // creates a raycast from the enemy in the direction of the obstacle vertex colliding only with the listed layers
                 //TODO chuck out a ray at the angles of view of enemy
                 // simulate the raycast (for demonstration purposes)
                 if (sightLine.collider) // if the ray has hit an obsticle 
                 {
                     UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), sightLine.point, Color.red); // if a collider is hit draw from enemy to collision point
                 }
                 else
                 {
                     UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), new Vector2(transform.position.x, transform.position.y) + direction * enemyViewDistance, Color.white);
                 }
             }
 
             // also send the rays of the sides of the FOV cone
             Vector2 pointOnTopLine;
             Vector2 pointOnBottomLine;
             if (movingRight)
             {
                 pointOnTopLine.x = enemyViewDistance * Mathf.Cos(enemyViewAngle) + transform.position.x;
                 pointOnTopLine.y = enemyViewDistance * Mathf.Sin(enemyViewAngle) + transform.position.y;
                 pointOnBottomLine.x = enemyViewDistance * Mathf.Cos(enemyViewAngle) + transform.position.x;
                 pointOnBottomLine.y = enemyViewDistance * -Mathf.Sin(enemyViewAngle) + transform.position.y;
             }
             else
             {
                 pointOnTopLine.x = enemyViewDistance * Mathf.Cos(Mathf.PI - enemyViewAngle) + transform.position.x;
                 pointOnTopLine.y = enemyViewDistance * Mathf.Sin(Mathf.PI - enemyViewAngle) + transform.position.y;
                 pointOnBottomLine.x = enemyViewDistance * Mathf.Cos(Mathf.PI - enemyViewAngle) + transform.position.x;
                 pointOnBottomLine.y = enemyViewDistance * -Mathf.Sin(Mathf.PI - enemyViewAngle) + transform.position.y;
             }
 
             // visualise the boundaries
             UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), pointOnTopLine, Color.yellow);
             UnityEngine.Debug.DrawLine(new Vector2(transform.position.x, transform.position.y), pointOnBottomLine, Color.yellow);
         }
     }
 }

I should mention I'm new to Unity and coding so thank you for your patience!

fovproblem.png (16.2 kB)
Comment
Add comment · Show 4
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Namey5 · Jun 17, 2020 at 09:33 AM 1
Share

You are nearly there with the logic for creating the field of view visualisation and occlusion, but to make things simpler rather than raycasting specific vertices, you can cast rays at an even rate throughout the cone to get an approximation of scene occlusion (the more rays, the closer it gets). From there you can use those rays to generate and fill in triangles on a mesh. This tutorial series by Sebastian Lague does exactly what you are looking for and explains it thoroughly along the way.

avatar image dylan1812 Namey5 · Jun 17, 2020 at 03:04 PM 0
Share

Thank you for the video link, its very informative. This will need to be applied to all enemies in the level however, would this option hurt the performance of the game? Im estimating ~=400 raycasts (20 casts for 20 enemies) in total using this method.

avatar image Namey5 dylan1812 · Jun 18, 2020 at 12:15 AM 1
Share

Chances are it isn't going to be cheap regardless of option. There are a few ways to optimise it however - using binary search to use fewer samples for greater precision, restricting possible raycast checks using a sphere-test, etc. You could also only run the effect when an enemy's view cone is on screen (I would imagine you would only ever have a few enemies on screen at any one time).

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
1
Best Answer

Answer by FeedMyKids1 · Jun 18, 2020 at 12:22 AM

Sebastian Lague did it in 3d - but really it could be considered 2d since it was top down...

He creates a dynamic mesh on the fly.

https://www.youtube.com/watch?v=rQG9aUWarwE&list=PLFt_AvWsXl0dohbtVgHDNmgZV_UY7xZv7

Hopefully that's what you're talking about.

Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dylan1812 · Jun 18, 2020 at 12:58 AM 0
Share

Thank you for the link, it pretty much does exactly what I need. This coupled with the advice Namey5 gave me solves my problem!

avatar image FeedMyKids1 dylan1812 · Jun 18, 2020 at 09:49 PM 0
Share

Glad to here it's what you needed.

avatar image
0

Answer by N-8-D-e-v · Jun 17, 2020 at 04:37 PM

There is a better (and much more performant way to do this, using Vector calculus. https://gamedev.net/tutorials/programming/math-and-physics/vector-maths-for-game-dev-beginners-r5442/ check out this article and read about dot product, I am making a stealth game (in 3d) right now, and I've used this method and it's worked great

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image dylan1812 · Jun 17, 2020 at 04:54 PM 0
Share

I assumed that the Vector2.Angle used the dot product to find the angle. In any case, which angles would I be finding using the dot product? Or are you suggesting I do what im doing but use the dot product ins$$anonymous$$d of Vector2.Angle?

avatar image N-8-D-e-v dylan1812 · Jun 17, 2020 at 05:02 PM 0
Share

I would just do this

 Quaternion look = Quaternion.LookRotation(enemy.position - player.position).normalized; //finds difference in rotation, normalizing makes the value independent of the magnitude (distance apart)
 
 if (Vector2.Dot(transform.right, look) > 0.1f) //transform.right is the direction it's looking, if dot product is > 0 the player is in front of the enemy
 {
 //do whatever
 } 

It's much simpler

avatar image dylan1812 N-8-D-e-v · Jun 17, 2020 at 05:37 PM 0
Share

I think maybe I wasn't very clear with what i wanted. I'm not stuck with getting the enemy to detect the player. Rather, I'm stuck with just displaying the field of view cone.

Show more comments
avatar image
0

Answer by JonPQ · Jun 18, 2020 at 06:07 PM

Why not use a 2D lighting solution from the asset store? this one is free... https://assetstore.unity.com/packages/tools/particles-effects/hard-light-2d-152208

OR to build it yourself... I think you'd need to iterate through all of your scene objects/blocks finding near and far corners, then projecting them in 2D onto a virtual plane or a circle represented in a list of run-length data.... the list would be a list of pretty much 2 states.... I can see clearly to the max distance ( to the plane), or it is blocked by an object... then you enter in sorted z-co-ordinate / ranges into the list, sorted by view angle from top to bottom of the view arc. This would also work for objects 'shadowed'/hidden by other objects... you wouldn't enter those values in the list as they are hidden but other items already in the list that are closer. You need to do some vector 2d math here.... especially for partially hidden line segments. Or you could actually draw into it like a z-buffer.

Then to re-render it.... you'd walk the list, from tip to bottom.... building and rendering triangles like a fan. You could either render shadows, or light.... view cones, or blocked view areas....

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

313 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Raycast to ignore caster (Not by layer) 1 Answer

Need help to convert this raycasting 3d Script into a 2D x&y version 0 Answers

Cast multiple rays from an object between two angles? 0 Answers

Raycasting not working as expected: rays are perpendicular to projectile's trajectory and collision doesn't occur 1 Answer

2D Raycast not working 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges