1. 程式人生 > >Unity3d即時戰鬥之敵人AI和角色攻擊

Unity3d即時戰鬥之敵人AI和角色攻擊

角色控制指令碼Character.cs,為角色新增角色控制器Character controller。

<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>
角色屬性指令碼Health.cs
<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>
敵人AI戰鬥指令碼 Enemy.cs,為敵人新增標籤(tag)“Monster”,新增尋路元件NavMeshAgent,把環境靜態變數變成True進行路徑(Navigation)渲染Bake
<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>
UI管理指令碼UIManager.cs
<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>
最後幾張執行效果圖




相關推薦

no