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