Unity3d Learning (V): Achieving a simple visual perception

Source: Internet
Author: User
Tags emit

Objective

In many first-person or third-person shooter games, the player's fun often comes from battles with various AI enemies. The outbreak of the battle is often due to the AI shooting at the player immediately after "seeing" the player,

So how did these AI detect, or "see" the player's position?

Examples of Others

refer to the game known to cat watching AI Combat (ii) Visual perception of the preliminary article.

In this article, the original author allows the player to stand at the enemy's point of view to detect the target, by firing a bunch of rays into a certain sector of the front to detect the position of the target, such as:

Although this method is relatively simple to implement, it has two drawbacks:

1. The launch of a large number of rays at the same time is not good for the optimization of the game itself, and it is easy to cause the Dayton.

2. If the object to be probed is small and even smaller than the distance between the two rays, the ray cannot detect the object.

Another way to solve this problem

In the original commentary, it was mentioned that a sphere could be built on the detector itself to detect surrounding objects.

So we can build a sphere detection area using Unity's own sphere trigger or the overlaps in physics, such as:

Here I use the overlaps, the code is as follows:

The player, the explorer

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityengine; Public classPlayer:monobehaviour { Public floatMovespeed;//Moving Speed     Public floatEyeviewdistance;//Vision Distance     Public floatViewangle = 120f;//Visual Angle    PrivateRigidbody RB; PrivateCollider[] spottedenemies;//nearby enemies.//Use this for initialization    voidStart () {RB= getcomponent<rigidbody>(); }    Private voidfixedupdate () {detectenemy (); }    //Update is called once per frame    voidUpdate () {//Automove ();Moveandturn (); Debug.drawline (transform.position, Transform.forward* -, color.red);//Red Ray, the direction of the face    }    voidAutomove ()//to move automatically in the direction of the face{transform.position+ = Transform.forward * Movespeed *Time.deltatime; }    voidMoveandturn ()//player Move{Ray Ray=Camera.main.ScreenPointToRay (input.mouseposition); Raycasthit Hitinfo=NewRaycasthit (); //shoot a ray from cam to mouse position which are only detected by Gameobject with "Plane" layer.Physics.raycast (Ray, outHitinfo, -, Layermask.getmask ("Plane")); if(Hitinfo.collider! =NULL) {transform. LookAt (NewVector3 (Hitinfo.point.x, TRANSFORM.POSITION.Y, hitinfo.point.z)); } rb.velocity=NewVector3 (Input.getaxisraw ("Horizontal"),0, Input.getaxisraw ("Vertical"). Normalized *Movespeed; }    voidDetectenemy ()//Detecting Enemies    {        //enemies within the OverlapsphereSpottedenemies = Physics.overlapsphere (transform.position, Eyeviewdistance, Layermask.getmask ("Enemy"));  for(inti =0; i < spottedenemies.length;i++)//detects if each enemy is in the field of view{Vector3 enemyposition= Spottedenemies[i].transform.position;//the position of the enemy//Debug.Log (Transform.forward + "facing direction"); //Debug.Log ("angle:" + vector3.angle (Transform.forward, enemyposition-transform.position));Debug.drawray (transform.position, Enemyposition-Transform.position, Color.yellow);//vector of player position to enemy position            if(Vector3.angle (Transform.forward, enemyposition-transform.position) <= viewangle/2)//whether the enemy is in the field of view            {                //if within the field of viewRaycasthit info =NewRaycasthit (); intLayermask = Layermask.getmask ("Enemy","obstacles");//specifies the object that the ray collides withPhysics.raycast (Transform.position, Enemyposition-transform.position, outInfo,eyeviewdistance,layermask);//firing rays at the enemy's locationDebug.Log (info.collider.gameObject.name); if(Info.collider = = Spottedenemies[i])//If there are no obstructions on the way, the Rays collide with the enemy.{discoveredenemy (spottedenemies[i]); }            }        }    }    voidDiscoveredenemy (Collider Enemy)//Find the enemy    {        //Do somethingDebug.Log ("Find the Enemy:"+Enemy.gameObject.name); Enemy.getcomponent<Enemy>().    Bediscovered (); }}

Spottedenemies is an array of collider that I use to hold all the enemy objects in this frame that are in the sphere area of the overlapsphere, (Layermask can let the overlaps sphere interact with only the objects of the specified layer). Then calculate the angle Vector3.angle (Transform.forward, enemyposition-transform.position) that the player faces and the direction of the target detected, such as:

The Forwar vector represents the direction the player faces, and the V1 represents the direction of the detected object relative to the player's position, and the red sector area represents the player's field of view. Then calculate the angle between the two vectors, and then determine whether the angle is less than half the angle of the sector (that is, whether the target is in the player's view) on the line. If the angle is less than half the angle of the field of view, then we emit a ray to the target and see if the object that the ray collides with is the target object, because if there is an obstacle between the player and the target, then the ray is blocked by an obstacle (that is, the player's "view" is obscured by the obstacle).

Enemy, the target being probed.

This sets the detected target to go back to stealth after a certain amount of time from the player's field of view.

usingSystem.Collections;usingSystem.Collections.Generic;usingUnityengine; Public classEnemy:monobehaviour { Public floatHidecooldown =0.3f;//Hide your cooling time     Public floatAppeartime;//The last time I was found    PrivateMeshrenderer Mr; //Use this for initialization    voidAwake () {Mr= getcomponent<meshrenderer>(); }    Private voidStart () {mr.enabled=false; }    //Update is called once per frame    voidUpdate () {if(Time.time-appeartime <Hidecooldown)return; if(mr.enabled) mr.enabled=false; }     Public voidBediscovered ()//was found.{mr.enabled=true; Appeartime=Time.time; }}

The final implementation is as follows:

This method does not emit large amounts of radiation, and only emits rays to objects that are in the field of vision that enter the sphere detection area, and also avoids the bug that small objects cannot be detected.

Resources

do you know that most of the events in U3D development are judged by mathematical calculations? Highest ticket answer Meta42cat watching Game AI Combat (ii) Visual perception preliminary horse Haruka

Unity3d Learning (V): Achieving a simple visual perception

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.