【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2051|回复: 0

7-3 Enemy Sight 敌人的视野

[复制链接]
发表于 2013-10-17 13:10:08 | 显示全部楼层 |阅读模式
C#
  1. using UnityEngine;
  2. using System.Collections;

  3. public class EnemySight : MonoBehaviour
  4. {
  5.         public float fieldOfViewAngle = 110f;                               // 机器巡逻兵视野的角度.
  6.         public bool playerInSight;                                          // 玩家是不是处于机器巡逻兵的视野中.
  7.         public Vector3 personalLastSighting;                                // 机器巡逻兵最后一个看到玩家的地点.
  8.        
  9.        
  10.         private NavMeshAgent nav;                                           // Reference to the NavMeshAgent component.
  11.         private SphereCollider col;                                         // Reference to the sphere collider trigger component.
  12.         private Animator anim;                                              // Reference to the Animator.
  13.         private LastPlayerSighting lastPlayerSighting;                      // Reference to last global sighting of the player.
  14.         private GameObject player;                                          // Reference to the player.
  15.         private Animator playerAnim;                                        // Reference to the player's animator component.
  16.         private PlayerHealth playerHealth;                                  // Reference to the player's health script.
  17.         private HashIDs hash;                                               // Reference to the HashIDs.
  18.         private Vector3 previousSighting;                                   // 玩家在视野中的最后一个位置.
  19.        
  20.        
  21.         void Awake ()
  22.         {
  23.                 // 初始化成员.
  24.                 nav = GetComponent<NavMeshAgent>();
  25.                 col = GetComponent<SphereCollider>();
  26.                 anim = GetComponent<Animator>();
  27.                 lastPlayerSighting = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<LastPlayerSighting>();
  28.                 player = GameObject.FindGameObjectWithTag(Tags.player);
  29.                 playerAnim = player.GetComponent<Animator>();
  30.                 playerHealth = player.GetComponent<PlayerHealth>();
  31.                 hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<HashIDs>();
  32.                
  33.                 // 设置玩家的发现位置的初始值为resetPosition(1000,1000,1000).
  34.                 personalLastSighting = lastPlayerSighting.resetPosition;
  35.                 previousSighting = lastPlayerSighting.resetPosition;
  36.         }
  37.        
  38.        
  39.         void Update ()
  40.         {
  41.                 // 如果玩家处于警报状态...
  42.                 if(lastPlayerSighting.position != previousSighting)
  43.                         // ... 设置玩家最后的发现位置为玩家的当前坐标.
  44.                         personalLastSighting = lastPlayerSighting.position;
  45.                
  46.                 // 设置视野内玩家位置为当前玩家坐标.
  47.                 previousSighting = lastPlayerSighting.position;
  48.                
  49.                 // 如果玩家是活的...
  50.                 if(playerHealth.health > 0f)
  51.                         // ... 设置玩家动画控制器中的playerInSightBool变量为playerInSight.
  52.                         anim.SetBool(hash.playerInSightBool, playerInSight);
  53.                 else
  54.                         // ... 如果玩家已经死了,就设置playerInSightBool为false.
  55.                         anim.SetBool(hash.playerInSightBool, false);
  56.         }
  57.        
  58.        
  59.         void OnTriggerStay (Collider other)
  60.         {
  61.                 // 如果进入触发区域的是玩家...
  62.                 if(other.gameObject == player)
  63.                 {
  64.                         // 设置默认的playerInSight状态为不可见.
  65.                         playerInSight = false;
  66.                        
  67.                         // 创建一个变量 记录从机器人到玩家的方向向量.
  68.                         Vector3 direction = other.transform.position - transform.position;
  69.                         // 求得机器人正方向和玩家之间的角度
  70.                         float angle = Vector3.Angle(direction, transform.forward);
  71.                        
  72.                         // 如果玩家处于视野内...
  73.                         if(angle < fieldOfViewAngle * 0.5f)
  74.                         {
  75.                                 RaycastHit hit;
  76.                                
  77.                                 // ... 从机器人的身高部位向玩家发射一条射线...
  78.                                 if(Physics.Raycast(transform.position + transform.up, direction.normalized, out hit, col.radius))
  79.                                 {
  80.                                         // ... 射线触碰到了玩家...
  81.                                         if(hit.collider.gameObject == player)
  82.                                         {
  83.                                                 // ... 玩家在视野内,被发现了,设置标志位为true.
  84.                                                 playerInSight = true;
  85.                                                
  86.                                                 // 将警报标志位的坐标设定为玩家当前坐标.
  87.                                                 lastPlayerSighting.position = player.transform.position;
  88.                                         }
  89.                                 }
  90.                         }
  91.                        
  92.                         // 获取动画层0和动画层1两层当前的动画播放状态机.
  93.                         int playerLayerZeroStateHash = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
  94.                         int playerLayerOneStateHash = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
  95.                        
  96.                         // 如果玩家现在正处于行走或者呼唤状态(有声音)...
  97.                         if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)
  98.                         {
  99.                                 // ... 并且玩家处于机器人的监听范围内...
  100.                                 if(CalculatePathLength(player.transform.position) <= col.radius)
  101.                                         // ... 设置玩家当前位置为发现角色的位置.
  102.                                         personalLastSighting = player.transform.position;
  103.                         }
  104.                 }
  105.         }
  106.        
  107.        
  108.         void OnTriggerExit (Collider other)
  109.         {
  110.                 // 如果玩家离开了机器巡逻的监测区域...
  111.                 if(other.gameObject == player)
  112.                         // ... 视野失去目标.
  113.                         playerInSight = false;
  114.         }
  115.        
  116.         //--------------------------------------------------------------------
  117.         // 计算一条路径,返回需要走的步数
  118.         //--------------------------------------------------------------------
  119.         float CalculatePathLength (Vector3 targetPosition)
  120.         {
  121.                 // 生成一个变量记录自动寻路的路径.
  122.                 NavMeshPath path = new NavMeshPath();
  123.                 if(nav.enabled)
  124.                         nav.CalculatePath(targetPosition, path);
  125.                
  126.                 // 创建一个保存自动寻路节点的数组.数组的大小比实际的寻路节点多2个
  127.                 Vector3 [] allWayPoints = new Vector3[path.corners.Length + 2];
  128.                
  129.                 // 第一个节点存的是机器人当前坐标.
  130.                 allWayPoints[0] = transform.position;
  131.                
  132.                 // 最后一个存的是玩家的坐标.
  133.                 allWayPoints[allWayPoints.Length - 1] = targetPosition;
  134.                
  135.                 // 中间的存的是自动寻路的路径节点.
  136.                 for(int i = 0; i < path.corners.Length; i++)
  137.                 {
  138.                         allWayPoints[i + 1] = path.corners[i];
  139.                 }
  140.                
  141.                 //  步长变量.
  142.                 float pathLength = 0;
  143.                
  144.                 // 计算每一个节点之间的长度,并将这些长度加起来.
  145.                 for(int i = 0; i < allWayPoints.Length - 1; i++)
  146.                 {
  147.                         pathLength += Vector3.Distance(allWayPoints[i], allWayPoints[i + 1]);
  148.                 }
  149.                
  150.                 return pathLength;
  151.         }
  152. }
复制代码
js脚本
  1. #pragma strict

  2. public var fieldOfViewAngle : float = 110f;             // Number of degrees, centred on forward, for the enemy see.
  3. public var playerInSight : boolean;                     // Whether or not the player is currently sighted.
  4. public var personalLastSighting : Vector3;              // Last place this enemy spotted the player.


  5. private var nav : NavMeshAgent;                         // Reference to the NavMeshAgent component.
  6. private var col : SphereCollider;                       // Reference to the sphere collider trigger component.
  7. private var anim : Animator;                            // Reference to the Animator.
  8. private var lastPlayerSighting : LastPlayerSighting;    // Reference to last global sighting of the player.
  9. private var player : GameObject;                        // Reference to the player.
  10. private var playerAnim : Animator;                      // Reference to the player's animator component.
  11. private var playerHealth : PlayerHealth;                // Reference to the player's health script.
  12. private var hash : HashIDs;                             // Reference to the HashIDs.
  13. private var previousSighting : Vector3;                 // Where the player was sighted last frame.


  14. function Awake ()
  15. {
  16.     // Setting up the references.
  17.     nav = GetComponent(NavMeshAgent);
  18.     col = GetComponent(SphereCollider);
  19.     anim = GetComponent(Animator);
  20.     lastPlayerSighting = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent(LastPlayerSighting);
  21.     player = GameObject.FindGameObjectWithTag(Tags.player);
  22.     playerAnim = player.GetComponent(Animator);
  23.     playerHealth = player.GetComponent(PlayerHealth);
  24.     hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent(HashIDs);
  25.    
  26.     // Set the personal sighting and the previous sighting to the reset position.
  27.     personalLastSighting = lastPlayerSighting.resetPosition;
  28.     previousSighting = lastPlayerSighting.resetPosition;
  29. }


  30. function Update ()
  31. {
  32.     // If the last global sighting of the player has changed...
  33.     if(lastPlayerSighting.position != previousSighting)
  34.         // ... then update the personal sighting to be the same as the global sighting.
  35.         personalLastSighting = lastPlayerSighting.position;
  36.    
  37.     // Set the previous sighting to the be the sighting from this frame.
  38.     previousSighting = lastPlayerSighting.position;
  39.    
  40.     // If the player is alive...
  41.     if(playerHealth.health > 0f)
  42.         // ... set the animator parameter to whether the player is in sight or not.
  43.         anim.SetBool(hash.playerInSightBool, playerInSight);
  44.     else
  45.         // ... set the animator parameter to false.
  46.         anim.SetBool(hash.playerInSightBool, false);
  47. }


  48. function OnTriggerStay (other : Collider)
  49. {
  50.     // If the player has entered the trigger sphere...
  51.     if(other.gameObject == player)
  52.     {
  53.         // By default the player is not in sight.
  54.         playerInSight = false;
  55.         
  56.         // Create a vector from the enemy to the player and store the angle between it and forward.
  57.         var direction : Vector3 = other.transform.position - transform.position;
  58.         var angle : float = Vector3.Angle(direction, transform.forward);
  59.         
  60.         // If the angle between forward and where the player is, is less than half the angle of view...
  61.         if(angle < fieldOfViewAngle * 0.5f)
  62.         {
  63.             var hit : RaycastHit;
  64.             
  65.             // ... and if a raycast towards the player hits something...
  66.             if(Physics.Raycast(transform.position + transform.up, direction.normalized, hit, col.radius))
  67.             {
  68.                 // ... and if the raycast hits the player...
  69.                 if(hit.collider.gameObject == player)
  70.                 {
  71.                     // ... the player is in sight.
  72.                     playerInSight = true;
  73.                     
  74.                     // Set the last global sighting is the players current position.
  75.                     lastPlayerSighting.position = player.transform.position;
  76.                 }
  77.             }
  78.         }
  79.         
  80.         // Store the name hashes of the current states.
  81.         var playerLayerZeroStateHash : int = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
  82.         var playerLayerOneStateHash : int = playerAnim.GetCurrentAnimatorStateInfo(1).nameHash;
  83.         
  84.         // If the player is running or is attracting attention...
  85.         if(playerLayerZeroStateHash == hash.locomotionState || playerLayerOneStateHash == hash.shoutState)
  86.         {
  87.             // ... and if the player is within hearing range...
  88.             if(CalculatePathLength(player.transform.position) <= col.radius)
  89.                 // ... set the last personal sighting of the player to the player's current position.
  90.                 personalLastSighting = player.transform.position;
  91.         }
  92.     }
  93. }


  94. function OnTriggerExit (other : Collider)
  95. {
  96.     // If the player leaves the trigger zone...
  97.     if(other.gameObject == player)
  98.         // ... the player is not in sight.
  99.         playerInSight = false;
  100. }


  101. function CalculatePathLength (targetPosition : Vector3)
  102. {
  103.     // Create a path and set it based on a target position.
  104.     var path : NavMeshPath = new NavMeshPath();
  105.     if(nav.enabled)
  106.         nav.CalculatePath(targetPosition, path);
  107.    
  108.     // Create an array of points which is the length of the number of corners in the path + 2.
  109.     var allWayPoints : Vector3[] = new Vector3[path.corners.Length + 2];
  110.    
  111.     // The first point is the enemy's position.
  112.     allWayPoints[0] = transform.position;
  113.    
  114.     // The last point is the target position.
  115.     allWayPoints[allWayPoints.Length - 1] = targetPosition;
  116.    
  117.     // The points inbetween are the corners of the path.
  118.     for(var i = 0; i < path.corners.Length; i++)
  119.     {
  120.         allWayPoints[i + 1] = path.corners[i];
  121.     }
  122.    
  123.     // Create a float to store the path length that is by default 0.
  124.     var pathLength : float = 0;
  125.    
  126.     // Increment the path length by an amount equal to the distance between each waypoint and the next.
  127.     for(var j = 0; j < allWayPoints.Length - 1; j++)
  128.     {
  129.         pathLength += Vector3.Distance(allWayPoints[j], allWayPoints[j + 1]);
  130.     }
  131.    
  132.     return pathLength;
  133. }
复制代码

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2024-5-6 11:03

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表