事件中心模块

假设怪物死亡后,需要做三件事:player得到奖励,更新任务记录,其他包括成就系统、刷新怪物等待,有前后联系,最简单的方法就是找到脚本挂在的对象,然后得到脚本,最后调用脚本中的函数,但这样会让程序的耦合性太强,因此换一个做法,当怪物死亡的时候不和其他方法直接进行关联,而是通知事件中心派发一个事件,将该事件关联的行为(即监听 )进行调用。

public class EventMgr : BaseManager<EventMgr > {
    // key —— 事件的名字
    // value —— 监听的事件对应的委托函数们
    // 通过UnityAction<object>可以用一个类型传任何参数(数组也可以用object表示)
    private Dictionary<string, UnityAction<object>> eventDic = new Dictionary<string, UnityAction<object>>();
    
    // <param name="name"> 事件的名字</param>
    // <param name="action"> 处理事件的委托函数</param>
    public void AddEventListener(string name, UnityAction<object> action) {
        if (eventDic.ContainsKey(name)) {
            eventDic[name] += action;
        } else {
            eventDic.Add(name, action);
        }
    }

    // <param name="name"> 触发的事件</param>
    public void EventTrigger(string name, object params) {
        if (eventDic.ContainsKey(name)) {
            eventDic[name].Invoke(params);
        }
    }

    // 移除委托函数
    public void RemoveEventListener(string name, UnityAction<object> action) {
        if (eventDic.ContansKey(name)) {
            eventDic[name] -= action;
        }
    }

    public void ClearAllListener() {
        // eventDic[name] = null;
        eventDic.Clear();
    }
}
public class Monster : MonoBehaviour {
    public string name = "monster";

    void Start() {
        Dead();
    }

    void Dead() {
        Debug.Log("怪物死亡");

        // 其他对象想在怪物死亡后的行为,比如
        // 1、玩家得到奖励
        // 2、更新任务记录
        // 3、其他(比如成就系统,副本继续刷怪等)
        // TODO.....

        // 分发事件
        EventMgr .GetInstance().EventTrigger("MonsterDead", this);  
    }
}
// -----------------------------------------------
public class Player : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", MonsterDeadDo);
    }

    public void MonsterDeadDo(object info) {
        Debug.Log("玩家得到奖励");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", MonsterDeadDo);
    }
}
// -----------------------------------------------
public class Task : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", TaskWaitMonsterDeadDo);
    }

    public void TaskWaitMonsterDeadDo(object info) {
        Debug.Log("任务记录");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", TaskWaitMonsterDeadDo);
    }
}
// -----------------------------------------------
public class Other : MonoBehaviour {
    void Start() {
        EventMgr .GetInstance().AddEventListerner("MonsterDead", OtherWaitMonsterDeadDo);
    }

    public void OtherWaitMonsterDeadDo(object info) {
        Debug.Log("其他要做的事");
    }

    void OnDestroy() {
        EventMgr .GetInstance().RemoveEventListener("MonsterDead", OtherWaitMonsterDeadDo);
    }
}

如果要优化一下装箱拆箱的问题,可以通过里氏替换以及泛型原则进行一个骚操作,如果不需要参数,通过重载

public interface IEventInfo {

}

public class EventInfo<T> : IEventInfo {
    public UnityAction<T> actions;

    public EventInfo( UnityAction<T> action) {
        actions += action;
    }
}

public class EventInfo : IEventInfo {
    public UnityAction actions;

    public EventInfo( UnityAction action) {
        actions += action;
    }
}


public class EventMgr : BaseManager<EventMgr > {
    // key —— 事件的名字
    // value —— 监听的事件对应的委托函数们
    // 通过UnityAction<object>可以用一个类型传任何参数(数组也可以用object表示)
    private Dictionary<string, IEventInfo > eventDic = new Dictionary<string, IEventInfo >();
    
    // <param name="name"> 事件的名字</param>
    // <param name="action"> 处理事件的委托函数</param>
    public void AddEventListener<T>(string name, UnityAction<T> action) {
        if (eventDic.ContainsKey(name)) {
            (eventDic[name] as EventInfo<T>).actions += action;
        } else {
            eventDic.Add(name, new EventInfo<T>(action));
        }
    }



    public void AddEventListener(string name, UnityAction action) {
        if (eventDic.ContainsKey(name)) {
            (eventDic[name] as EventInfo).actions += action;
        } else {
            eventDic.Add(name, new EventInfo(action));
        }
    }

    // <param name="name"> 触发的事件</param>
    public void EventTrigger<T>(string name, T params) {
        if (eventDic.ContainsKey(name)) {
            if ((eventDic[name] as EventInfo<T>).actions != null) 
                (eventDic[name] as EventInfo<T>).actions.Invoke(params);
        }
    }

    public void EventTrigger(string name) {
        if (eventDic.ContainsKey(name)) {
            if ((eventDic[name] as EventInfo).actions != null) 
                (eventDic[name] as EventInfo).actions.Invoke();
        }
    }

    // 移除委托函数
    public void RemoveEventListener<T>(string name, UnityAction<T> action) {
        if (eventDic.ContansKey(name)) {
            (eventDic[name] as EventInfo<T>).actions -= action;
        }
    }

    public void RemoveEventListener(string name, UnityAction action) {
        if (eventDic.ContansKey(name)) {
            (eventDic[name] as EventInfo).actions -= action;
        }
    }

    public void ClearAllListener() {
        // eventDic[name] = null;
        eventDic.Clear();
    }
}

 

考虑柔性负荷的综合能源系统低碳经济优化调度【考虑碳交易机制】(Matlab代码实现)内容概要:本文围绕“考虑柔性负荷的综合能源系统低碳经济优化调度”展开,重点研究在碳交易机制下如何实现综合能源系统的低碳化与经济性协同优化。通过构建包含风电、光伏、储能、柔性负荷等多种能源形式的系统模型,结合碳交易成本与能源调度成本,提出优化调度策略,以降低碳排放并提升系统运行经济性。文中采用Matlab进行仿真代码实现,验证了所提模型在平衡能源供需、平抑可再生能源波动、引导柔性负荷参与调度等方面的有效性,为低碳能源系统的设计与运行提供了技术支撑。; 适合人群:具备一定电力系统、能源系统背景,熟悉Matlab编程,从事能源优化、低碳调度、综合能源系统等相关领域研究的研究生、科研人员及工程技术人员。; 使用场景及目标:①研究碳交易机制对综合能源系统调度决策的影响;②实现柔性负荷在削峰填谷、促进可再生能源消纳中的作用;③掌握基于Matlab的能源系统建模与优化求解方法;④为实际综合能源项目提供低碳经济调度方案参考。; 阅读建议:建议读者结合Matlab代码深入理解模型构建与求解过程,重点关注目标函数设计、约束条件设置及碳交易成本的量化方式,可进一步扩展至多能互补、需求响应等场景进行二次开发与仿真验证。
修改::#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 事件中心模块 (优化版) """ import logging import threading import uuid import time from enum import Enum from typing import Dict, List, Callable, Optional, Any, Set, Tuple, DefaultDict from collections import defaultdict from dataclasses import dataclass logger = logging.getLogger(__name__) logger.setLevel(logging.INFO) # 解决导入问题的关键修改:确保模块作为独立实体导入 if __name__ == "__main__": print("警告: 此模块应作为库导入,而非直接运行") class EventType(Enum): """事件类型枚举""" MODULE_RUN = "module_run" ANALYSIS_RESULT = "analysis_result" DATA_UPDATE = "data_update" ANALYSIS_COMPLETED = "analysis_completed" CONFIG_SAVED = "config_saved" DATA_SUBMIT = "data_submit" INPUT_ANALYSIS = "input_analysis" COMBINATION_ANALYSIS = "combination_analysis" TREND_ANALYSIS = "trend_analysis" NUMBER_GENERATION = "number_generation" ACK = "ack" ERROR = "error" @dataclass class Event: """事件数据类""" event_id: str type: str source: str target: Optional[str] = None data: Optional[Dict[str, Any]] = None token: Optional[str] = None timestamp: float = time.time() class EventCenter: """线程安全的事件中心单例 (优化实现)""" _instance = None _lock = threading.Lock() def __new__(cls): with cls._lock: if cls._instance is None: cls._instance = super().__new__(cls) # 延迟初始化,避免递归问题 cls._instance.__initialized = False return cls._instance def __init__(self): if getattr(self, '__initialized', False): return self.__initialized = True self._lock = threading.RLock() self._subscribers: DefaultDict[str, List[Tuple[Callable[[Event], None], Optional[str]]]] = defaultdict(list) self._event_history: Dict[str, Event] = {} self._pending_acks: Set[str] = set() self._ack_timeout = 5.0 self._event_counter = 0 # 事件计数器用于监控 logger.info("EventCenter 初始化完成 (模块: %s)", __name__) def subscribe(self, event_type: str, handler: Callable[[Event], None], token: Optional[str] = None) -> None: """订阅事件 (添加类型检查)""" if not isinstance(event_type, str): raise TypeError("event_type 必须是字符串") if not callable(handler): raise ValueError("handler 必须是可调用对象") with self._lock: self._subscribers[event_type].append((handler, token)) logger.debug("已订阅 %s [token=%s]", event_type, token) def publish(self, event: Event, require_ack: bool = False) -> bool: """发布事件 (添加事件计数)""" if not isinstance(event, Event): raise TypeError("需要 Event 实例") with self._lock: if event.event_id in self._event_history: logger.warning("重复事件 %s", event.event_id[:8]) return False self._event_history[event.event_id] = event self._event_counter += 1 if require_ack: self._pending_acks.add(event.event_id) logger.info("发布 %s 事件 %s (总事件数: %d)", event.type, event.event_id[:8], self._event_counter) # 获取匹配的处理器 handlers = [] with self._lock: for handler, token in self._subscribers.get(event.type, []): if token is None or token == event.token: handlers.append(handler) # 异步处理事件 if handlers: threading.Thread( target=self._dispatch_event, args=(event, handlers, require_ack), daemon=True, name=f"EventDispatch-{event.event_id[:6]}" ).start() return True def _dispatch_event(self, event: Event, handlers: List[Callable[[Event], None]], require_ack: bool) -> None: """分发事件 (添加异常隔离)""" for handler in handlers: try: handler(event) logger.debug("事件 %s 由 %s 处理", event.event_id[:8], getattr(handler, '__name__', str(handler))) except Exception as e: logger.exception("处理器失败: %s", str(e)) self._publish_error( source="event_center", target=event.source, error=e, context=f"处理 {event.type} 时出错" ) if require_ack and event.target: self._wait_for_ack(event) def _wait_for_ack(self, event: Event) -> None: """等待ACK (添加超时日志)""" start = time.time() while time.time() - start < self._ack_timeout: with self._lock: if event.event_id not in self._pending_acks: logger.debug("收到 %s 的ACK", event.event_id[:8]) return time.sleep(0.1) logger.warning("事件 %s 等待ACK超时 (目标: %s)", event.event_id[:8], event.target) self._publish_error( source="event_center", target=event.source, error=TimeoutError("ACK超时"), context=f"等待 {event.target} 确认超时" ) def acknowledge(self, event_id: str) -> None: """确认事件处理完成 (添加验证)""" with self._lock: if event_id in self._pending_acks: self._pending_acks.remove(event_id) logger.info("收到 %s 的ACK", event_id[:8]) else: logger.warning("无效的ACK: %s (未找到或已处理)", event_id[:8]) def _publish_error(self, source: str, target: str, error: Exception, context: str = "") -> None: """发布错误事件 (增强错误信息)""" error_event = Event( event_id=str(uuid.uuid4()), type=EventType.ERROR.value, source=source, target=target, data={ "error": str(error), "type": type(error).__name__, "context": context, "timestamp": time.time() } ) self.publish(error_event) logger.error("已发布错误事件: %s", error) def get_stats(self) -> Dict[str, int]: """获取事件中心统计信息""" with self._lock: return { "total_events": self._event_counter, "pending_acks": len(self._pending_acks), "subscriber_types": len(self._subscribers), "active_subscriptions": sum(len(h) for h in self._subscribers.values()) } # 全局单例实例 - 解决导入问题的关键 event_center = EventCenter() # 模块加载完成日志 logger.info("事件中心模块 %s 已成功加载", __name__) def validate(self): if not isinstance(self.event_id, str): raise ValueError("event_id 必须是字符串") if not self.type: raise ValueError("type 不能为空")
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值