转载POWERFUL ACTION-REACTION System in Unity|BEST Card Game ARCHITECTURE!Unity 中强大的“动作-反应”系统|最佳卡牌游戏架构!

原视频网址:POWERFUL ACTION-REACTION System in Unity | BEST Card Game ARCHITECTURE!

B站上也有搬运的带翻译的视频,但是没有人分享代码,视频里代码都是分段截出来的,而且都没有写注释,这个系统太庞大了,我使用的时候才发现我有的代码都敲错了,也没有人分享完整的代码,所以我这里分享一下

贴一下系统的代码 注释有的是自己写的,有的是ai写的

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

public class ActionSystem : MonoSingleton<ActionSystem>
{
    //当前阶段反应列表的引用
    private List<GameAction> reactions = null;
    //正在执行 属性
    public bool IsPerforming { get; private set; } = false;
    // 事件订阅系统(按事件类型分类存储)
    private static Dictionary<Type, List<Action<GameAction>>> preSubs = new Dictionary<Type, List<Action<GameAction>>>();
    private static Dictionary<Type, List<Action<GameAction>>> postSubs = new Dictionary<Type, List<Action<GameAction>>>();
    // 事件执行器注册表(每个GameAction子类对应的执行逻辑)
    private static Dictionary<Type, Func<GameAction, IEnumerator>> performers = new Dictionary<Type, Func<GameAction, IEnumerator>>();

    
    /// <summary>
    /// 执行游戏事件(入口方法)
    /// </summary>
    /// <param name="action">继承了GameAction的游戏事件</param>
    /// <param name="OnPerformFinished">完成事件后的回调函数</param>
    public void Perform(GameAction action, Action OnPerformFinished = null)
    {
        if (IsPerforming)
            return;
        IsPerforming = true;
        StartCoroutine(Flow(action, () =>
        {
            IsPerforming = false;
            OnPerformFinished?.Invoke();
        }));
    }

    /// <summary>
    /// 添加当前阶段的游戏事件以备激活
    /// </summary>
    /// <param name="gameAction">继承GameAction的游戏事件</param>
    public void AddReaction(GameAction gameAction)
    {
        reactions?.Add(gameAction);
    }

    /// <summary>
    /// 事件处理主流程(三阶段协程)
    /// </summary>
    /// <param name="action"></param>
    /// <param name="OnFlowFinished"></param>
    /// <returns></returns>
    private IEnumerator Flow(GameAction action, Action OnFlowFinished = null)
    {
        // ===== 阶段1:前置处理 =====
        reactions = action.PreReactions;
        PerformSubscribers(action, preSubs);
        yield return PerformReactions();
    
        // ===== 阶段2:主执行 =====
        // 执行核心逻辑前重置反应列表
        reactions = action.PerformReactions; // 使用专门的PerformReactions列表
        yield return PerformPerformer(action);
        yield return PerformReactions();
    
        // ===== 阶段3:后置处理 =====
        reactions = action.PostReactions; // 使用独立的PostReactions列表
        PerformSubscribers(action, postSubs);
        yield return PerformReactions();
    
        OnFlowFinished?.Invoke();
    }

    /// <summary>
    /// 执行事件对应的核心逻辑
    /// </summary>
    /// <param name="action"></param>
    /// <returns></returns>
    private IEnumerator PerformPerformer(GameAction action)
    {
        Type type = action.GetType();
        if (performers.ContainsKey(type))
        {
            yield return performers[type](action); // 执行注册的协程逻辑
        }
    }

    /// <summary>
    /// 触发订阅者回调(Pre/POST阶段)
    /// </summary>
    /// <param name="action">事件</param>
    /// <param name="subs">事件链表</param>
    private void PerformSubscribers(GameAction action, Dictionary<Type, List<Action<GameAction>>> subs)
    {
        Type type = action.GetType();
        if (subs.ContainsKey(type))
        {
            foreach (var sub in subs[type])
            {
                sub(action);// 触发所有订阅者
            }
        }
    }
    
    /// <summary>
    /// 执行当前阶段的所有反应事件(递归处理)
    /// </summary>
    /// <returns></returns>
    private IEnumerator PerformReactions()
    {
        foreach (var reaction in reactions)
        {
            yield return Flow(reaction);// 递归执行子事件
        }
    }

    /// <summary>
    /// 注册事件执行器(核心逻辑实现)
    /// </summary>
    /// <typeparam name="T">GameAction子类型</typeparam>
    /// <param name="performer">协程执行函数</param>
    public static void AttachPerformer<T>(Func<T, IEnumerator> performer) where T : GameAction
    {
        Type type = typeof(T);
        // 包装泛型参数适配字典存储
        IEnumerator wrappedPerformer(GameAction action) => performer((T)action);
        if (performers.ContainsKey(type))
            performers[type] = wrappedPerformer;
        else
            performers.Add(type, wrappedPerformer);// 注册或覆盖
    }

    /// <summary>
    /// 注册对应的移除
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public static void DetachPerformer<T>() where T : GameAction
    {
        Type type = typeof(T);
        if (performers.ContainsKey(type))
            performers.Remove(type);
    }

    /// <summary>
    /// 订阅事件响应(Pre/POST阶段)
    /// </summary>
    /// <param name="timing">订阅阶段(前置/后置)</param>
    public static void SubscribeReaction<T>(Action<T> reaction, ReactionTiming timing) where T : GameAction
    {
        Dictionary<Type, List<Action<GameAction>>> subs = timing == ReactionTiming.PRE ? preSubs : postSubs;
        // 创建类型安全的包装回调
        void wrappedReaction(GameAction action) => reaction((T)action);
        if (subs.ContainsKey(typeof(T)))
        {
            subs[typeof(T)].Add(wrappedReaction);
        }
        else
        {
            subs.Add(typeof(T), new List<Action<GameAction>>());
            subs[typeof(T)].Add(wrappedReaction);// 添加订阅
        }
    }

    /// <summary>
    /// 订阅对应的移除
    /// </summary>
    /// <param name="reaction"></param>
    /// <param name="timing"></param>
    /// <typeparam name="T"></typeparam>
    public static void UnsubscribeReaction<T>(Action<T> reaction, ReactionTiming timing) where T : GameAction
    {
        Dictionary<Type, List<Action<GameAction>>> subs = timing == ReactionTiming.PRE ? preSubs : postSubs;
        if (subs.ContainsKey(typeof(T)))
        {
            void wrappedReaction(GameAction action) => reaction((T)action);
            subs[typeof(T)].Remove(wrappedReaction);
        }
    }
    
}
using System.Collections.Generic;
using UnityEngine;

/// <summary>
/// 注册游戏事件
/// </summary>
public abstract class GameAction 
{
    public List<GameAction> PreReactions {get; private set;} = new List<GameAction>();
    public List<GameAction> PerformReactions {get; private set;} = new List<GameAction>();
    public List<GameAction> PostReactions {get; private set;} = new List<GameAction>();
}
public enum ReactionTiming 
{
    PRE,
    POST
}

使用方法

推荐大家去看他的视频学习,我也讲不清楚

  1. 事件驱动架构:基于 GameAction 的事件系统,所有游戏操作(抽卡、伤害等)都封装为事件

  2. 三阶段执行流

    • 前置阶段(PreReactions)

    • 主执行阶段(Perform)

    • 后置阶段(PostReactions)

  3. 订阅者模式:通过 SubscribeReaction 实现解耦的事件响应

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值