2301_77516548 2023-07-10 15:32 采纳率: 75%
浏览 66
已结题

Unity回合制游戏中,如何实现单项技能效果中混合着事件效果,并且该事件效果不止一种。

游戏战斗逻辑:
AB阵容各5名英雄,根据出手顺序依次进行攻击或释放技能。部分技能在战斗开始时释放,部分技能在满足某种事件时释放。

我的技能设计思路是:
1、创建技能数据类:定义技能的完整数据。
2、创建技能释放类:用于配置技能和释放技能。
3、创建技能效果算法类:用于实现每一种技能效果的算法。(例如增减hp,atk,各种控制效果等…)
4、创建技能作用目标算法类:实现对每一种技能效果的作用目标的匹配。(攻击单个,多个,随机目标,或者特定目标)

由于每一个技能都包含数种效果:有的一种,有的两种,有的3种…数量不限。

我通过在技能配表里,将每一个技能的多种技能效果拆解出来,分别根据其释放时机,作用目标,作用效果,持续回合等一一对应。

例如一个技能有4种效果,通过拆解后可以得到4种技能效果的数据。包含作用目标,作用效果,持续回合等…

在技能释放脚本里,先讲单个技能拆解为多种技能效果,通过for循环依次执行这4种效果,成功实现对绝大多数技能的释放。

但是,这种实现思路无法做到对事件技能的配表数据标记读取,进行动态注册和释放。

例如技能1:攻击力增加30%,防御力增加30%,对流血目标额外造成50%伤害,且每有一个友军阵亡,增加自身20%攻击,10%暴击率,20%爆伤,直到战斗结束。

这个技能包含6种效果,2个事件。

如果按照我之前的设计思路,只能在技能配表里拆解得到6种技能效果,并不能让程序知道还有两个事件,且这两个事件分别对应哪几种技能效果。

前2种技能效果:攻击力增加30%,防御力增加30%,这两项为普通的技能效果,按之前的思路可以实现。

第3种技能效果:对流血目标额外造成50%伤害。这个需要给自身注册一个在造成伤害时判断被攻击目标是否流血增伤的事件,该事件调用的是第三项技能效果。

第4,5,6项技能效果:需要给自身注册一个监控全体敌人是否阵亡的事件,并施加第4,5,6种效果。

问题1:我如何让程序知道1个完整的技能里的多种技能效果,包含哪些事件技,并且每种事件技分别对应哪些效果。是改变技能配表结构吗?修改我之前的设计思路吗?有什么更好的实现思路?

问题2:该如何实现这种单个技能的多种效果里糅合着不同的事件技且还对应不同的效果?

  • 写回答

6条回答 默认 最新

  • haowanba588 2023-07-10 17:06
    关注

    对于问题1,可以将技能配表的数据结构进行调整,引入事件数据结构,将技能效果与事件一一对应。例如,定义技能效果的数据结构如下:

    class SkillEffect {
        int target; // 攻击目标类型
        int effect; // 效果类型
        int turns; // 持续回合数
        float amount; // 数值
        int event; // 事件类型
    }
    

    其中,event是事件类型,可以为0表示无事件,其他数字表示特定的事件类型。定义事件数据结构如下:

    class SkillEvent {
        int effectIndex; // 触发事件对应的技能效果索引
        int event; // 事件类型
    }
    

    在技能配表数据中,可以将技能效果和事件数据分别存储在不同的数据结构中,例如:

    class SkillData {
        int id; // 技能ID
        List<SkillEffect> effects; // 技能效果
        List<SkillEvent> events; // 事件格数据
    }
    

    这样可以让程序知道一个完整的技能里的多种技能效果,包含哪些事件技,并且每种事件技分别对应哪些效果。

    对于问题2,可以在释放技能的逻辑中,遍历每个技能效果,判断是否有事件技。如果有事件技,则将事件注册到相应的事件处理器中,事件处理器负责监控触发相应的事件,并执行对应的效果。可以使用观察者模式实现事件处理器。在技能释放脚本中,将所有技能效果注册到对应的事件处理器中,事件处理器负责监听比如"敌人流血增伤"、"阵亡增益"等事件,一旦事件触发,处理器便会通知对应的技能效果进行操作。

    例如,对于技能1中的第3和第4、5、6个效果,可以分别定义事件为"敌人流血"和"友军阵亡",将其注册到事件处理器中,事件处理器监听相应的事件并通知对应效果生效。

    class SkillEventProcessor {
        map<int, list<int>> effectEventMap; // 技能效果与事件的映射表
        map<int, SkillEventCallback> eventCallbackMap; // 每个事件类型对应的回调处理函数
    
        void registerEffectWithEvent(int effectIndex, int event) {
            if (effectEventMap.find(event) == effectEventMap.end()) {
                effectEventMap[event] = list<int>();
            }
            effectEventMap[event].push_back(effectIndex);
        }
    
        void registerCallbackForEvent(int event, SkillEventCallback callback) {
            eventCallbackMap[event] = callback;
        }
    
        void processEvent(int event, SkillEventData eventData) {
            if (eventCallbackMap.find(event) != eventCallbackMap.end()) {
                for (auto effectIndex : effectEventMap[event]) {
                    auto& effect = effects[effectIndex];
                    if (effect.event == event) {
                        eventCallbackMap[event](effect, eventData);
                    }
                }
            }
        }
    }
    

    在技能释放脚本中,注册事件处理器,以及每个事件所对应的回调函数:

    class MySkillScript {
        SkillEventProcessor eventProcessor; // 注册事件处理器
    
        // 注册事件和回调函数
        void registerEventsAndCallbacks(SkillData skill) {
            for (auto event : skill.events) {
                eventProcessor.registerEffectWithEvent(event.effectIndex, event.event);
                switch (event.event) {
                    case EVENT_ENEMY_BLEED:
                        eventProcessor.registerCallbackForEvent(EVENT_ENEMY_BLEED, [=](SkillEffect& effect, SkillEventData& data) {
                            if (data.target.isBleeding()) {
                                applyEffect(effect, data); // 对目标施加效果
                            }
                        });
                        break;
                    case EVENT_ALLY_DIED:
                        eventProcessor.registerCallbackForEvent(EVENT_ALLY_DIED, [=](SkillEffect& effect, SkillEventData& data) {
                            if (data.allyDied()) {
                                applyEffect(effect, data); // 对自身施加效果
                            }
                        });
                        break;
                    // 处理其他事件...
                }
            }
        }
    
        void castSkill(SkillData skill, list<Target> targets) {
            registerEventsAndCallbacks(skill);
    
            // 遍历技能效果
            for (auto effect : skill.effects) {
                if (effect.event == 0) {
                    applyEffect(effect, targets); // 直接对目标施加效果
                }
            }
        }
    
        void applyEffect(SkillEffect effect, list<Target> targets) {
            // 根据效果的目标类型,从传入的目标列表中选择目标
            auto targets = chooseTargets(effect.target, targets);
    
            // 根据效果类型和数值,对目标施加效果
            for (auto target : targets) {
                switch (effect.effect) {
                    case EFFECT_INCREASE_ATTACK:
                        target.increaseAttack(effect.amount, effect.turns);
                        break;
                    case EFFECT_INCREASE_DEFENSE:
                        target.increaseDefense(effect.amount, effect.turns);
                        break;
                    case EFFECT_EXTRA_DAMAGE_TO_BLEEDING:
                        // 对流血目标施加额外伤害效果
                        auto eventData = SkillEventData(target);
                        eventProcessor.processEvent(EVENT_ENEMY_BLEED, eventData);
                        break;
                    // 处理其他效果...
                }
            }
        }
    }
    

    通过这种设计思路,可以实现单个技能的多种效果里糅合着不同的事件技且还对应不同的效果。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(5条)

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 7月24日
  • 已采纳回答 7月17日
  • 创建了问题 7月10日