孫廣東 2015.8.15 一、Enemy Aim Ai
這種效應(yīng)可以創(chuàng)建的 Lerping 旋轉(zhuǎn)角度對(duì)玩家的敵人。這種情況是在動(dòng)作游戲,敵人跟隨,目的是何地然后射球員的情況下非常有用。對(duì)敵人遵循概念是在早些時(shí)候發(fā)布的博客中已經(jīng)討論過。在推行針對(duì)在游戲的同時(shí),理解四元數(shù)的概念是非常必要的。 四元數(shù)存儲(chǔ)對(duì)象的旋轉(zhuǎn),還可以計(jì)算價(jià)值取向。一個(gè)可以直接玩歐拉角,但可能會(huì)出現(xiàn) 萬向鎖 的情況。 根據(jù)當(dāng)?shù)氐淖鴺?biāo)系統(tǒng),如果你旋轉(zhuǎn)模型X 軸,然后其 Y 和 Z 軸經(jīng)驗(yàn)萬向節(jié)鎖被'鎖定'在一起。 現(xiàn)在回到我們的主題,給出了下面是一個(gè)簡單的例子來解釋 Enemy aim AI 按照下面給出的步驟。 1、創(chuàng)建Cube將作用在player control
TargetMovementScript.cs public class TargetMovementScript : MonoBehaviour {
public float targetSpeed=9.0f;//Speed At Which the Object Should Move
void Update ()
transform.Translate (Input.GetAxis ('Horizontal')*Time.deltaTime*targetSpeed,Input.GetAxis ('Vertical')*Time.deltaTime*targetSpeed,0);
}
} 2、創(chuàng)建一個(gè)Enemy對(duì)象,由箭頭和Cube組成, 1、應(yīng)用適當(dāng)?shù)牟牧蠈?duì)Cube 。 2、使箭頭Sprite作為一個(gè)不同的對(duì)象 3、其方向由 Cube指出 . 所以在這里,箭頭將充當(dāng)了敵人的槍。 4、此箭頭將指向目標(biāo)對(duì)象和它看起來就好像它試圖鎖定目標(biāo) 5、我們也可以操縱速度,敵人將能夠鎖定目標(biāo)屬性 ;作為不同的敵人應(yīng)該是不同的困難,以及不同的功能。 EnemyAimScript.cs public class EnemyAimScript : MonoBehaviour {
public Transform target; // Target Object
public float enemyAimSpeed=5.0f; // Speed at Which Enenmy locks on the Target
Quaternion newRotation;
float orientTransform;
float orientTarget;
void Update () {
orientTransform = transform.position.x;
orientTarget = target.position.x;
// To Check on which side is the target , i.e. Right or Left of this Object
if (orientTransform > orientTarget) {
// Will Give Rotation angle , so that Arrow Points towards that target
newRotation = Quaternion.LookRotation (transform.position - target.position, -Vector3.up);
}
else {
newRotation = Quaternion.LookRotation (transform.position - target.position,Vector3.up);
}
// Here we have to freeze rotation along X and Y Axis, for proper movement of the arrow
newRotation.x = 0.0f;
newRotation.y = 0.0f;
// Finally rotate and aim towards the target direction using Code below
transform.rotation = Quaternion.Lerp (transform.rotation,newRotation,Time.deltaTime * enemyAimSpeed);
// Another Alternative
// transform.rotation = Quaternion.RotateTowards(transform.rotation,newRotation, Time.deltaTime * enemyAimSpeed);
}
} 7、Hierarchy 和 Scene View 可能會(huì)像作為給定下面 備注:-
二、通過有限狀態(tài)機(jī)實(shí)現(xiàn)AI Contents Objective Step - 1: Set up the scene Step - 2: Create and place Game Objects Step - 3: Implement the BoxMovement Script Step - 4: FSM Modelled Script Step - 5: AI Script for the Box - 目的: 這篇文章的主要目的是要給你一個(gè)關(guān)于如何使用有限狀態(tài)機(jī)模型在 實(shí)現(xiàn) AI 。
Step - 1: Set up the scene 以一個(gè)平面和兩個(gè)Box在場景中,如下圖所示的設(shè)置。 Step - 2: Create and place Game Objects 創(chuàng)建空的游戲?qū)ο蟛⑵渥鳛橛巫狱c(diǎn)Wanderer Points。放置這些空的游戲?qū)ο笙?,為您選擇平面周圍。在這里藍(lán)色的Cube是 AI Cube和紅一個(gè)是玩家控制的Cube。將它們放在距離不夠遠(yuǎn)。 Step - 3: Implement the BoxMovement Script 實(shí)現(xiàn) BoxMovement 腳本來控制玩家的Cube的移動(dòng):如下: public class BoxMovementScript : MonoBehaviour
{
public float speed = 0.1f;
private Vector3 positionVector3;
void Update ()
{
InitializePosition ();
if (Input.GetKey (KeyCode.LeftArrow)) {
GoLeft ();
}
if (Input.GetKey (KeyCode.RightArrow)) {
GoRight ();
}
if (Input.GetKey (KeyCode.UpArrow)) {
GoTop ();
}
if (Input.GetKey (KeyCode.DownArrow)) {
GoDown ();
}
RotateNow ();
}
private void InitializePosition ()
{
positionVector3 = transform.position;
}
private void RotateNow ()
{
Quaternion targetRotation = Quaternion.LookRotation (transform.position - positionVector3);
transform.rotation = targetRotation;
}
private void GoLeft ()
{
transform.position = transform.position new Vector3 (-speed, 0, 0);
}
private void GoRight ()
{
transform.position = transform.position new Vector3 (speed, 0, 0);
}
private void GoTop ()
{
transform.position = transform.position new Vector3 (0, 0, speed);
}
private void GoDown ()
{
transform.position = transform.position new Vector3 (0, 0, -speed);
}
} Step - 4: FSM Modelled Script 構(gòu)建FSM模型腳本: public class FSM : MonoBehaviour
{
//Player Transform
protected Transform playerTransform;
//Next destination position of the Box
protected Vector3 destPos;
//List of points for patrolling
protected GameObject[] pointList;
protected virtual void Initialize (){
}
protected virtual void FSMUpdate (){
}
protected virtual void FSMFixedUpdate (){
}
void Start ()
{
Initialize ();
}
void Update ()
{
FSMUpdate ();
}
void FixedUpdate ()
{
FSMFixedUpdate ();
}
}
Step - 5: AI Script for the Box 構(gòu)建 AI 腳本作為Box擴(kuò)展. public class BoxFSM : FSM
{
public enum FSMState
{
None,
Patrol,
Chase,
}
//Current state that the Box is in
public FSMState curState;
//Speed of the Box
private float curSpeed;
//Box Rotation Speed
private float curRotSpeed;
//Initialize the Finite state machine for the AI Driven Box
protected override void Initialize ()
{
curState = FSMState.Patrol;
curSpeed = 5.0f;
curRotSpeed = 1.5f;
//Get the list of points
pointList = GameObject.FindGameObjectsWithTag ('WandarPoint');
//Set Random destination point for the patrol state first
FindNextPoint ();
//Get the target enemy(Player)
GameObject objPlayer = GameObject.FindGameObjectWithTag ('Player');
playerTransform = objPlayer.transform;
if (!playerTransform)
print ('Player doesn't exist.. Please add one ' 'with Tag named 'Player'');
}
//Update each frame
protected override void FSMUpdate ()
{
switch (curState) {
case FSMState.Patrol:
UpdatePatrolState ();
break;
case FSMState.Chase:
UpdateChaseState ();
break;
}
}
protected void UpdatePatrolState ()
{
//Find another random patrol point on reaching the current Point
//point is reached
if (Vector3.Distance (transform.position, destPos) <= 2.5f) {
print ('Reached to the destination point\n' 'calculating the next point');
FindNextPoint ();
}
//Check the distance with player Box
//When the distance is near, transition to chase state
else if (Vector3.Distance (transform.position, playerTransform.position) <= 15.0f) {
print ('Switch to Chase State');
curState = FSMState.Chase;
}
//Rotate to the target point
Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);
//Go Forward
transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);
}
protected void FindNextPoint ()
{
print ('Finding next point');
int rndIndex = Random.Range (0, pointList.Length);
float rndRadius = 5.0f;
Vector3 rndPosition = Vector3.zero;
destPos = pointList [rndIndex].transform.position rndPosition;
//Check Range to Move and decide the random point
//as the same as before
if (IsInCurrentRange (destPos)) {
rndPosition = new Vector3 (Random.Range (-rndRadius, rndRadius), 0.0f, Random.Range (-rndRadius, rndRadius));
destPos = pointList [rndIndex].transform.position rndPosition;
}
}
protected bool IsInCurrentRange (Vector3 pos)
{
float xPos = Mathf.Abs (pos.x - transform.position.x);
float zPos = Mathf.Abs (pos.z - transform.position.z);
if (xPos <= 8 && zPos <= 8)
return true;
return false;
}
protected void UpdateChaseState ()
{
//Set the target position as the player position
destPos = playerTransform.position;
//Check the distance with player Box When
float dist = Vector3.Distance (transform.position, playerTransform.position);
//Go back to patrol as player is now too far
if (dist >= 15.0f) {
curState = FSMState.Patrol;
FindNextPoint ();
}
//Rotate to the target point
Quaternion targetRotation = Quaternion.LookRotation (destPos - transform.position);
transform.rotation = Quaternion.Slerp (transform.rotation, targetRotation, Time.deltaTime * curRotSpeed);
//Go Forward
transform.Translate (Vector3.forward * Time.deltaTime * curSpeed);
}
} 此腳本適用于Cube是要跟隨玩家,不要忘記把player標(biāo)記Tag為 Player 和 Tag 為 WandarPoint,現(xiàn)在如 FSMUpdate() 所示的腳本將調(diào)用方法,這在子類中重寫和它將在每個(gè) update () 上執(zhí)行。 在這里switch case被實(shí)施 將用于執(zhí)行的當(dāng)前狀態(tài)的操作。 因此擴(kuò)展 AI 是很簡單的僅僅通過添加新的state。Initialize() 方法也重寫,并將在 start () 方法中調(diào)用執(zhí)行。UpdatePatrolState() 將在每次更新上執(zhí)行,當(dāng)當(dāng)前狀態(tài)是patrol 周圍巡邏,也將會(huì)發(fā)生在 UpdateChaseState(),當(dāng)玩家在接近度 AI Box。如果當(dāng)處于巡邏,玩家進(jìn)來的 AI Box中,狀態(tài)將更改為 巡邏,相同 類型的檢查仍在 追逐模式檢查如果球員已遠(yuǎn)離其視野范圍, 然后切換回巡邏狀態(tài), 在每個(gè)更新,檢查狀態(tài)更改。 結(jié)論: FSM 的很容易理解和實(shí)現(xiàn),F(xiàn)sm 可以用于執(zhí)行復(fù)雜的 AI 。他們也可以表示使用圖,允許開發(fā)人員很容易理解,因此開發(fā)人員可以調(diào)整、 改變和優(yōu)化的最終結(jié)果。有限狀態(tài)機(jī)使用的函數(shù)或方法來代表狀態(tài)執(zhí)行是簡單、 功能強(qiáng)大、 易于擴(kuò)展。 可以使用基于堆棧的狀態(tài)機(jī),確保易于管理和穩(wěn)定的 執(zhí)行流,而不會(huì)產(chǎn)生消極影響的代碼應(yīng)用甚至更復(fù)雜的 AI。 所以讓你的敵人更聰明使用有限狀態(tài)機(jī),讓您的游戲的成功。 |
|