Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
12 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
19
Question by Mattivc · Apr 22, 2010 at 10:57 AM · raycastailimitjavascript-specificfieldofview

Field of view, using raycasting

I am making a AI script. I have already made it so the script checks if the enemy can see the player, based on a raycast that checks if there are any obsticals obscuring the enemy's view of the player.

function CanSeePlayer() : boolean{

 var hit : RaycastHit;
 var rayDirection = playerObject.transform.position - transform.position;

 if (Physics.Raycast (transform.position, rayDirection, hit)) {

     if (hit.transform.tag == "Player") {
         Debug.Log("Can see player");
         return true;
     }else{
         Debug.Log("Can not see player");
         return false;
     }
 }

}

The problem is that this gives the enemy a 360 degree view, how can i restrict it so the enemy can only see the player if the player is within a 135 degree cone in front of the enemy?

Comment
Add comment
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

5 Replies

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

Answer by Mattivc · Apr 22, 2010 at 12:20 PM

I found a solution to the problem, i used Vector3.Angle to detect how far away from the front of the enemy the player is. The code ended up looking like this for anyone that might be interested:

 function CanSeePlayer() : boolean{
 
     var hit : RaycastHit;
     var rayDirection = playerObject.transform.position - transform.position;
 
     if(Physics.Raycast (transform.position, rayDirection, hit)){ // If the player is very close behind the player and in view the enemy will detect the player
         if((hit.transform.tag == "Player") && (distanceToPlayer <= minPlayerDetectDistance)){
         return true;
         }
     }
 
     if((Vector3.Angle(rayDirection, transform.forward)) < fieldOfViewRange){ // Detect if player is within the field of view
         if (Physics.Raycast (transform.position, rayDirection, hit)) {
 
             if (hit.transform.tag == "Player") {
                 //Debug.Log("Can see player");
                 return true;
             }else{
                 //Debug.Log("Can not see player");
                 return false;
             }
         }
     }
 }

             
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 Yamauti · Nov 17, 2012 at 07:12 PM 0
Share

Awesome! This helped a lot!

avatar image jfcool10 · Sep 23, 2013 at 01:28 AM 1
Share

Physics.Raycast has a overloaded method that let you put in the distance which should take out that useless if statement comparing distances and shortened the raycast to the desired length.

avatar image vexe · Jun 02, 2014 at 11:11 AM 3
Share

Shouldn't you be dividing fieldOfViewRange by 2 when you check for your angle? For ex: your AI's fov is 90 dgs facing forward, but then angle between your AI's forward and the direction between your AI and the player is 60 dgs, in this case 60 is less than 90 but the player is actually outside the view cone! So ins$$anonymous$$d of checking for 90, it should be 45 (half the cone). 60 is not less than 45, so it's out of view.

alt text

fov.png (7.8 kB)
avatar image Shahabaz · Apr 03, 2017 at 01:44 AM 0
Share

I think the OP needs a 135 degree fov. So he should've put in that and it would work. You require 180 for the above case to work.

avatar image
15

Answer by agentsmith · Jul 01, 2010 at 12:30 AM

Thanks Mattivc!! This helped me a lot... I tried to figure out what some of your variables are since not all of them were declared in your code snippet. Here's my slightly modified version if anyone wants to check out. Just attach this javascript script to the enemy, drag your player to the playerObject variable, and be sure the player is tagged "Player"

var playerObject : GameObject; // the player var fieldOfViewRange : float; // in degrees (I use 68, this gives the enemy a vision of 136 degrees) var minPlayerDetectDistance : float; // the distance the player can come behind the enemy without being deteacted var rayRange : float; // distance the enemy can "see" in front of him private var rayDirection = Vector3.zero;

function CanSeePlayer() : boolean { var hit : RaycastHit; rayDirection = playerObject.transform.position - transform.position; var distanceToPlayer = Vector3.Distance(transform.position, playerObject.transform.position);

 if(Physics.Raycast (transform.position, rayDirection, hit)){ // If the player is very close behind the enemy and not in view the enemy will detect the player
     if((hit.transform.tag == "Player") && (distanceToPlayer <= minPlayerDetectDistance)){
         //Debug.Log("Caught player sneaking up behind!");
         return true;
     }
 }


 if((Vector3.Angle(rayDirection, transform.forward)) < fieldOfViewRange){ // Detect if player is within the field of view
     if (Physics.Raycast (transform.position, rayDirection, hit, rayRange)) {

         if (hit.transform.tag == "Player") {
             //Debug.Log("Can see player");
             return true;
         }else{
             //Debug.Log("Can not see player");
             return false;
         }
     }
 }

}

function OnDrawGizmosSelected () { // Draws a line in front of the player and one behind this is used to visually illustrate the detection ranges in front and behind the enemy Gizmos.color = Color.magenta; // the color used to detect the player in front Gizmos.DrawRay (transform.position, transform.forward rayRange); Gizmos.color = Color.yellow; // the color used to detect the player from behind Gizmos.DrawRay (transform.position, transform.forward -minPlayerDetectDistance);
}

Comment
Add comment · Show 3 · 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 scarletsnake · Oct 19, 2012 at 11:51 PM 0
Share

I came across this while looking for something else, but was a question mark I had for quite some time. Thanks, both of you :)

avatar image Kaha · Jan 20, 2013 at 07:50 PM 0
Share

This was great help! Thanks.

avatar image Jaqal · Jul 31, 2014 at 02:14 AM 0
Share

I tried using this script and get the debug rays but it seems like the CanSeePlayer function never starts. I'm not sure what I'm doing wrong. I put a debug line at the top of it and it never shows in the console!

avatar image
9

Answer by Augur · Jun 12, 2014 at 08:09 PM

The original question was just about finding the player in front of the enemy, which was exactly what I needed. I took the work of Mattivc and the suggestions of Jfcool10 and vexe and converted it into c# in case anyone else stumbles on this question.

     protected bool CanSeePlayer()
     {
         RaycastHit hit;
         Vector3 rayDirection = Player.transform.position - transform.position;
 
         if ((Vector3.Angle(rayDirection, transform.forward)) <= fieldOfViewDegrees * 0.5f)
         {
             // Detect if player is within the field of view
             if (Physics.Raycast(transform.position, rayDirection, out hit, visibilityDistance))
             {
                 return (hit.transform.CompareTag("Player"));
             }
         }
 
         return false;
     }
 
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
avatar image
2

Answer by jmunozar · Sep 11, 2014 at 05:22 AM

I know this has already been answered but here's a fast, light and easy to use implementation without any physics code of the FOV for 2D http://www.pencilsquaregames.com/2014/09/light-easy-and-fast-field-of-view-2d/ it can be easily be expanded to 3D with some extra thinking.

Comment
Add comment · Show 1 · 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 luislodosm · Apr 22, 2018 at 03:07 PM 0
Share

404 Web not found.

avatar image
0

Answer by andreyakladov · Oct 06, 2020 at 09:04 PM

this is a simple OverlapSphere-based implementation of horizontal field of view:

 IEnumerator FindVisibleTargetsWithDelay() 
     {
         while (true) 
         {
             yield return new WaitForSeconds(visibleTargetsUpdateTimeInterval);
             FindVisibleTargets();
         }
     }
 
     void FindVisibleTargets() 
     {
         mostRelevantTarget = null;
         visibleTargets.Clear();
         var targets = Physics.OverlapSphere(transform.position, radius, targetMask, QueryTriggerInteraction.Ignore);
         foreach (var col in targets)
         {
             var target = col.transform;
             var direction = (target.position - transform.position);
             var horizontalAngle = Vector3.Angle(Vector3.ProjectOnPlane(transform.forward, Vector3.up), Vector3.ProjectOnPlane(target.position, Vector3.up) - Vector3.ProjectOnPlane(transform.position, Vector3.up));
 
             if (horizontalAngle < angle/2) 
             {
                 var distance = Vector3.Distance(transform.position, target.position);
                 if (!Physics.Raycast(transform.position, direction, distance, obstacleMask)) 
                 {
                     var targetInfo = new TargetInfo(target, horizontalAngle, distance);
                     visibleTargets.Add(targetInfo);
                     if (mostRelevantTarget == null)
                     {
                         mostRelevantTarget = targetInfo;
                     }
                     else 
                     {
                         var mrTarget = mostRelevantTarget.Value;
                         if (targetInfo.distance < mrTarget.distance) 
                         {
                             mostRelevantTarget = targetInfo;
                         }
                     }
                 }
             }
         }
     }
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

14 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

Related Questions

Enemy Ai Field of View 0 Answers

Using box collider to determine if AI should stop help 1 Answer

How can I draw a ray for direction object is moving? 1 Answer

Finding RayCastHit's Origin Position 2 Answers

Implementing BUG2 algorithm 0 Answers


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