Unity3d即時戰鬥之敵人AI和角色攻擊
阿新 • • 發佈:2019-01-16
角色控制指令碼Character.cs,為角色新增角色控制器Character controller。
角色屬性指令碼Health.cs<span style="font-size:14px;">using UnityEngine; using System.Collections; public class Character : MonoBehaviour { float attackInterval = 1.5f; float timer = 0; public float speed = 5.0F; public float jumpSpeed = 10.0F; public float gravity = 20.0F; private Vector3 moveDirection = Vector3.zero; private Animator anim; private CharacterController controller; public Transform cameraTarget; public GameObject effect1; public GameObject effect2; public GameObject effect3; public GameObject AttackObj; float Rot_y; Health heroHealth; Enemy enemy; private bool isRun = false; private bool isAttack = false; private bool isDeath = false; void Start () { heroHealth = GetComponent<Health> (); anim = GetComponent<Animator> (); controller = GetComponent<CharacterController> (); } // Update is called once per frame void Update () { if (heroHealth.currentheroHelth > 0) { if (!isAttack) { Move (); }else Attack (); } else if(!isDeath){ anim.SetTrigger ("Death"); isDeath = true; } } void OnTriggerEnter(Collider col){ if (col.gameObject.tag == "Monster") { isAttack = true; anim.SetBool ("isAttack", true); AttackObj = col.gameObject; enemy = AttackObj.GetComponent<Enemy> (); } } void OnTriggerExit(Collider col){ if (col.gameObject.tag == "Monster") { isAttack = false; anim.SetBool("isAttack",false); AttackObj = null; } } void Move(){ if (Input.GetKeyDown (KeyCode.LeftShift)) { if (!isRun) { isRun = true; anim.SetBool ("isRun", true); } else { isRun = false; anim.SetBool ("isRun", false); } } if (controller.isGrounded) { if (Input.GetButtonDown ("Jump")) { moveDirection.y = jumpSpeed; } } moveDirection.y -= gravity * Time.deltaTime; controller.Move( moveDirection * Time.deltaTime); if (Input.GetKey (KeyCode.A) || Input.GetKey (KeyCode.D) || Input.GetKey (KeyCode.W) || Input.GetKey (KeyCode.S)) { anim.SetInteger ("ActionID", 1); if (Input.GetKeyDown (KeyCode.W)) { Rot_y = cameraTarget.rotation.eulerAngles.y + 180; } else if (Input.GetKeyDown (KeyCode.S)) { Rot_y = cameraTarget.rotation.eulerAngles.y; } else if (Input.GetKeyDown (KeyCode.A)) { Rot_y = cameraTarget.rotation.eulerAngles.y + 90; } else if (Input.GetKeyDown (KeyCode.D)) { Rot_y = cameraTarget.rotation.eulerAngles.y - 90; } if (!isRun) { controller.Move (transform.forward * -speed * Time.deltaTime); } else controller.Move (transform.forward * -speed * 2 * Time.deltaTime); transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (0, Rot_y, 0), Time.deltaTime * 6); } else if (Input.GetMouseButton (1)) { anim.SetInteger ("ActionID", 1); } else { anim.SetInteger ("ActionID", 0); anim.SetInteger ("AttackID", 0); } } void Attack(){ timer += Time.deltaTime; if (Input.GetKeyDown (KeyCode.LeftShift)) { if (!isRun) { isRun = true; anim.SetBool ("isRun", true); } else { isRun = false; anim.SetBool ("isRun", false); } } if (Input.GetKey (KeyCode.A) || Input.GetKey (KeyCode.D) || Input.GetKey (KeyCode.W) || Input.GetKey (KeyCode.S)) { anim.SetInteger ("AttackID", 4); if (Input.GetKeyDown (KeyCode.W)) { Rot_y = cameraTarget.rotation.eulerAngles.y + 180; } else if (Input.GetKeyDown (KeyCode.S)) { Rot_y = cameraTarget.rotation.eulerAngles.y; } else if (Input.GetKeyDown (KeyCode.A)) { Rot_y = cameraTarget.rotation.eulerAngles.y + 90; } else if (Input.GetKeyDown (KeyCode.D)) { Rot_y = cameraTarget.rotation.eulerAngles.y - 90; } if (!isRun) { controller.Move (transform.forward * -speed * Time.deltaTime); } else controller.Move (transform.forward * -speed * 2 * Time.deltaTime); transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (0, Rot_y, 0), Time.deltaTime * 6); } else if (Input.GetKeyDown (KeyCode.J)) { transform.LookAt (AttackObj.transform.position); transform.eulerAngles += new Vector3 (0, 180, 0); if (timer >= attackInterval && enemy.currentEnemyHp > 0) { anim.SetInteger ("AttackID", 1); WaitAttackMonster (effect1); timer = 0; } } else if (Input.GetKeyDown (KeyCode.K)) { transform.LookAt (AttackObj.transform.position); transform.eulerAngles += new Vector3 (0, 180, 0); if (timer >= attackInterval && enemy.currentEnemyHp > 0) { anim.SetInteger ("AttackID", 2); WaitAttackMonster (effect2); timer = 0; } } else if (Input.GetKeyDown (KeyCode.L)) { transform.LookAt (AttackObj.transform.position); transform.eulerAngles += new Vector3 (0, 180, 0); if (timer >= attackInterval && enemy.currentEnemyHp > 0) { anim.SetInteger ("AttackID", 3); WaitAttackMonster (effect3); timer = 0; } }else if (Input.GetMouseButton (1)) { anim.SetInteger ("AttackID", 4); } else { anim.SetInteger ("AttackID", 0); anim.SetInteger ("ActionID", 0); } } void WaitAttackMonster(GameObject effect){ enemy.currentEnemyHp -= heroHealth.attack; GameObject proObj = (GameObject)Instantiate (effect, AttackObj.transform.position, Quaternion.identity); } }</span>
敵人AI戰鬥指令碼 Enemy.cs,為敵人新增標籤(tag)“Monster”,新增尋路元件NavMeshAgent,把環境靜態變數變成True進行路徑(Navigation)渲染Bake<span style="font-size:14px;">using UnityEngine; using System.Collections; public class Health : MonoBehaviour { public int attack = 20; public int heroHealth = 100; public int currentheroHelth; public bool isDamage = false; UIManager uiManager; void Awake(){ currentheroHelth = heroHealth; uiManager = GameObject.FindGameObjectWithTag ("UIManager").GetComponent<UIManager> (); } public void TakeDamage(int damage){ isDamage = true; currentheroHelth -= damage; uiManager.updateHealthBar (currentheroHelth); } }</span>
UI管理指令碼UIManager.cs<span style="font-size:14px;">using UnityEngine; using System.Collections; using UnityEngine.UI; public class Enemy : MonoBehaviour { public Sprite Head; public int EnemyHp = 200; public int currentEnemyHp; GameObject hero; NavMeshAgent agent; Animator anim; CharacterController controller; public int attack = 20; public float attackInterval = 2f; float timer = 0; Health heroHealth; float dis; float times = 10.0f; int Action; bool heroInRange; bool isDeath = false; void Awake(){ currentEnemyHp = EnemyHp; hero = GameObject.FindGameObjectWithTag ("Player"); heroHealth = hero.GetComponent<Health> (); agent = GetComponent<NavMeshAgent> (); anim = GetComponent<Animator> (); controller = GetComponent<CharacterController> (); } void Update(){ dis = Vector3.Distance (this.transform.position, hero.transform.position); if (currentEnemyHp > 0) { Activity (); } else if (!isDeath) { anim.SetTrigger ("Death"); isDeath = true; } } void Activity(){ if (dis > 15) { anim.SetBool ("isRun", false); anim.SetBool ("isAttack", false); times -= Time.deltaTime; if (times < 0) { Action = Random.Range (0, 5); times = 10.0f; } switch (Action) { case 0: anim.SetBool ("isWalk", false); transform.Rotate (0, 8 * Time.deltaTime, 0); break; case 1: anim.SetBool ("isWalk", false); transform.Rotate (0, -8 * Time.deltaTime, 0); break; case 2: anim.SetBool ("isWalk", true); controller.Move (transform.forward * -3 * Time.deltaTime); break; default: anim.SetBool ("isWalk", false); break; } } else if (dis > 7 && dis <= 15) { anim.SetBool ("isWalk", false); anim.SetBool ("isAttack", false); anim.SetBool ("isRun", true); transform.LookAt (hero.transform.position); transform.eulerAngles += new Vector3 (0, 180, 0); agent.SetDestination (hero.transform.position); } else { anim.SetBool ("isWalk", false); anim.SetBool ("isRun", false); anim.SetBool ("isAttack", true); transform.LookAt (hero.transform.position); transform.eulerAngles += new Vector3 (0, 180, 0); timer += Time.deltaTime; if (timer >= attackInterval) { Attack (); timer = 0; } } } void Attack(){ int ActionAttack = Random.Range (1, 5); if (heroHealth.currentheroHelth > 0) { switch (ActionAttack) { case 1: anim.SetInteger ("AttackID", 1); break; case 2: anim.SetInteger ("AttackID", 2); break; case 3: anim.SetInteger ("AttackID", 3); break; default: anim.SetInteger ("AttackID", 4); break; } if(heroInRange) heroHealth.TakeDamage (attack); }else anim.SetInteger ("AttackID", 0); } void OnTriggerEnter(Collider col){ if (col.gameObject == hero) { heroInRange = true; } } void OnTriggerExit(Collider col){ if (col.gameObject == hero) { heroInRange = false; } } }</span>
<span style="font-size:14px;">using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class UIManager : MonoBehaviour {
Health heroHealth;
Character character;
public Slider HealthBar;
public Slider EnemyHpBar;
public Image Head;
public Image flashScreen;
public float flashSpeed = 0.5f;
public Color flashColor = new Color (1f, 0f, 0f, 0.1f);
void Awake(){
heroHealth = GameObject.FindGameObjectWithTag ("Player").GetComponent<Health> ();
character = GameObject.FindGameObjectWithTag ("Player").GetComponent<Character> ();
}
public void updateHealthBar(int value){
HealthBar.value = (float)value / heroHealth.heroHealth;
}
void Update(){
if (!character.AttackObj) {
EnemyHpBar.gameObject.SetActive (false);
Head.gameObject.SetActive (false);
} else {
Enemy enemy = character.AttackObj.GetComponent<Enemy> ();
EnemyHpBar.gameObject.SetActive (true);
Head.gameObject.SetActive (true);
EnemyHpBar.value = (float)enemy.currentEnemyHp / enemy.EnemyHp;
Head.sprite = enemy.Head;
}
if (heroHealth.isDamage) {
flashScreen.color = flashColor;
} else {
flashScreen.color = Color.Lerp (flashScreen.color, Color.clear, flashSpeed * Time.deltaTime);
}
heroHealth.isDamage = false;
}
}</span>
最後幾張執行效果圖