最近在做一個小的ARPG游戲。剛寫了一點關(guān)于怪物的AI控制的代碼,前后還出現(xiàn)了很多問題的?,F(xiàn)在拿出來分享一下。
首先我們先導(dǎo)入一個骷髏模型作例子學(xué)習(xí)。
1、先增加一個animator狀態(tài)機。
2、然后我們把Skeleton_Pack文件夾里面的其中一個prefab拖到場景。我們在prefab給他添加好Controller,組件和腳本。(差點忘了說,我們把prefab拖出來后,在skeleton_archer_blue設(shè)置一個空的gameobject,命名為head,這個head的坐標(biāo)是skeleton_archer_blue的頭頂,用來顯示血條的。)
3.using UnityEngine;
using System.Collections;
////// 功能:人物血條的隱藏與顯示,怪物的轉(zhuǎn)向(當(dāng)player與怪物小于一定距離,則設(shè)置兩者面對面),怪物的自動攻擊。
///public class MonsterAI : MonoBehaviour {?
?? public GameObject uiPrefab; ? //血條的prefab? ?
?//角色頭頂?shù)狞c,最好讓美術(shù)把這個點直接做在fbx模型里面? ?
? public Transform head;??
? public enum State? ? {? ? ?
?? IDLE,? ? ? ? WALK,? ? ? ? ATTACK,? ? ? ? DANGER? ?
?}?
?? public State state;??
? private Animator animator;//獲取Animator組件? ??
? private CharacterController control;??
? ?private GameObject ui;? ??
?//默認(rèn)血條與攝像機的距離? ?
? ? private float fomat;? ??
? //人物位置坐標(biāo)? ?
? ? private Vector3 playerPosition;? ? ? ? ? ?
? ? void Awake()? ? {? ? ? ?
? ? ?ui = (GameObject)Instantiate(uiPrefab);? ? ? ??
? ? ? animator = GetComponent();? ? ? ??
? ? ? control = GetComponent();? ?
? ? ? }? ? ?
? ? ? ? void Start () {? ? ??
? ? ? ? state = State.IDLE;? ? ??
? ? ? ? fomat = Vector3.Distance(head.position, Camera.main.transform.position);? ?
? ? ?} ? ? ? ? ?
? ? ? ?void Update () {? ? ? ??
? ? ? //人物Position? ? ? ?
? ? ? ? playerPosition=PlayerControl.instance.transform.position;? ? ?
? ? ? ? Debug.DrawLine(playerPosition, transform.position, Color.red);? ? ? ?
? ? ? ? ?setBloodBar();? ? ??
? ? ? ?//人物與怪物的距離? ? ?
? ? ? ?float dis = Vector3.Distance(transform.position, playerPosition);? ? ??
? ? ? ?/**? ? ? ? * 下面是這樣的,當(dāng)兩者距離小于3時,則怪物攻擊,設(shè)置怪物狀態(tài)為ATTACK? ? ??
? ? ? ? ? ? ? ? ?* 當(dāng)兩者距離大于3小于15時候 ,怪物走向player?
? ? ? ? ? ? ? ? ? * 當(dāng)大于15時, 怪物處于IDLE狀態(tài))??
? ? **/ ? ? ??
if(dis < 3){
? ?state ?= State.Attack;
}if( dis <15){
print("進(jìn)入攻擊狀態(tài)");
? Quatertion rotation? =Quatertion.Slerp( tranform.rotation , Quatertion.LookRotation( playerPosition - transform.position),5 * Time.deltatime);? (LookRotation 創(chuàng)建由怪物正方向轉(zhuǎn)向玩家正方向的旋轉(zhuǎn))
? if(dis > 3){
? state = State.WALK;
? ?transform.position += transform.forwrd * 5 * Time.deltatime;?
? ? ? ? ? ? ? ? ? ? }
}
? ? ? ?else? ? ? ? {? ? ? ? ?
? ? ? ? ? ?print("退出小怪攻擊范圍");? ? ? ? ? ??
? ? ? ? ? ?state = State.IDLE;? ? ? ?
? ? ? ? }? ? ? ??
? ? ? ?MonsterStateControl();? ? }? ?
? ?////// 怪物的各種狀態(tài)處理,設(shè)置了animator的狀態(tài)機的變量
///void MonsterStateControl()? ? {? ? ?
? ? ? ? switch (state)? ? ? ? {? ? ??
? ? ? ? ? ?case State.IDLE:? ? ? ? ? ? ? ??
? ? ? ? ? ? ?animator.SetBool("isAttack00", false);? ? ? ? ??
? ? ? ? ? ? ?animator.SetBool("isRun", false);? ? ? ? ? ? ? ??
? ? ? ? ? ? ?break;? ? ? ? ? ?
? ? ? ? ? case State.WALK:? ? ? ? ? ? ??
? ? ? ? ? ? animator.SetBool("isRun", true);? ? ? ? ? ??
? ? ? ? ? ?animator.SetBool("isAttack00", false);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? ? break;? ? ? ? ? ?
? ? ? ? ? case State.ATTACK:? ? ? ? ? ? ? ? ? ? ? ? ?
? ? ? ? ? animator.SetBool("isAttack00", true);? ? ? ? ??
? ? ? ? ? ?animator.SetBool("isRun", false);? ? ? ? ??
? ? ? ? ? ?break;? ? ? ? ? ?
? ? ? ? ? ? case State.DANGER:? ? ? ? ? ? ?
? ? ? ? ? ? state = State.ATTACK;? ? ? ? ? ?
? ? ? ? ? ? ? break;? ? ? ?
? ? ? ? }? ?
? ?}? ??
? ? ////// 設(shè)置怪物血條,當(dāng)怪物在人物前方時顯示血條,否則隱藏
///void setBloodBar()? ? {? ? ??
? ? /**? ? ? ? * 此處判斷怪物是否在player的前方。 * 獲得player的forward,和兩者的距離,再通過Vector3.Angle取得player正前方方向與distance方向的角度? ? ? ? * 計算,magnitude表示兩者距離,angle當(dāng)角度小于45,證明怪物在player的正前方視野。? ? ? ? * */? ??
? ? ? Vector3 Playerforward = PlayerControl.instance.transform.TransformDirection(Vector3.forward); ? ? ?(從自身坐標(biāo)到世界坐標(biāo)的變換)
? ?//人物與怪物的距離? ? ? ?
? Vector3 distance = transform.position - playerPosition;? ? ?
? ? float angle = Vector3.Angle(Playerforward, distance);? ? ? ? ? ??
? ? ? ? if(angle<45 && distance.magnitude<15)? ? ? ? {? ? ? ?
? ? ? ? ? ?ui.SetActive(true);? ? ? ??
? ? ? }? ? ? ? else? ? ? ? {? ? ? ??
? ? ? ? ? ? ui.SetActive(false);? ? ??
? ? ? ?}? ? ? ? ? ? ? ??
? ? ? //這里可以判定一下,如果位置沒有變化就不要再賦值了? ? ??
? ? ? ?float newFomat = fomat / Vector3.Distance(head.position, Camera.main.transform.position);? ??
? ? ? ?ui.transform.position = WorldToUI(head.position);? ? ?
? ? ? ?ui.transform.localScale = Vector3.one * newFomat;? ?
? }? ? ? ?
? //核心代碼在這里把3D點換算成NGUI屏幕上的2D點。? ?
? public static Vector3 WorldToUI(Vector3 point)? ? {? ? ?
? ? Vector3 pt = Camera.main.WorldToScreenPoint(point);? ? ?
? ? Vector3 ff = UICamera.currentCamera.ScreenToWorldPoint(pt);? ? ? ??
? ? //UI的話z軸等于0? ? ? ??
? ? ? ff.z = 0;? ? ?
? ? ? return ff;? ?
? ? ?}
?}