[Unity] ACT 战斗系统学习 1:基于委托的事件管理器

本文介绍了在Unity中学习ACT战斗系统的过程,重点探讨了如何使用委托实现事件管理。通过分析示例代码BattleManager.cs和ActorManager.cs,解释了如何确保数据共享和逻辑封装。同时,提到了在事件管理中遇到的问题及解决方案,如利用Action和Func简化委托的使用。
摘要由CSDN通过智能技术生成

我觉得看视频太慢了,还是看别人源码更快……

1.664235822/DarkSouls-Demo

Github 源码:
https://github.com/664235822/DarkSouls-Demo

其中关于战斗的主要代码:

BattleManager.cs

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[RequireComponent(typeof(CapsuleCollider))]
public class BattleManager : IActorManagerInterface
{
   
    private void OnTriggerEnter(Collider other)
    {
   
        WeaponController targetController = other.GetComponentInParent<WeaponController>();

        if (targetController == null) return;

        GameObject attacker = targetController.weaponManager.actorManager.gameObject;
        GameObject receiver = actorManager.actorController.model.gameObject;

        bool attackValid = CheckAngleTarget(receiver, attacker, 45.0f);
        bool counterValid = CheckAnglePlayer(receiver, attacker, 30.0f);

        if (other.gameObject.layer == LayerMask.NameToLayer("Weapon"))
        {
   
            actorManager.TryDoDamage(targetController, attackValid, counterValid);
        }
    }

    /// <summary>
    /// 检查格挡
    /// </summary>
    /// <param name="player"></param>
    /// <param name="target"></param>
    /// <param name="playerAngle"></param>
    /// <returns></returns>
    public static bool CheckAnglePlayer(GameObject player, GameObject target, float playerAngle)
    {
   
        Vector3 counterDir = target.transform.position - player.transform.position;
        float counterAngle = Vector3.Angle(player.transform.forward, counterDir);
        float counterAngle2 = Vector3.Angle(target.transform.forward, player.transform.forward);

        bool counterValid = (counterAngle < playerAngle && Mathf.Abs(counterAngle2 - 180.0f) < playerAngle);
        return counterValid;
    }

    public static bool CheckAngleTarget(GameObject player, GameObject target, float targetAngle)
    {
   
        Vector3 attackingDir = player.transform.position - target.transform.position;
        float attackingAngle = Vector3.Angle(target.transform.forward, attackingDir);

        bool attackValid = (attackingAngle < targetAngle);
        return attackValid;
    }


}

ActorManager.cs

public class ActorManager : MonoBehaviour
{
   
    public ActorController actorController;
    public BattleManager battleManager;
    public WeaponManager weaponManager;
    public StateManager stateManager;
    public DirectorManager directorManager;
    public InteractionManager interactionManager;

    public void TryDoDamage(WeaponController target, bool attackValid, bool counterValid)
    {
   
        // 如果自己正在无敌状态,那么目标不会受到伤害
        if (stateManager.isImmortal)
        {
   
        }
        // 如果自己允许使用 counter,并且该次攻击 counter 角度成立,那么目标进入被眩晕流程
        else if (stateManager.isCounterBack && counterValid)
        {
   
            target.weaponManager.actorManager.Stunned();
        }
        // 如果自己正在防御,那么自己进入格挡流程
        // counter 的优先级高于防御
        else if (stateManager.isDefence)
        {
   
            Blocked();
        }
        // 以上情况均不成立,进入伤害判断
        else
        {
   
            // 如果自己血量大于 0,并且攻击有效,那么可以对自己造成伤害
            if (stateManager.HP > 0 && attackValid)
            {
   
                // 思考:这里是在武器伤害的部分检查死亡
                // 等到流程多了之后,应该在别的地方判断死亡
                // 比如在 HP 的 setter 的地方判断死亡
                // 还有就是,之后应该将受到攻击的流程和死亡的流程不放在同一个逻辑层级里面
                
                // 对自己造成伤害的值就是目标的武器的伤害值
                stateManager.AddHP(-1 * target.WeaponData.ATK);
                // 如果自己血量被扣除之后仍然大于 0,那么自己进入受攻击流程
                if (stateManager.HP > 0)
                {
   
                    // 进入被攻击流程
                    Hit();
                }
                // 如果自己血量被扣除之后小于 0,那么自己进入死亡流程
                else
                {
   
                    // 死亡流程
                    Die();
                }
            }
        }
    }

    private void Blocked()
    {
   
        actorController.IssueTrigger("blocked");
    }

    private void Hit()
    {
   
        actorController.IssueTrigger("hit");
    }

    public void Stunned()
    {
   
        actorController.IssueTrigger("stunned");
    }

    public void SetIsCounterBack(bool value)
    {
   
        stateManager.isCounterBack = value;
    }

    private void Die()
    {
   
        actorController.IssueTrigger("die");
        actorController.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值