1. 程式人生 > >unity官方demo學習之Stealth(二十)敵人視聽範圍

unity官方demo學習之Stealth(二十)敵人視聽範圍

為敵人新增指令碼DoneEnemySight

using UnityEngine;
using System.Collections;

public class DoneEnemySight : MonoBehaviour
{
	public float fieldOfViewAngle = 110f;				// Number of degrees, centred on forward, for the enemy see.
    public bool playerInSight;							// Whether or not the player is currently sighted.
	public Vector3 personalLastSighting;				// Last place this enemy spotted the player.
	
	
	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 DoneLastPlayerSighting 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 DonePlayerHealth playerHealth;				// Reference to the player's health script.
	private DoneHashIDs hash;							// Reference to the HashIDs.
	private Vector3 previousSighting;					// Where the player was sighted last frame.
	
	
	void Awake ()
	{
		// Setting up the references.
		nav = GetComponent<NavMeshAgent>();
		col = GetComponent<SphereCollider>();
		anim = GetComponent<Animator>();
		lastPlayerSighting = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent<DoneLastPlayerSighting>();
		player = GameObject.FindGameObjectWithTag(DoneTags.player);
		playerAnim = player.GetComponent<Animator>();
		playerHealth = player.GetComponent<DonePlayerHealth>();
		hash = GameObject.FindGameObjectWithTag(DoneTags.gameController).GetComponent<DoneHashIDs>();
		
		// Set the personal sighting and the previous sighting to the reset position.
		personalLastSighting = lastPlayerSighting.resetPosition;
		previousSighting = lastPlayerSighting.resetPosition;
	}
	
	
	void 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);
	}
	

	void OnTriggerStay (Collider other)
    {
		// 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.
            Vector3 direction = other.transform.position - transform.position;
			float angle = 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)
			{
				RaycastHit hit;
				
				// ... and if a raycast towards the player hits something...
				if(Physics.Raycast(transform.position + transform.up, direction.normalized, out 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.
			int playerLayerZeroStateHash = playerAnim.GetCurrentAnimatorStateInfo(0).nameHash;
			int playerLayerOneStateHash = 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;
			}
        }
    }
	
	
	void OnTriggerExit (Collider other)
	{
		// If the player leaves the trigger zone...
		if(other.gameObject == player)
			// ... the player is not in sight.
			playerInSight = false;
	}
	
	
	float CalculatePathLength (Vector3 targetPosition)
	{
		// Create a path and set it based on a target position.
		NavMeshPath path = 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.
		Vector3 [] allWayPoints = 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(int 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.
		float pathLength = 0;
		
		// Increment the path length by an amount equal to the distance between each waypoint and the next.
		for(int i = 0; i < allWayPoints.Length - 1; i++)
		{
			pathLength += Vector3.Distance(allWayPoints[i], allWayPoints[i + 1]);
		}
		
		return pathLength;
	}
}

引數:(公有)敵人的視角範圍

判斷敵人是否看見玩家

每個敵人獨立的變數 用於儲存敵人聽到玩家腳步聲/喊叫聲的位置

(私有)

引用NavMeshAgent元件 引用sphere collider觸發器元件 引用Animator元件 引用LastPlayerSighting指令碼 引用玩家物件 引用玩家的Animator元件 引用PlayerHealth指令碼 引用HashIDs指令碼 上一幀玩家被發現的位置 函式 Awake 獲取引用物件和元件 把敵人單獨發現的位置 和上一幀發現玩家的位置都重置(1000,1000,1000)
Update 如果發現玩家位置的全域性變數發生改變(即玩家被發現) 那麼每個敵人的單獨位置變數都將等於全域性變數(即告訴所有敵人發現玩家了,趕快來) 並把上一幀發現玩家的位置等於全域性變數 如果玩家HP值等於0 也就是玩家還活著 把playerInSight的值傳遞到Animator中相應的引數 也就是設為true(觸發敵人的各種動作) 否則設為false OnTriggerStay (Collider other) 如果玩家進入觸發器範圍內 預設玩家還沒有被發現 建立敵人到玩家位置的向量 然後獲取它與敵人正前方向量的夾角
如果夾角小於敵人視角的二分之一 建立光線碰撞檢測物件 如果從敵人到玩家的光線投射碰撞到某個物件(因為敵人座標在腳上,投射可能會碰到地面,所以向上位移一個單位,敵人為2個單位) 如果碰撞物件是玩家 判定玩家被發現

相關推薦

unity官方demo學習Stealth敵人視聽範圍

為敵人新增指令碼DoneEnemySight using UnityEngine; using System.Collections; public class DoneEnemySight : MonoBehaviour { public float fieldO

unity官方demo學習Stealth敵人AI

1,新增指令碼檔案DoneEnemyAI using UnityEngine; using System.Collections; public class DoneEnemyAI : MonoBehaviour { public float patrolSpeed

unity官方demo學習Stealth遊戲控制器

五,遊戲控制器  主要:記錄主角最後出現的位置 1,建立空物件,命名為gameController,設定tag,gameController,將audio中的music_normal拖入音訊剪輯中(這是正常遊戲音樂背景),勾選paly    on awake,loop 2,

unity官方demo學習Stealth單開門動畫

1,將modles中的door_generic_slide拖入層級檢視,位置:-6,0,7;角度:90.子物件勾選 use light probes使光可以照到門 2,父物件新增Sphere collider使門可以檢測到敵人或玩家的靠近,center:y:1,radius

unity官方demo學習Stealth角色移動

十一,角色移動 為char_ethan新增指令碼DonePlayerMovement using UnityEngine; using System.Collections; public class DonePlayerMovement : MonoBehaviour

unity官方demo學習Stealth角色動畫控制器

1,(建立玩家靜止狀態)在Animator資料夾中 右鍵,create->Animator Controller,建立一個動畫控制器,命名為PlayerAnimator,建立引數,float:Speed;bool:Snesking;bool:Dead:bool:Sho

Hive學習Hive 執行過程實例分析

cred exe 重復 generator pan hql 語句 color SQ 一、Hive 執行過程概述 1、概述 (1) Hive 將 HQL 轉換成一組操作符(Operator),比如 GroupByOperator, JoinOperator 等 (2)操

Python小白學習—【打開文件的模式】【文件的其他操作】

encoding 否則 移動 換行 tar 循環 color nic true 打開文件的模式(二) 對於非文本文件,我們只能使用b模式,"b"表示以字節的方式操作(而所有文件也都是以字節的形式存儲的,使用這種模式無需考慮文本文件的字符編碼、圖片文件的jgp格式、視頻文件的

Python學習

mil 循環 函數 type() 高級編程 裝飾器 pri 綁定 沒有 Python基礎知識(19):面向對象高級編程(Ⅱ) 定制類 形如“__xx__”的變量或函數在Python中是有特殊用途的 1、__str__ 讓打印出來的結果更好看 __str__:面向用戶;__r

Python小白學習—【開啟檔案的模式】【檔案的其他操作】

開啟檔案的模式(二) 對於非文字檔案,我們只能使用b模式,"b"表示以位元組的方式操作(而所有檔案也都是以位元組的形式儲存的,使用這種模式無需考慮文字檔案的字元編碼、圖片檔案的jgp格式、視訊檔案的avi格式) rb:    以位元組方式讀檔案 wb:  以位元組方式寫檔案ab:   以位元組方式追加檔案 注

Hadoop學習十三MapReduce中的shuffle詳解

就是 多個 流程 http cer 分開 分享圖片 數據分區 bsp 概述 1、MapReduce 中,mapper 階段處理的數據如何傳遞給 reducer 階段,是 MapReduce 框架中 最關鍵的一個流程,這個流程就叫 Shuffle 2、Shuffle: 數

Spark學習分布式圖計算系統

尺度 內存 底層 mapr 分區 ces 兩個 傳遞方式 cat 一、引言   在了解GraphX之前,需要先了解關於通用的分布式圖計算框架的兩個常見問題:圖存儲模式和圖計算模式。 二、圖存儲模式   巨型圖的存儲總體上有邊分割和點分割兩種存儲方式。2013年,Gra

Python小白學習—【迭代器】

迭代器 1.迭代器協議 物件必須提供一個 next 方法,執行該方法要麼返回迭代中的下一項,要麼就引起一個Stoplteration異常,以終止迭代(只能往後走不能往前退) 2.可迭代物件 實現了迭代器協議的物件(如何實現:物件內部定義一個_iter_()方法) 協議是一種約定,可迭代物件實現了

Python學習

Python基礎知識(20):錯誤、除錯和測試 一、錯誤處理 在執行程式的過程中有可能會出錯,一般我們會在新增一段程式碼在可能出錯的地方,返回約定的值,就可以知道會不會出錯以及出錯的原因 1、使用try......except......finally......錯誤處理機制 try...可能會出異常

Python小白學習—【生成器】

表達式 視頻 控制 del 循環 有道 cor 數據量 分享圖片 一.什麽是生成器? 生成器可以理解成是一種數據類型,特殊地是生成器可以自動實現叠代器協議其他的數據類型需要調用自己內置的__iter__方法所以換種說法,生成器就是可叠代對象 !回憶:很重要的叠代器協議

Python小白學習十三—【生成器補充】

生成器的一些補充 接著下雞蛋和吃包子!   補充一:生成器只能遍歷一次 (總是把生成器比喻成母雞下雞蛋,需要一個下一個,首先是下出來的雞蛋不能塞回母雞肚子裡,其次是一個母雞一生只能下一定數量的雞蛋,下完了就死掉了) #通過程式來理解什麼意思 #程式一: def test():

Python學習

Python基礎知識(25):常用內建模組 1、datetime:處理日期和時間 (1)獲取當前日期和時間 from datetime import datetime now = datetime.now() print(now) 結果: 2018-12-07 16:05:53.396953

Python學習

Python基礎知識(27):常用內建模組(Ⅲ) 1、urlblib urllib提供了一系列用於操作URL的功能 url是統一資源定位符,對可以從網際網路上得到的資源的位置和訪問方法的一種簡潔的表示,是網際網路上標準資源的地址 網際網路上的每個檔案都有一個唯一的URL,它包含的資訊指出檔案的位置以及

Python學習

Python基礎知識(28):常用第三方模組 一、Pillow PIL(Python Imaging Library):提供了強大的影象操作功能,可以通過簡單的程式碼完成複雜的影象處理,是Python平臺事實上的影象處理庫,支援Python 2.7以及更低的版本 Pillow:在PIL基礎上建立的相容版

Python小白學習—【裝飾器】

裝飾器 一、裝飾器的本質 裝飾器的本質就是函式,功能就是為其他函式新增附加功能。 利用裝飾器給其他函式新增附加功能時的原則:         1.不能修改被修飾函式的原始碼        2.不能修改被修飾函式的呼叫方式