|
C#- 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;
- }
- }
复制代码 js脚本- #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;
- }
复制代码 |
|