(个人思考)游戏技能的实现

游戏技能实现的三种方式:

1.类似UE中GAS的方式,统一为Ability,并且不处理任何数据逻辑。

https://github.com/No78Vino/gameplay-ability-system-for-unity

2.类似双影其境那种, 简单直观,每个Ability都是独立处理响应、行为。

3.一个SkillController方式。 SkillController驱动所有Skill的更新,Skill+Buff系统去处理战斗内每个Entity的行为。

其实类似第1中方式。不过没有这么明确的限定“属性”一定要在GAS中的GameEffect中进行处理

 

主要目标:本文讨论第3种的实现方式的实现思路。本文并没有讨论“属性”的实现,没有讨论editor实现。

 

第一步:有哪些内容需要实现?

1.触发器

一个triggerCondition可以触发 triggerActionList

一个Skill可以有多个triggerConditionList

 

2.每个skill的状态和具体逻辑,和触发后的逻辑;

skill的Active状态,skill在Active状态下内部逻辑

 

3.每个skill之间的关系。

比如当active skillA的时候 会禁用skillB。

比如有active skillA的时候,不能active skillB

 

4.多个skill绑定ownerEntity

 

第二步:怎么实现

so : ScriptableObject的缩写

我们定义了一个SkillContainer的So,里面包含了所有信息。

 public class SkillContainer
    {
        Trigger trigger;
        ISkill skill;
        TagAggregator TagAggregator;
    }

 

 

1. 一个triggerCondition只是condition,并不关心触发后的triggerActionList是什么。我们使用组合的方式

1.1 triggerCondition是一个so

1.2 triggerActionList的element是so (eventData)。

像一些CommonAction由指定CommonActionSystem去监听执行,比如常见的消耗、发射单发子弹行为。

像一些特殊的Action由当前skill.cs去执行。比如 每隔1s生成一颗环绕的旋转球

 

    class Trigger
    {
        TriggerCondition condition;
        TriggerActionList actionList;
    }

 

 

 

在实现skill流程后,通过配置去映射流程的实现, 并且,配置去“配”一些通用的功能。 

 

2.skill的话需要定义

2.1

interface ISkill
{
bool Active { get; set; }
bool TryActivate();
void Deactivate();
void Tick();
}

2.2 trigger的action直接监听1.2中的 triggerActionEventData

2.3  针对快节奏的项目,而非大世界的项目。我觉得直接把所有skill看作permanentSkill就行了,如果不需要了,直接Deactive。

如果是战斗内new的skill,也没有问题。

最多在Deactive的时候,把可能的“大数据”给clear或者returnPool。

这样比较简单直接

 

3.skill之间的关系

当整体skill流程完成后,通过skill内的tag数据去做“流程内”的细节处理。

比如在TryActive的函数内,需要检测这个skill和owner active skillList之间的关系。

 

4.我们使用entity+component的方式,而不是面向对象的方式实现。那么我们定义system和component:

class SkillListComponent: Component
{
  List
<SkillContainer>
}

同时, SkillSystem去Update这个SkillListComponent

    class SkillControllerSystem
    {

        Tick()
        {
            foreach (var entity in queryEntity)
            {
                var skillContainerList= entity.getComponent<SkillListComponent>().SkillList;
                foreach (var skillContainer in skillContainerList)
                {
                    if (skillContainer.skill.Active)
                    {
                        if (CheckTriggerCondition)
                        {
                            TriggerAction()
                        }
                        skillContainer.skill.Tick()
                    }
                }
            }
          
        }
    }

 

posted @ 2025-10-19 19:39  sun_dust_shadow  阅读(10)  评论(0)    收藏  举报