RPG2.0戰鬥框架學習5之目標被擊處理

前言


這篇學習,作用到(攻擊/治癒/BUFF)到目標後的邏輯處理.


步驟


1 到子彈接觸到目標後,會執行目標上AI腳本的BeHit方法


    /// <summary>子彈打到目標,計算傷害值,根據玩家和敵人的屬性,在子彈所有人身上計算出目標承受的傷害值</summary> 
    public virtual void BeHit(AttackBullteS bullte)
    {
        //健壯性判斷
        if (!CanProgramme()) return;
        //判斷技能的類型,將目標設置爲施法者
        if (targetObj == null && (bullte.skillData.attackType == SkillType.Attack || bullte.skillData.attackType == SkillType.None))
            InputTargetObj(bullte.bullteOwner.gameObject);//如果沒有目標,目標設爲攻擊者
        //這裏的操作是停掉所有協程
        StopAllCoroutines();
        //計算傷害
        CostDamage(gameRoleProperty.DamageValue(bullte), bullte);
        //計算buff
        CostBuff(bullte);
        //計算其他邏輯   
    }

2 計算傷害值,你需要施法者的數值和目標者的數值,進行計算得出,這裏我們定義一個傷害值類,通過一個方法得出

    public class BeHitClass
    {
        //數值
        public int damageValue;
        /// <summary> 傷害類型,0普通,1暴擊,2治療</summary>
        public int damageType = 0;
        public float repelValue = 0;
        public BeHitClass(int damagevalue, int damagetype)
        {
            damageValue = damagevalue;
            damageType = damagetype;
        }
        public BeHitClass CloneMe()
        {
            BeHitClass result = new BeHitClass(damageValue, damageType);
            result.repelValue = repelValue;
            return result;
        }
    }

    public BeHitClass DamageValue(AttackBullteS bullte)
    {
        //new一個BeHit類
        BeHitClass result = new GameRoleAI.BeHitClass(0, 0);
        //通過子彈,得到施法者的數值
        GameRoleProperty roleProperty = bullte.bullteOwner.GetComponent<GameRoleProperty>();
        //計算總傷害值
        result.damageValue = GetDamageAmount(roleProperty, this);//一個公式          
        //計算多端傷害的比值
        result.damageValue = (int)(result.damageValue * roleProperty.skillList[bullte.skillIndex].damageList[bullte.damageIndex].damageRate);
        //計算其他

        return result;
    }

    /// <summary> 受到傷害減血或者加血 </summary> 
    public virtual void CostDamage(BeHitClass damageValue, AttackBullteS bullte)
    {
        //健壯性判斷
        if (bullte.skillData == null) return;        
        //決定數值類型,是skill中的參數,這點感覺有點彆扭,保留意見
        float parammean = -1;//該次傷害產生的效果,(0:hp-)(1:hp+)(2:施法者hp+)(3:施法者hp-)(4:)
        ///傷害類型 0 : 普通傷害
        parammean = bullte.skillData.GetParamByParamMean(0);
        BeHitClass tempbehit;
        if (parammean >= 0)
        {
            tempbehit = damageValue.CloneMe();
            if (damageValue.damageType == 2) damageValue.damageType = 0;//如果是治療效果,則變成受傷害效果
            gameRoleProperty.hpNow = Mathf.Clamp(gameRoleProperty.hpNow - tempbehit.damageValue, 0, gameRoleProperty.hpmaxNow);
            
            gameRoleAnimator.Playinjury(tempbehit, bullte);//執行顯示數值的方法
            //播放音效
            if (gameRoleProperty.hpNow == 0)
            {
                ChangeSta2Die();//目標死亡
            }
            else
            {
                StartCoroutine(DetectBehitEnd(tempbehit, bullte));//執行擊退效果(屬於一種BUFF)                
            }
            //刷新血條
            gameRoleAnimator.SetHpBar((float)gameRoleProperty.hpNow / gameRoleProperty.hpmaxNow);
        }
        ///傷害類型 1 : 治療
        parammean = bullte.skillData.GetParamByParamMean(1);
        if (parammean >= 0)
        {
            //目標加血
        }
        ///傷害類型 2 : 吸血
        parammean = bullte.skillData.GetParamByParamMean(2);
        if (parammean >= 0)
        {
            //目標扣血
            //施法者加血
        }
    }
    
    public virtual IEnumerator DetectBehitEnd(BeHitClass damageValue, AttackBullteS bullte)
    {
        if (damageValue.repelValue > 0)//如果擊退值大於0,則被擊退
        {
            //new一個BUFF
            Buff bufftemp = new Buff();
            //設置參數
            bufftemp.Duration = damageValue.repelValue;
            bufftemp.Script = "HitBack";
            bufftemp.owner = bullte.bullteOwner.gameObject;
            //添加BUFF
            gameRoleBuffFX.AddBuff(bufftemp);
        }
        yield return null;

    }

3 看看Animator執行顯示數值的方法


    public virtual void Playinjury(GameRoleAI.BeHitClass damageValue, AttackBullteS attackbullteS)
    {
        GameObject tempo = null;//數值顯示prefab
        //設置數字顯示座標
        Vector3 temppos = transform.position + new Vector3(Random.Range(-0.5f, 0.5f), Random.Range(0f, 0.5f), Random.Range(-0.5f, 0.5f));
        if (bodyPart.bodypartBody != null) temppos = bodyPart.bodypartBody.transform.position;
        //怪物和角色數值顯示不一樣
        if (tag == "Monster")
        {
            if (damageValue.damageType == 0 && attackbullteS.skillIndex > 0) damageValue.damageType = 6;
            if (damageValue.damageValue > 0) tempo = Instantiate(SAOResources.SAOIcon("damageFX" + damageValue.damageType) as GameObject, temppos, Camera.main.transform.rotation) as GameObject;
            //設置目標被擊時的閃紅效果
            FXRoleBehitShine fxtemp = gameObject.GetComponent<FXRoleBehitShine>();
            if (fxtemp != null)
            {
                fxtemp.Resum(Color.white, 0.5f);
            }
            else
            {
                fxtemp = gameObject.AddComponent<FXRoleBehitShine>();
                fxtemp.Initialize(Color.white, 0.5f);
            }
        }
        if (tag == "Player")
        {
            if (damageValue.damageValue > 0) tempo = Instantiate(SAOResources.SAOIcon("damageFX" + (3 + damageValue.damageType)) as GameObject, temppos, Camera.main.transform.rotation) as GameObject;
        }

        if (tempo != null && damageValue.damageValue > 0)
        {
            //保證UI顯示在最前面
            UIWidget[] uiws = tempo.GetComponentsInChildren<UIWidget>(true);
            foreach (UIWidget uiw in uiws) uiw.depth = UIRoot.list[0].transform.childCount;
            Destroy(tempo, 3);
            tempo.name = transform.name + " damagetype " + damageValue.damageType;
            //顯示數值(用的是sprite)
            tempo.GetComponent<DamageFX0>().ShowDamage(damageValue.damageValue, transform);

        }
    }

4 介紹 BUFF的簡單思路,常見的BUFF有,擊退,石化,冰凍,減速,減益(降低防禦,攻擊),中毒/撕裂(持續掉血)。

BUFF就像一個組件,當中了BUFF時,就掛在目標上,腳本上的Update方法,就在buff持續時間中,執行寫代碼,實現不同的效果

BUFF系統需要哪些腳本呢

BUFF:entity類

BUFFBase:總結出BUFF的通用方法,比如begin,effet,end方法

BUFF_XX:繼承BUFFBase,實現具體代碼

BUFFMgr:控制BUFF的增刪查改

    public class Buff
    {
        public int Id;
        public string Name;
        public int Type;//類型
        public float Duration;//持續時間
        public string Script;//腳本名稱,作爲索引
        public List<float> Param;//參數
        public float ReleaseRate;//觸發機率
        public int RealLevel;//基礎等級
        public int AddRealLevel;//增加等級
        public List<float> Ratio;//成長參數
        public int Effect;

        public BuffDataEntity Data;
        public GameObject owner;
    }

using UnityEngine;
using System.Collections;

public class BuffBase : MonoBehaviour {
    public Buff buffData;
    public GameRoleAI ai; //目標AI
    public float intervalTime = 0.5f;//BUFF作用間隔
    public float ti = 0;
    /// <summary>爲true時使用幀數,爲false使用時間 </summary>
    public bool realTime = false;
    float time0;
	void Start () {
	    
	} 
	void Update () {
        //健壯性判斷
        if (ai.sta == GameRoleStaus.Die)
        {
            this.enabled = false;
            return;
        }
        if (realTime)//使用幀數
        {
            time0--;
            if (time0 < 0)
            {
                BuffEnd();
                Destroy(this);
                return;
            }
            ti++;
        }
        else//使用時間
        {
            if ((Time.time - time0) > buffData.Duration)//超出持續時間
            {
                BuffEnd();
                Destroy(this);
                return;
            }
            ti += Time.deltaTime;
        }
        if (ti > intervalTime)//到了作用時間
        {
            ti = 0;
            BuffCost();
        }
	}
    //
    public virtual void RefreshBuff(Buff buffdata)
    {
        buffData = buffdata;
        time0 = Time.time;
        if (realTime) time0 = buffdata.Duration;
        BuffBegin();
    }
    /// <summary> 初始化 </summary>
    public virtual void Initialize(Buff buffdata)
    {
        ai = GetComponent<GameRoleAI>();
        buffData = buffdata; 
        //Destroy(this, buffduration);
        time0 = Time.time;
        if (realTime) time0 = buffdata.Duration;
        BuffBegin();
    }
    /// <summary> buff開始時調用的函數</summary>
    public virtual void BuffBegin()
    {

    }
    /// <summary> buff結束時調用的函數</summary>
    public virtual void BuffEnd()
    {

    }
    /// <summary> buff發揮作用時調用的 </summary>
    public virtual void BuffCost()
    {

    }
    public virtual void BuffCancel()
    {
        BuffEnd();
        Destroy(this);
    }
}

這裏,寫一箇中毒BUFF


    public class Buff_Poison : BuffBase
    {
        public override void BuffBegin()
        {
            ai.gameRoleIcon.ShowIcon(GameRoleIconType.Poison);//顯示中毒的圖標
            intervalTime = 1f;//間隔時間是1秒
        }
        public override void BuffEnd()
        {
            ai.gameRoleIcon.HideIcon(GameRoleIconType.Poison);//去掉中毒圖標

        }
        public override void BuffCost()
        {
            //製作一個BeHitClass類
            GameRoleAI.BeHitClass beHitClass = new GameRoleAI.BeHitClass((int)buffData.Param[0], 0);
            AttackBullteS attackBullteS = new AttackBullteS();
            if (buffData.owner == null) return;
            attackBullteS.bullteOwner = buffData.owner.GetComponent<GameRoleAnimator>();
            ai.CostDamage(beHitClass, attackBullteS);
        }
    }

public class BuffMgr : MonoBehaviour {
    public List<BuffBase> saoBufflist = new List<BuffBase>();//存放目標上所有BUFF
    public GameRoleAI ai;//目標AI
	void Start () {
        ai = GetComponent<GameRoleAI>();
	}
	void Update () {
        if (ai.sta != GameRoleStaus.Die)
        {
            for (int i =0;i<saoBufflist.Count;i++)//實時刷新BUFF集合
            {
                if (saoBufflist[i] == null)
                {
                    saoBufflist.RemoveAt(i);
                    i -= 1;
                }
            }
        }
        else
        {
            //StartCoroutine("BuffDisappear");
        }
        if (ai.sta == GameRoleStaus.Unusual)//有的BUFF例如中毒,不需要改變AI的狀態,而石化,需要改變AI的狀態,
        {
            if (CanMove()) ai.sta = GameRoleStaus.Wait;
        }
	}
    IEnumerator BuffDisappear()
    {

        yield return null;
    }
    /// <summary> 移除所有有利和不利buff</summary>
    public void RemoveAll()
    {
        foreach (SaoBuffBase bufftemp in saoBufflist)
        {
            bufftemp.BuffCancel();
        }
    }
    public void RemoveAllDebuff()
    {
        foreach (SaoBuffBase bufftemp in saoBufflist)
        {
            if (bufftemp.buffData.Type==1) bufftemp.BuffCancel();
        }
    }
    public void RemoveAllBuff()
    {
        foreach (SaoBuffBase bufftemp in saoBufflist)
        {
            if (bufftemp.buffData.Type == 0) bufftemp.BuffCancel();
        }
    }
    /// <summary> 看看餘下的buff是否能夠移動 </summary>
    public bool CanMove()
    {
        foreach (BuffBase buffone in saoBufflist)
        {
            if (buffone.buffData.Script == "Stone") return false;
            if (buffone.buffData.Script == "Frozen") return false;
            if (buffone.buffData.Script == "Stun") return false;
            if (buffone.buffData.Script == "KnockDown") return false;
        }
        return true;
    }
    //添加一個buff效果
    public void AddBuff(SAOBuff saobuff)
    {
        if (saobuff == null) return; 
        foreach (BuffBase tempb in saoBufflist)
        {
            if (tempb.buffData.Id == saobuff.Id)//如果id一致則判斷爲相同的buff,則刪除之前的buff,加入新的buff
            {
                tempb.RefreshBuff(saobuff);
                return;//如果爲true,則已經存在,不再添加
            }
        }
        Component buffcomponent = gameObject.AddComponent("SaoBuff_" + saobuff.Script);
        
        BuffBase itemtemp = null;
        if (buffcomponent != null) itemtemp = buffcomponent as BuffBase;
        if (itemtemp != null)
        {
            itemtemp.Initialize(saobuff);
            saoBufflist.Add(itemtemp);
        }
    }
}

以上,基本就可以對BUFF進行操作


    public virtual void CostBuff(AttackBullteS bullte)
    { 
        //健壯性判斷
        if (sta == GameRoleStaus.Die) return;
        if (bullte.buff.Count < 1) return; 
        GameRoleProperty owner = bullte.bullteOwner.GetComponent<GameRoleProperty>();
        //將攻擊中帶的BUFF,經過幾率判斷,加到AI上
        foreach(SAOBuff bufftemp in bullte.buff) gameRoleBuffFX.AddBuff(gameRoleProperty.BuffValue(bufftemp, owner));
    }


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