2-17 Player Melee Damage
今天要來製作玩家的範圍技!哈哈,不過還沒有動畫特效啦,先把程式碼的部分實作好。首先請大家下載課程提供的武器:
自己匯入。
匯入之後放在場景中。
然後請將武器物件放到Player中,結構如下圖。Player/Armature/Hips/Spine/Shoulder_R/Upper_Arm_R/Lower_Arm_R/Hand_R底下,簡言之就是右手下面啦。
然後請自己調整武器的位置,就像是握在手上。執行看看吧,開始遊戲後武器就會跟人物的動畫綁在一起。
以下提供程式碼,註解也寫在程式碼中嘍:
Player.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class Player : MonoBehaviour, IDamageable { [SerializeField] float maxHealthPoints = 100f; [SerializeField] float damagePerHit = 50f; [SerializeField] float minTimeBetweenHits = 0.5f; [SerializeField] float maxAttackRange = 5f; GameObject currentTarget; float currentHealthPoint; float lastHitTime; CameraRaycaster cameraRaycaster; public float healthAsPercentage{ get{ return currentHealthPoint / maxHealthPoints; } } void Start(){ // 初始化血量 currentHealthPoint = maxHealthPoints; cameraRaycaster = FindObjectOfType(); cameraRaycaster.notifyMouseClickObservers += OnMouseClick ; } void OnMouseClick(RaycastHit raycastHit, int layerHit){ const int enemyLayer = 9; if (layerHit == enemyLayer) { GameObject enemy = raycastHit.collider.gameObject; // 確認敵人是否在範圍技的攻擊範圍內 if ((enemy.transform.position - transform.position).magnitude > maxAttackRange) { return; // 超過攻擊範圍就跳出 } // 控制攻擊頻率,若本次攻擊時間離上一次攻擊時間大於minTimeBetweenHits,才允許攻擊 // 相當於範圍技的CD時間,不能一直發動技能! if (Time.time - lastHitTime > minTimeBetweenHits) { currentTarget = enemy; IDamageable enemyDamageable = enemy.GetComponent (typeof(IDamageable)) as IDamageable; // 讓敵人損血 enemyDamageable.TakeDamage (damagePerHit); // 紀錄目前攻擊的時間 lastHitTime = Time.time; } } } public void TakeDamage(float damage){ // Math.Clamp可以確保數值運算後不會低於最小值或者高於最大值 currentHealthPoint = Mathf.Clamp (currentHealthPoint - damage, 0f, maxHealthPoints); } }
Enemy.cs:
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using UnityStandardAssets.Characters.ThirdPerson; public class Enemy : MonoBehaviour, IDamageable { [SerializeField] float maxHealthPoints = 100f; [SerializeField] float attackRadius = 3.0f; [SerializeField] float chaseRadius = 10.0f; [SerializeField] float damagePerShot = 9f; [SerializeField] float secondsBetweenShots = 0.5f; [SerializeField] GameObject projectileToUse; [SerializeField] GameObject projectileSocket; [SerializeField] Vector3 aimOffset = new Vector3(0, 1f, 0); bool isAttacking = false; float currentHealthPoint = 100f; AICharacterControl aiCharacterControl = null; GameObject player; IEnumerator coroutine; public float healthAsPercentage{ get{ return currentHealthPoint / maxHealthPoints; } } void Start(){ aiCharacterControl = GetComponent(); player = GameObject.FindGameObjectWithTag ("Player"); } void Update(){ // 計算Player跟Enemy的距離 float distanceToPlayer = Vector3.Distance (player.transform.position, transform.position); // 若彼此之間的距離小於attackRadius,就讓Enemy開始攻擊Player if (distanceToPlayer <= attackRadius && !isAttacking) { isAttacking = true; coroutine = SpawnProjectile (); StartCoroutine (coroutine); } if (distanceToPlayer > attackRadius && isAttacking) { isAttacking = false; StopCoroutine (coroutine); } // 若彼此之間的距離小於chaseRadius,就讓Enemy開始追蹤Player if (distanceToPlayer <= chaseRadius) { aiCharacterControl.SetTarget (player.transform); } else { aiCharacterControl.SetTarget (transform); } } IEnumerator SpawnProjectile(){ while (true) { yield return new WaitForSeconds (secondsBetweenShots); // Instantiate可以生成GameObject,Quaternion.identity為方向不進行任何轉向 GameObject newProjectile = Instantiate(projectileToUse, projectileSocket.transform.position, Quaternion.identity); // 取得Projectile Projectile projectileComponent = newProjectile.GetComponent (); // 設定Projectile的攻擊威力 projectileComponent.SetDamage(damagePerShot); // 計算發射Projectile到Player之間的單位向量 Vector3 unitVectorToPlayer = (player.transform.position + aimOffset - projectileSocket.transform.position).normalized; float projectileSpeed = projectileComponent.projectileSpeed; // 將單位向量乘以發射速度,透過velocity將Projectile發射出去吧! newProjectile.GetComponent ().velocity = unitVectorToPlayer * projectileSpeed; } } public void TakeDamage(float damage){ // Math.Clamp可以確保數值運算後不會低於最小值或者高於最大值 currentHealthPoint = Mathf.Clamp (currentHealthPoint - damage, 0f, maxHealthPoints); // 敵人血量低於0就會消失 if (currentHealthPoint <= 0) { Destroy (gameObject); } } void OnDrawGizmos(){ //繪製攻擊範圍 Gizmos.color = new Color(255f, 0f, 0f, 0.5f); Gizmos.DrawWireSphere (transform.position, attackRadius); //繪製移動範圍 Gizmos.color = new Color(0f, 0f, 255f, 0.5f); Gizmos.DrawWireSphere (transform.position, chaseRadius); } }
開始執行遊戲後,玩家點擊敵人就會走到敵人前面,並且在進入玩家的範圍攻擊內(玩家的紅色框框)才可以讓敵人損血,而且攻擊敵人時有我設定的CD時間0.5秒。
將敵人打死後,敵人就會消失。
留言
張貼留言