來源於一個因爲某些原因做廢了的Demo:
實現主角攻擊敵人的傷害範圍判定,以及自動轉到距離玩家最近的敵人方向。
實現思路:
這個是我在玩王者榮耀的時候想到的,在王者榮耀中,當你按下普通攻擊鍵的時候。
角色會首先判斷在最大偵察範圍內,周圍有沒有敵人。
如果有敵人的話。
判斷敵人與玩家距離是否小於等於玩家的最大攻擊距離。
如果 玩家與怪物之間的距離大於等於玩家的最大攻擊距離的話,玩家會自動尋路到敵人的位置,當然不是無限位移,是當與敵人位置小於等於角色最大攻擊範圍的時候,停止位移,轉向敵人。
如果 玩家與怪物之間的距離小於玩家的距離,直接把玩家扭向敵人,然後再調用攻擊方法。
當然這只是基本的判定方式,實際上還有很多複雜的判斷條件。
這裏看下實現效果:
方便演示,這裏關閉了怪物對玩家的傷害。
下面是代碼實現:
核心思路就是維護場景中一個所有敵人的集合,然後對這個集合來進行操作。
using Control;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Model;
public class Ctrl_HeroAttackProcess : MonoBehaviour {
//把附近的所有敵人放入一個GameObejct的集合
//在一定範圍內,遍歷集合中找出最近的敵人,自動關注面朝向敵人
//相應輸入攻擊的輸入指令,對主角最近的敵人進行傷害處理
//定義敵人集合
private List<GameObject> EnemyList;
//定義普通 攻擊距離
private float NormalAttack = 2.3f;
//定義最大的攻擊距離
private float MaxAttackDistance = 3.4f;
//定義最近的的敵人
private GameObject NearstEnemy;
//
private void Start()
{
//敵人集合初始化
EnemyList = new List<GameObject>();
//開啓敵人偵測協程
StartCoroutine("EnemyDetector");
}
/// <summary>
/// 開啓敵人偵測協程
/// </summary>
/// <returns></returns>
IEnumerator EnemyDetector()
{
while (true)
{
yield return null;
//找到場景中所有活着的敵人
FindScenceEnemy();
//定位最近的敵人
FindNearestEnemy();
}
}
/// <summary>
/// 找到所有活着的敵人
/// </summary>
private void FindScenceEnemy()
{
EnemyList.Clear();
//先找到場景中的所有敵人
GameObject [] EnemyArray = GameObject.FindGameObjectsWithTag("enemy");
//再篩選出符合條件也就是活着的敵人
for (int i = 0; i < EnemyArray.Length; i++)
{
//判斷是否活着,等敵人屬性腳本編寫完成後
if (EnemyArray[i].GetComponent<Ctrl_Enemy_ShuXing>().CurrentState!=Global.GlobalParameter.EnemyState.Dealth)
{
EnemyList.Add(EnemyArray[i]);
}
}
}
/// <summary>
/// 找到最大攻擊距離內最近的敵人
/// </summary>
public void FindNearestEnemy()
{
NearstEnemy = null;
float Distance = MaxAttackDistance;
if (EnemyList != null && EnemyList.Count >=1)
{
for (int i = 0; i < EnemyList.Count; i++)
{
float EnemyAndMeDistance = CalculationOfDistance(EnemyList[i].transform.position);
if (EnemyAndMeDistance<Distance)
{
Distance = EnemyAndMeDistance;
NearstEnemy = EnemyList[i];
}
}
if (NearstEnemy!=null)
{
if (CalculationOfDistance(NearstEnemy.transform.position) <= MaxAttackDistance)
{
//Debug.Log("最近敵人名爲:" + NearstEnemy.name);
}
}
}
}
/// <summary>
/// 普通攻擊傷害計算
/// </summary>
public void NormalAttackDamageCalculation()
{
if (EnemyList == null || EnemyList.Count <=0)
{
return;
}
for (int i = 0; i < EnemyList.Count; i++)
{
//敵我距離
float EnemyAndMe = CalculationOfDistance(EnemyList[i].transform.position);
//構造向量線段
Vector3 EnemyAndMeVector = (EnemyList[i].transform.position - transform.position).normalized;
//範圍點乘計算
float EnemyAndMeVectorDot = Vector3.Dot(transform.forward, EnemyAndMeVector);
//旋轉角色普通攻擊範圍內角色正在攻擊的的敵人的位置
if (NearstEnemy != null) //這裏要注意判空一下最近敵人是有可能爲空的
{
if (CalculationOfDistance(NearstEnemy.transform.position) <= NormalAttack)
{
//Debug.Log("要轉向的敵人的名字"+NearstEnemy.name);
Quaternion dir = Quaternion.LookRotation(new Vector3(NearstEnemy.transform.position.x,0, NearstEnemy.transform.position.z)-new Vector3(this.transform.position.x,0, this.transform.position.z));
transform.rotation = dir;
}
}
//發送普通攻擊傷害
if (EnemyAndMeVectorDot > 0f&&EnemyAndMe<= NormalAttack)
{
// Debug.Log("傷害打出了"+"打中了"+EnemyList[i].name);
EnemyList[i].SendMessage("MakeHurt",Model_PlayerDataPloxy.GetInstance().GetCurrentAttackForce(),SendMessageOptions.DontRequireReceiver);
}
}
}
/// <summary>
/// 計算敵我距離
/// </summary>
/// <param name="a"></param>
/// <param name="b"></param>
/// <returns></returns>
private float CalculationOfDistance(Vector3 a)
{
float EnemyAndMeDistance = Vector3.Distance(this.transform.position, a);
return EnemyAndMeDistance;
}
}