Unity學(xué)習(xí)筆記07人工智能
有限狀態(tài)機(jī)Finite State Machine (FSM)
蒙特卡洛樹搜索:MCST
最常用的尋路算法是:A*(A star)
尋路相關(guān)概念
NavMesh:描述場(chǎng)景中可通過區(qū)域的數(shù)據(jù)結(jié)構(gòu),可以自動(dòng)創(chuàng)建。
NavMesh Agent:待控制角色,在移動(dòng)時(shí)可以自動(dòng)躲避障礙物。
Off-Mesh Link :將兩個(gè)不可直接通過區(qū)域連接起來(lái)。
NavMesh Obstacle :可移動(dòng)的障礙物,讓agent(待控制角色)能夠在尋路時(shí)避開。
應(yīng)用
場(chǎng)景的物體要設(shè)置成靜態(tài)物體(static)才能被烘焙成導(dǎo)航網(wǎng)格。
調(diào)出 Window-->AI-->Navigation窗口
Navigation窗口下的子窗口
1:Agents,被導(dǎo)航的對(duì)象
2:Areas,導(dǎo)航區(qū)域設(shè)置
3:Object,可以對(duì)選中的物體進(jìn)行導(dǎo)航相關(guān)的設(shè)置
4:Bake,烘焙子窗口,點(diǎn)擊Bake,場(chǎng)景中可通過的部分會(huì)被用藍(lán)色標(biāo)識(shí)出來(lái)。Agent Radius,調(diào)整角色的半徑。Max Slope :可通過的最大坡度。Step Height :可通過的樓梯高度
被導(dǎo)航的物體要添加Component-->Navigaton-->Nav Mesh Agent。
使用下面的腳本,作用是讓物體移動(dòng)到鼠標(biāo)點(diǎn)擊的地方
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class daohang : MonoBehaviour
{
? ?private NavMeshAgent agent;
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?agent = GetComponent<NavMeshAgent>(); ?
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? if (Input.GetMouseButtonDown(0))//鼠標(biāo)左鍵0,右鍵1
? ? ? ?{
? ? ? ? ? ?RaycastHit hit;
? ? ? ? ? ? if(Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition),out hit,100))
? ? ? ? ? ?{
? ? ? ? ? ? ? ?agent.destination = hit.point;
? ? ? ? ? ?}
? ? ? ?}
? ?}
}
新建兩個(gè)空物體,一個(gè)放在初始位置,另一個(gè)放在,目標(biāo)地點(diǎn),給初始位置的物體添加Off Mesh Link ,將start和
end設(shè)置好,Bake后可以看到物體的跳躍路線。
對(duì)于非靜態(tài)的物體,在運(yùn)行時(shí)可以直接過去,如果想要非靜態(tài)的物體有效果,需要為其添加Nav Mesh Obstacle。
巡邏
使用有限狀態(tài)機(jī)描述敵人智能
原理
1.構(gòu)造由一系列關(guān)鍵點(diǎn)組成的巡邏路徑
2.使用自動(dòng)尋路方式,讓敵人移向目標(biāo)點(diǎn)
3.到達(dá)目標(biāo)點(diǎn)后,將目標(biāo)點(diǎn)設(shè)置為下一個(gè)關(guān)鍵點(diǎn)
實(shí)現(xiàn)
建立一個(gè)空物體(父物體),將所有敵人經(jīng)過的路徑點(diǎn)(子物體)建在該空物體下(每一個(gè)路徑點(diǎn)都是一個(gè)空物
體,然后將其放到設(shè)置的路徑點(diǎn)上),建立敵人的控制腳本,將父物體拖拽給腳本。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class AI_Enemy : MonoBehaviour
{
? ?public float patrolSpeed = 2f;//敵人的巡邏速度
? ?public float patrolWaitTime = 1f;//敵人到達(dá)路徑點(diǎn)時(shí)的停留時(shí)間
? ?public Transform patrolWayPoints;//用來(lái)保存所有的路徑點(diǎn),是父物體,子物體為路徑點(diǎn)
? ?private NavMeshAgent agent;//自動(dòng)尋路的智能體
? ?private float patrolTimer;//用來(lái)記錄敵人到達(dá)路徑點(diǎn)的時(shí)候停留時(shí)間是多少
? ?private int wayPointIndex;//用來(lái)記錄當(dāng)前目標(biāo)點(diǎn)是哪個(gè)路徑點(diǎn)
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?agent = GetComponent<NavMeshAgent>();
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? ?Patrolling();//在Update時(shí)每一幀都會(huì)調(diào)用
? ?}
? ?
? ?void Patrolling()
? ?{
? ? ? ?agent.isStopped = false;//默認(rèn)情況是可以自動(dòng)尋路的
? ? ? ?agent.speed = patrolSpeed;
? ? ? ?if(agent.remainingDistance<=agent.stoppingDistance)//判斷agent是否移動(dòng)到了目標(biāo)點(diǎn)
? ? ? ?{
? ? ? ? ? ?patrolTimer += Time.deltaTime;
? ? ? ? ? ?if(patrolTimer>=patrolWaitTime)//如果超過了停留時(shí)間
? ? ? ? ? ?{
? ? ? ? ? ? ? ?if(wayPointIndex==patrolWayPoints.childCount-1)//判斷是否是最后一個(gè)路徑點(diǎn)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex = 0;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex++;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?patrolTimer = 0;
? ? ? ? ? ?}
? ? ? ?}
? ? ? ?else
? ? ? ?{
? ? ? ? ? ?patrolTimer = 0;//未到目標(biāo)點(diǎn)將停留時(shí)間設(shè)置為零;
? ? ? ?}
? ? ? ?agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//設(shè)置agent的目標(biāo)點(diǎn)為要過去的點(diǎn)
? ?}
}
視野
使用有限狀態(tài)機(jī)描述敵人智能:

讓敵人判斷是否"看"到玩家角色
1.敵人面前綁定一個(gè)Trigger,只有進(jìn)入這個(gè)區(qū)域的玩家才可能被看到
2.使用視野來(lái)判斷玩家是否在敵人的一定視角范圍,利用數(shù)學(xué)方法判斷玩家和敵人視線的偏離
實(shí)踐
在敵人上面新建一個(gè)cube,將其網(wǎng)格隱藏(Mesh Renderer) ,擴(kuò)大其Box collider至需要的范圍,并將其Is
Trigger勾選(碰撞體需要為觸發(fā)器類型),建立控制腳本,將其拖拽給cube,
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class EnemySight : MonoBehaviour
{
? ?public float fieldOfViewAngle = 120f;//用來(lái)模擬視野
? ?public bool playerInSight;//用來(lái)判斷當(dāng)前的玩家是否在敵人的視野當(dāng)中
? ?public Vector3 personalLastSight;//玩家最后一次出現(xiàn)在視野中時(shí),玩家的位置
? ?public static Vector3 resetPos = Vector3.back;//用來(lái)記錄玩家的默認(rèn)位置
? ?BoxCollider col;//用來(lái)保存當(dāng)前視野的碰撞體
? ?GameObject player;
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?col = GetComponent<BoxCollider>();
? ? ? ?player = GameObject.FindGameObjectWithTag("Player");//需要將玩家對(duì)象修改為player類型
? ? ? ?personalLastSight = resetPos;
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? ?
? ?}
? ?private void OnTriggerStay(Collider other)//進(jìn)入時(shí)調(diào)用
? ?{
? ? ? ?if(other.gameObject==player)//如果在里面的物體是player的h話進(jìn)行處理
? ? ? ?{
? ? ? ? ? ?playerInSight = false;
? ? ? ? ? ?Vector3 direction = other.transform.position - transform.position;//玩家位置和敵人位置連線做出的向量direction
? ? ? ? ? ?float angle = Vector3.Angle(direction, transform.forward);//direction和敵人朝向的夾角
? ? ? ? ? ?if (angle<fieldOfViewAngle*0.5f)
? ? ? ? ? ?{
? ? ? ? ? ? ? ?//即使?jié)M足上述條件,也只是可能在視野內(nèi),因?yàn)樵诰€路上可能會(huì)有障礙物
? ? ? ? ? ? ? ?RaycastHit hit;//使用物理的方式來(lái)判斷是否有障礙物,投射一條射線,看是否可以從敵人到達(dá)玩家
? ? ? ? ? ? ? ?if(Physics.Raycast(transform.position,direction.normalized,out hit,col.size.z))
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?if(hit.collider.gameObject==player)
? ? ? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ? ? ?Debug.Log("kandao player");
? ? ? ? ? ? ? ? ? ? ? ?playerInSight = true;//中間無(wú)障礙物,玩家出現(xiàn)在敵人視野中
? ? ? ? ? ? ? ? ? ? ? ?personalLastSight = player.transform.position;
? ? ? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?}
? ? ? ? ? ?}
? ? ? ?}
? ?}
? ?private void OnTriggerExit(Collider other)//出去時(shí)調(diào)用
? ?{
? ? ? ?if(other.gameObject==player)
? ? ? ?{
? ? ? ? ? ?playerInSight = false;
? ? ? ?}
? ?}
}
自動(dòng)攻擊
攻擊狀態(tài)
1.當(dāng)敵人和玩家距離達(dá)到攻擊狀態(tài)時(shí)觸發(fā)
2.可以使用子狀態(tài)(選擇不同的攻擊方式,按照玩家的反應(yīng)來(lái)決定自己的行為)
實(shí)踐
為敵人和玩家添加指示方向的物體(這里是z方向),建立子彈預(yù)制件,將其設(shè)置為Is Trigger(觸發(fā)),添加簡(jiǎn)單的子彈腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AI_Enemybullet : MonoBehaviour
{
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? ?
? ?}
? ?private void OnTriggerEnter(Collider other)
? ?{
? ? ? ?if(other.gameObject.tag=="Player")//需要將玩家的tag設(shè)置為Player
? ? ? ?{
? ? ? ? ? ?Destroy(other.gameObject);
? ? ? ? ? ?Destroy(gameObject);
? ? ? ?}
? ?}
}
修改上節(jié)的視野腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Ai_enemy_me : MonoBehaviour
{
? ?public float patrolSpeed = 2f;//敵人的巡邏速度
? ?public float patrolWaitTime = 1f;//敵人到達(dá)路徑點(diǎn)時(shí)的停留時(shí)間
? ?public Transform patrolWayPoints;//用來(lái)保存所有的路徑點(diǎn),是父物體,子物體為路徑點(diǎn)
? ?private NavMeshAgent agent;//自動(dòng)尋路的智能體
? ?private float patrolTimer;//用來(lái)記錄敵人到達(dá)路徑點(diǎn)的時(shí)候停留時(shí)間是多少
? ?private int wayPointIndex;//用來(lái)記錄當(dāng)前目標(biāo)點(diǎn)是哪個(gè)路徑點(diǎn)
//以下為敵人射擊功能
? ?public float shootRotSpeed = 5f;//射擊時(shí)的轉(zhuǎn)向速度
? ?public float shootFreeTime = 2f;//在射擊時(shí)敵人不可能一直發(fā)來(lái)子彈,這個(gè)時(shí)間就是敵人的凍結(jié)時(shí)間
? ?private float shootTimer = 0f;//時(shí)間的計(jì)數(shù)器,一旦達(dá)到凍結(jié)時(shí)間,就可以刷新新一次的射擊
? ?private EnemySight enemySight;//用該腳本來(lái)得到玩家是否在視野中
? ?public Rigidbody Bullet;//獲取子彈
? ?private Transform player;//玩家
? ?//追蹤
? ?public bool chase;//前面是否已經(jīng)發(fā)現(xiàn)過玩家
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?agent = GetComponent<NavMeshAgent>();
? ? ? ?
? ? ? ?//射擊
? ? ? ?enemySight = transform.Find("ViewRange").GetComponent<EnemySight>();//得到玩家是否在視野中
? ? ? ?player = GameObject.FindGameObjectWithTag("Player").transform;
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? ?if (enemySight.playerInSight)//如果看到玩家,則進(jìn)入射擊狀態(tài)
? ? ? ?{
? ? ? ? ? ?Shooting();
? ? ? ? ? ?chase = true;
? ? ? ?}
? ? ? ?else if (chase)//已經(jīng)看到過玩家,進(jìn)入追蹤狀態(tài)
? ? ? ?{
? ? ? ? ? ?Chasing();
? ? ? ?}
? ? ? ?else//未發(fā)現(xiàn),未處于追蹤狀態(tài),則保持巡邏狀態(tài)
? ? ? ?{
? ? ? ? ? ?Patrolling();//在Update時(shí)每一幀都會(huì)調(diào)用
? ? ? ?}
? ?}
? ?void Shooting()//射擊狀態(tài)
? ?{
? ? ? ?Vector3 lookpos = player.position;//首先得到玩家的位置,即目標(biāo)位置
? ? ? ?lookpos.y = transform.position.y;//設(shè)置成與敵人的y方向相同高度,避免在射擊時(shí)出現(xiàn)點(diǎn)頭現(xiàn)象
? ? ? ?Vector3 targetDir = lookpos - transform.position;//要發(fā)射子彈的方向向量
? ? ? ?transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir),
? ? ? ? ? ?Mathf.Min(1, Time.deltaTime * shootRotSpeed));//使用四元數(shù)旋轉(zhuǎn)轉(zhuǎn)向玩家所在方向射擊
? ? ? ?agent.isStopped = true;//射擊時(shí)需要讓玩家停下來(lái)
? ? ? ?if (Vector3.Angle(transform.forward, targetDir) < 2)//判斷敵人是否已經(jīng)足夠朝向射擊目標(biāo)
? ? ? ?{
? ? ? ? ? ?if (shootTimer > shootFreeTime)//判斷凍結(jié)時(shí)間是否刷新
? ? ? ? ? ?{
? ? ? ? ? ? ? ?Instantiate(Bullet, transform.position, Quaternion.LookRotation(player.position - transform.position));
? ? ? ? ? ? ? ?//Instantiate函數(shù)實(shí)例化一個(gè)對(duì)象,三個(gè)參數(shù)分別為,要實(shí)例化的對(duì)象,產(chǎn)生位置,產(chǎn)生后的朝向
? ? ? ? ? ? ? ?shootTimer = 0;//發(fā)射后重置凍結(jié)時(shí)間
? ? ? ? ? ?}
? ? ? ? ? ?shootTimer += Time.deltaTime;//疊加計(jì)數(shù)器時(shí)間
? ? ? ?}
? ?}
? ?void Chasing()//追蹤狀態(tài)
? ?{
? ?}
? ?void Patrolling()//巡邏狀態(tài)
? ?{
? ? ? ?agent.isStopped = false;//默認(rèn)情況是可以自動(dòng)尋路的
? ? ? ?agent.speed = patrolSpeed;
? ? ? ?if (agent.remainingDistance <= agent.stoppingDistance)//判斷agent是否移動(dòng)到了目標(biāo)點(diǎn)
? ? ? ?{
? ? ? ? ? ?patrolTimer += Time.deltaTime;
? ? ? ? ? ?if (patrolTimer >= patrolWaitTime)//如果超過了停留時(shí)間
? ? ? ? ? ?{
? ? ? ? ? ? ? ?if (wayPointIndex == patrolWayPoints.childCount - 1)//判斷是否是最后一個(gè)路徑點(diǎn)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex = 0;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex++;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?patrolTimer = 0;
? ? ? ? ? ?}
? ? ? ?}
? ? ? ?else
? ? ? ?{
? ? ? ? ? ?patrolTimer = 0;//未到目標(biāo)點(diǎn)將停留時(shí)間設(shè)置為零;
? ? ? ?}
? ? ? ?agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//設(shè)置agent的目標(biāo)點(diǎn)為要過去的點(diǎn)
? ?}
}
還需將敵人的視野范圍的碰撞體設(shè)置為Is ?Trigger類型,將子彈預(yù)制件拖拽到敵人腳本開放出來(lái)的對(duì)應(yīng)位置
追蹤
追蹤玩家
1.當(dāng)玩家出現(xiàn)在視野中是觸發(fā)這個(gè)狀態(tài)
2.將玩家位置設(shè)置為目標(biāo)位置(為了真實(shí)性,當(dāng)玩家逃出視野時(shí)的位置也記錄,如果在特定時(shí)間內(nèi)無(wú)法找到玩家,
就停止追蹤)
實(shí)踐
改寫上節(jié)腳本
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class Ai_enemy_me : MonoBehaviour
{
? ?public float patrolSpeed = 2f;//敵人的巡邏速度
? ?public float patrolWaitTime = 1f;//敵人到達(dá)路徑點(diǎn)時(shí)的停留時(shí)間
? ?public Transform patrolWayPoints;//用來(lái)保存所有的路徑點(diǎn),是父物體,子物體為路徑點(diǎn)
? ?private NavMeshAgent agent;//自動(dòng)尋路的智能體
? ?private float patrolTimer;//用來(lái)記錄敵人到達(dá)路徑點(diǎn)的時(shí)候停留時(shí)間是多少
? ?private int wayPointIndex;//用來(lái)記錄當(dāng)前目標(biāo)點(diǎn)是哪個(gè)路徑點(diǎn)
? ?
? ?public float shootRotSpeed = 5f;//射擊時(shí)的轉(zhuǎn)向速度
? ?public float shootFreeTime = 2f;//在射擊時(shí)敵人不可能一直發(fā)來(lái)子彈,這個(gè)時(shí)間就是敵人的凍結(jié)時(shí)間
? ?private float shootTimer = 0f;//時(shí)間的計(jì)數(shù)器,一旦達(dá)到凍結(jié)時(shí)間,就可以刷新新一次的射擊
? ?private EnemySight enemySight;//用該腳本來(lái)得到玩家是否在視野中
? ?public Rigidbody Bullet;//獲取子彈
? ?private Transform player;//玩家
? ?public bool chase;//前面是否已經(jīng)發(fā)現(xiàn)過玩家
? ?public float chaseSpeed = 5f;//追蹤速度
? ?public float chaseWaitTime = 5f;//追蹤等待時(shí)間,指的是追上玩家后觀察時(shí)間
? ?private float chaseTimer;//追蹤等待計(jì)時(shí)器
? ?public float sqrPlayerDist = 3f;//一個(gè)閾值,什么時(shí)候才算追上了玩家,當(dāng)距離的平方等于這個(gè)值時(shí)(用平方是為了計(jì)算效率的提高)
? ?// Start is called before the first frame update
? ?void Start()
? ?{
? ? ? ?agent = GetComponent<NavMeshAgent>();
? ? ? ?enemySight = transform.Find("ViewRange").GetComponent<EnemySight>();//得到玩家是否在視野中
? ? ? ?player = GameObject.FindGameObjectWithTag("Player").transform;
? ?}
? ?// Update is called once per frame
? ?void Update()
? ?{
? ? ? ?if (enemySight.playerInSight)//如果看到玩家,則進(jìn)入射擊狀態(tài)
? ? ? ?{
? ? ? ? ? ?Shooting();
? ? ? ? ? ?chase = true;
? ? ? ?}
? ? ? ?else if (chase)//已經(jīng)看到過玩家,進(jìn)入追蹤狀態(tài)
? ? ? ?{
? ? ? ? ? ?Chasing();
? ? ? ?}
? ? ? ?else//未發(fā)現(xiàn),未處于追蹤狀態(tài),則保持巡邏狀態(tài)
? ? ? ?{
? ? ? ? ? ?Patrolling();//在Update時(shí)每一幀都會(huì)調(diào)用
? ? ? ?}
? ?}
? ?void Shooting()//射擊狀態(tài)
? ?{
? ? ? ?Vector3 lookpos = player.position;//首先得到玩家的位置,即目標(biāo)位置
? ? ? ?lookpos.y = transform.position.y;//設(shè)置成與敵人的y方向相同高度,避免在射擊時(shí)出現(xiàn)點(diǎn)頭現(xiàn)象
? ? ? ?Vector3 targetDir = lookpos - transform.position;//要發(fā)射子彈的方向向量
? ? ? ?transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(targetDir),
? ? ? ? ? ?Mathf.Min(1, Time.deltaTime * shootRotSpeed));//使用四元數(shù)旋轉(zhuǎn)轉(zhuǎn)向玩家所在方向射擊
? ? ? ?agent.isStopped = true;//射擊時(shí)需要讓玩家停下來(lái)
? ? ? ?if (Vector3.Angle(transform.forward, targetDir) < 2)//判斷敵人是否已經(jīng)足夠朝向射擊目標(biāo)
? ? ? ?{
? ? ? ? ? ?if (shootTimer > shootFreeTime)//判斷凍結(jié)時(shí)間是否刷新
? ? ? ? ? ?{
? ? ? ? ? ? ? ?Instantiate(Bullet, transform.position, Quaternion.LookRotation(player.position - transform.position));
? ? ? ? ? ? ? ?//Instantiate函數(shù)實(shí)例化一個(gè)對(duì)象,三個(gè)參數(shù)分別為,要實(shí)例化的對(duì)象,產(chǎn)生位置,產(chǎn)生后的朝向
? ? ? ? ? ? ? ?shootTimer = 0;//發(fā)射后重置凍結(jié)時(shí)間
? ? ? ? ? ?}
? ? ? ? ? ?shootTimer += Time.deltaTime;//疊加計(jì)數(shù)器時(shí)間
? ? ? ?}
? ?}
? ?void Chasing()//追蹤狀態(tài)
? ?{
? ? ? ?agent.isStopped = false;//玩家不停止
? ? ? ?Vector3 sightingDeltaPos = enemySight.personalLastSight - transform.position;//玩家最后出現(xiàn)的位置-敵人當(dāng)前位置
? ? ? ?if(sightingDeltaPos.sqrMagnitude > sqrPlayerDist)//如果距離大于閾值,需要繼續(xù)追蹤
? ? ? ?{
? ? ? ? ? ?agent.destination = enemySight.personalLastSight;//設(shè)置追蹤點(diǎn)
? ? ? ?}
? ? ? ?agent.speed = chaseSpeed;
? ? ? ?if(agent.remainingDistance<=agent.stoppingDistance)//追蹤過程中到達(dá)玩家最后出現(xiàn)的位置
? ? ? ?{
? ? ? ? ? ?chaseTimer += Time.deltaTime;
? ? ? ? ? ?if(chaseTimer>=chaseWaitTime)//追蹤完成
? ? ? ? ? ?{
? ? ? ? ? ? ? ?chase = false;
? ? ? ? ? ? ? ?chaseTimer = 0f;
? ? ? ? ? ?}
? ? ? ?}
? ? ? ?else
? ? ? ?{
? ? ? ? ? ?chaseTimer = 0;
? ? ? ?}
? ?}
? ?void Patrolling()//巡邏狀態(tài)
? ?{
? ? ? ?agent.isStopped = false;//默認(rèn)情況是可以自動(dòng)尋路的
? ? ? ?agent.speed = patrolSpeed;
? ? ? ?if (agent.remainingDistance <= agent.stoppingDistance)//判斷agent是否移動(dòng)到了目標(biāo)點(diǎn)
? ? ? ?{
? ? ? ? ? ?patrolTimer += Time.deltaTime;
? ? ? ? ? ?if (patrolTimer >= patrolWaitTime)//如果超過了停留時(shí)間
? ? ? ? ? ?{
? ? ? ? ? ? ? ?if (wayPointIndex == patrolWayPoints.childCount - 1)//判斷是否是最后一個(gè)路徑點(diǎn)
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex = 0;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?else
? ? ? ? ? ? ? ?{
? ? ? ? ? ? ? ? ? ?wayPointIndex++;
? ? ? ? ? ? ? ?}
? ? ? ? ? ? ? ?patrolTimer = 0;
? ? ? ? ? ?}
? ? ? ?}
? ? ? ?else
? ? ? ?{
? ? ? ? ? ?patrolTimer = 0;//未到目標(biāo)點(diǎn)將停留時(shí)間設(shè)置為零;
? ? ? ?}
? ? ? ?agent.destination = patrolWayPoints.GetChild(wayPointIndex).position;//設(shè)置agent的目標(biāo)點(diǎn)為要過去的點(diǎn)
? ?}
}
機(jī)器學(xué)習(xí)
所謂的學(xué)習(xí)指的是系統(tǒng)所做的適應(yīng)性變化,使得該系統(tǒng)在下一次完成同樣的任務(wù)時(shí)更有效率。
傳統(tǒng)人工智能的問題
1.再靈活精巧的算法也是"死"的
2.無(wú)法自動(dòng)適應(yīng)新的環(huán)境
3.無(wú)法進(jìn)化
4.不能對(duì)不同的對(duì)手采取不同策略
機(jī)器學(xué)習(xí)Machine Learning
1.非監(jiān)督學(xué)習(xí) unsupervised ? learning
比如要將玩家按照沉浸度分為兩類。
獲得了玩家的一系列信息(比如游戲時(shí)間、內(nèi)購(gòu)情況和完成的關(guān)卡數(shù)量)。
在非監(jiān)督學(xué)習(xí)系統(tǒng)中,設(shè)定分類為2。
并沒有標(biāo)注玩家信息,卻可以對(duì)玩家進(jìn)行分類。
2.監(jiān)督式學(xué)習(xí) supervised ? learning
可以依據(jù)玩家屬性直接將玩家映射為某種類型。
對(duì)樣本進(jìn)行標(biāo)注(除了游戲時(shí)間、內(nèi)購(gòu)情況和完成的關(guān)卡數(shù)量外,還標(biāo)注出樣本玩家是否是高沉浸度玩家)。
學(xué)習(xí)到哪些屬性影響了玩家是否沉浸。
將學(xué)習(xí)到的模型用來(lái)預(yù)測(cè)新的玩家可能的狀態(tài)。
3.強(qiáng)化學(xué)習(xí) reinforcement learning
讓計(jì)算機(jī)通過不斷地嘗試,從錯(cuò)誤中學(xué)習(xí),最后找到規(guī)律。
類似于有一位虛擬的裁判,他給計(jì)算機(jī)的行為打分。
計(jì)算機(jī)會(huì)盡量執(zhí)行能夠拿高分的行為,并避免低分的行為。
具有分?jǐn)?shù)導(dǎo)向性(這種分?jǐn)?shù)導(dǎo)向性類似于監(jiān)督學(xué)習(xí)中的正確標(biāo)簽)。