|  | 
 
| C#js脚本复制代码using UnityEngine;
using System.Collections;
public class EnemySight : MonoBehaviour
{
        public float fieldOfViewAngle = 110f;                               // 机器巡逻兵视野的角度.
        public bool playerInSight;                                          // 玩家是不是处于机器巡逻兵的视野中.
        public Vector3 personalLastSighting;                                // 机器巡逻兵最后一个看到玩家的地点.
        
        
        private NavMeshAgent nav;                                           // Reference to the NavMeshAgent component.
        private SphereCollider col;                                         // Reference to the sphere collider trigger component.
        private Animator anim;                                              // Reference to the Animator.
        private LastPlayerSighting lastPlayerSighting;                      // Reference to last global sighting of the player.
        private GameObject player;                                          // Reference to the player.
        private Animator playerAnim;                                        // Reference to the player's animator component.
        private PlayerHealth playerHealth;                                  // Reference to the player's health script.
        private HashIDs hash;                                               // Reference to the HashIDs.
        private Vector3 previousSighting;                                   // 玩家在视野中的最后一个位置.
        
        
        void Awake ()
        {
                // 初始化成员.
                nav = GetComponent<NavMeshAgent>();
                col = GetComponent<SphereCollider>();
                anim = GetComponent<Animator>();
                lastPlayerSighting = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<LastPlayerSighting>();
                player = GameObject.FindGameObjectWithTag(Tags.player);
                playerAnim = player.GetComponent<Animator>();
                playerHealth = player.GetComponent<PlayerHealth>();
                hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<HashIDs>();
                
                // 设置玩家的发现位置的初始值为resetPosition(1000,1000,1000).
                personalLastSighting = lastPlayerSighting.resetPosition;
                previousSighting = lastPlayerSighting.resetPosition;
        }
        
        
        void Update ()
        {
                // 如果玩家处于警报状态...
                if(lastPlayerSighting.position != previousSighting)
                        // ... 设置玩家最后的发现位置为玩家的当前坐标.
                        personalLastSighting = lastPlayerSighting.position;
                
                // 设置视野内玩家位置为当前玩家坐标.
                previousSighting = lastPlayerSighting.position;
                
                // 如果玩家是活的...
                if(playerHealth.health > 0f)
                        // ... 设置玩家动画控制器中的playerInSightBool变量为playerInSight.
                        anim.SetBool(hash.playerInSightBool, playerInSight);
                else
                        // ... 如果玩家已经死了,就设置playerInSightBool为false.
                        anim.SetBool(hash.playerInSightBool, false);
        }
        
        
        void OnTriggerStay (Collider other)
        {
                // 如果进入触发区域的是玩家...
                if(other.gameObject == player)
                {
                        // 设置默认的playerInSight状态为不可见.
                        playerInSight = false;
                        
                        // 创建一个变量 记录从机器人到玩家的方向向量.
                        Vector3 direction = other.transform.position - transform.position;
                        // 求得机器人正方向和玩家之间的角度
                        float angle = Vector3.Angle(direction, transform.forward);
                        
                        // 如果玩家处于视野内...
                        if(angle < fieldOfViewAngle * 0.5f)
                        {
                                RaycastHit hit;
                                
                                // ... 从机器人的身高部位向玩家发射一条射线...
                                if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))
                                {
                                        // ... 射线触碰到了玩家...
                                        if(hit.collider.gameObject == player)
                                        {
                                                // ... 玩家在视野内,被发现了,设置标志位为true.
                                                playerInSight = true;
                                                
                                                // 将警报标志位的坐标设定为玩家当前坐标.
                                                lastPlayerSighting.position = player.transform.position;
                                        }
                                }
                        }
                        
                        // 获取动画层0和动画层1两层当前的动画播放状态机.
                        int playerLayerZeroStateHash = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
                        int playerLayerOneStateHash = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
                        
                        // 如果玩家现在正处于行走或者呼唤状态(有声音)...
                        if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)
                        {
                                // ... 并且玩家处于机器人的监听范围内...
                                if(CalculatePathLength(player.transform.position) <= col.radius)
                                        // ... 设置玩家当前位置为发现角色的位置.
                                        personalLastSighting = player.transform.position;
                        }
                }
        }
        
        
        void OnTriggerExit (Collider other)
        {
                // 如果玩家离开了机器巡逻的监测区域...
                if(other.gameObject == player)
                        // ... 视野失去目标.
                        playerInSight = false;
        }
        
        //--------------------------------------------------------------------
        // 计算一条路径,返回需要走的步数
        //--------------------------------------------------------------------
        float CalculatePathLength (Vector3 targetPosition)
        {
                // 生成一个变量记录自动寻路的路径.
                NavMeshPath path = new NavMeshPath();
                if(nav.enabled)
                        nav.CalculatePath(targetPosition, path);
                
                // 创建一个保存自动寻路节点的数组.数组的大小比实际的寻路节点多2个
                Vector3 [] allWayPoints = new Vector3[path.corners.Length + 2];
                
                // 第一个节点存的是机器人当前坐标.
                allWayPoints[0] = transform.position;
                
                // 最后一个存的是玩家的坐标.
                allWayPoints[allWayPoints.Length - 1] = targetPosition;
                
                // 中间的存的是自动寻路的路径节点.
                for(int i = 0; i < path.corners.Length; i++)
                {
                        allWayPoints[i + 1] = path.corners[i];
                }
                
                //  步长变量.
                float pathLength = 0;
                
                // 计算每一个节点之间的长度,并将这些长度加起来.
                for(int i = 0; i < allWayPoints.Length - 1; i++)
                {
                        pathLength += Vector3.Distance(allWayPoints[i], allWayPoints[i + 1]);
                }
                
                return pathLength;
        }
}
复制代码#pragma strict
public var fieldOfViewAngle : float = 110f;             // Number of degrees, centred on forward, for the enemy see.
public var playerInSight : boolean;                     // Whether or not the player is currently sighted.
public var personalLastSighting : Vector3;              // Last place this enemy spotted the player.
private var nav : NavMeshAgent;                         // Reference to the NavMeshAgent component.
private var col : SphereCollider;                       // Reference to the sphere collider trigger component.
private var anim : Animator;                            // Reference to the Animator.
private var lastPlayerSighting : LastPlayerSighting;    // Reference to last global sighting of the player.
private var player : GameObject;                        // Reference to the player.
private var playerAnim : Animator;                      // Reference to the player's animator component.
private var playerHealth : PlayerHealth;                // Reference to the player's health script.
private var hash : HashIDs;                             // Reference to the HashIDs.
private var previousSighting : Vector3;                 // Where the player was sighted last frame.
function Awake ()
{
    // Setting up the references.
    nav = GetComponent(NavMeshAgent);
    col = GetComponent(SphereCollider);
    anim = GetComponent(Animator);
    lastPlayerSighting = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent(LastPlayerSighting);
    player = GameObject.FindGameObjectWithTag(Tags.player);
    playerAnim = player.GetComponent(Animator);
    playerHealth = player.GetComponent(PlayerHealth);
    hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent(HashIDs);
    
    // Set the personal sighting and the previous sighting to the reset position.
    personalLastSighting = lastPlayerSighting.resetPosition;
    previousSighting = lastPlayerSighting.resetPosition;
}
function Update ()
{
    // If the last global sighting of the player has changed...
    if(lastPlayerSighting.position != previousSighting)
        // ... then update the personal sighting to be the same as the global sighting.
        personalLastSighting = lastPlayerSighting.position;
    
    // Set the previous sighting to the be the sighting from this frame.
    previousSighting = lastPlayerSighting.position;
    
    // If the player is alive...
    if(playerHealth.health > 0f)
        // ... set the animator parameter to whether the player is in sight or not.
        anim.SetBool(hash.playerInSightBool, playerInSight);
    else
        // ... set the animator parameter to false.
        anim.SetBool(hash.playerInSightBool, false);
}
function OnTriggerStay (other : Collider)
{
    // If the player has entered the trigger sphere...
    if(other.gameObject == player)
    {
        // By default the player is not in sight.
        playerInSight = false;
        
        // Create a vector from the enemy to the player and store the angle between it and forward.
        var direction : Vector3 = other.transform.position - transform.position;
        var angle : float = Vector3.Angle(direction, transform.forward);
        
        // If the angle between forward and where the player is, is less than half the angle of view...
        if(angle < fieldOfViewAngle * 0.5f)
        {
            var hit : RaycastHit;
            
            // ... and if a raycast towards the player hits something...
            if(Physics.Raycast(transform.position + transform.up, direction.normalized, hit, col.radius))
            {
                // ... and if the raycast hits the player...
                if(hit.collider.gameObject == player)
                {
                    // ... the player is in sight.
                    playerInSight = true;
                    
                    // Set the last global sighting is the players current position.
                    lastPlayerSighting.position = player.transform.position;
                }
            }
        }
        
        // Store the name hashes of the current states.
        var playerLayerZeroStateHash : int = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
        var playerLayerOneStateHash : int = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
        
        // If the player is running or is attracting attention...
        if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)
        {
            // ... and if the player is within hearing range...
            if(CalculatePathLength(player.transform.position) <= col.radius)
                // ... set the last personal sighting of the player to the player's current position.
                personalLastSighting = player.transform.position;
        }
    }
}
function OnTriggerExit (other : Collider)
{
    // If the player leaves the trigger zone...
    if(other.gameObject == player)
        // ... the player is not in sight.
        playerInSight = false;
}
function CalculatePathLength (targetPosition : Vector3)
{
    // Create a path and set it based on a target position.
    var path : NavMeshPath = new NavMeshPath();
    if(nav.enabled)
        nav.CalculatePath(targetPosition, path);
    
    // Create an array of points which is the length of the number of corners in the path + 2.
    var allWayPoints : Vector3[] = new Vector3[path.corners.Length + 2];
    
    // The first point is the enemy's position.
    allWayPoints[0] = transform.position;
    
    // The last point is the target position.
    allWayPoints[allWayPoints.Length - 1] = targetPosition;
    
    // The points inbetween are the corners of the path.
    for(var i = 0; i < path.corners.Length; i++)
    {
        allWayPoints[i + 1] = path.corners[i];
    }
    
    // Create a float to store the path length that is by default 0.
    var pathLength : float = 0;
    
    // Increment the path length by an amount equal to the distance between each waypoint and the next.
    for(var j = 0; j < allWayPoints.Length - 1; j++)
    {
        pathLength += Vector3.Distance(allWayPoints[j], allWayPoints[j + 1]);
    }
    
    return pathLength;
}
 | 
 |