Unity近戰攻擊邏輯與範圍判定

來源於一個因爲某些原因做廢了的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;
    }

}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章