精华内容
下载资源
问答
  • unity 技能系统

    2021-06-03 15:16:47
    关于技能系统里面的skillData表,是用来填写数据的,但里面可能包含图片、音频、prefab实体等,怎么用数据表示?这时,就要写一个string和一个gameobject,这个string是用来填写的,比如string写为ballAttack,然后...
    • 关于技能系统里面的skillData表,是用来填写数据的,但里面可能包含图片、音频、prefab实体等,怎么用数据表示?这时,就要写一个string prefabName和一个gameobject skillPrefab,这个string是用来填写的,比如string写为ballAttack,然后在用到这个skillData时,先进行一次初始化,用ballAttack这个名字去Resources.Load这个gameobject下来。这样做,就是将非数据的东西进行数据化,整张skillData表全是数据。
    • 这个Load下来的gameobject就被存到skillPrefab里,后面用于实例化。实例化的意义,就是先有一个母版就是这个skillPrefab,然后复制出一个skillPrefab2来,母版留着。
    • 编程里面的逻辑,一般都是谁调用了谁,谁再调用了谁,然后这样调来调去,最终完成了方法。有可能最初只是A要做某事,但A如果要做某事就必须调用B,而B又要调用C和D,而C又要调用E和F,D又要调用G和H,然后F又要调用I,所以,看起来就很复杂了,但只要定睛去寻找谁调用了谁,把关系全部理清楚,也就简单一些。
    • 关于谁调用谁,再深入一点,其实编程最终传递的是变量,而方法只是用于加工变量或传递变量,但最终我们要的还是变量,方法只是手段。所以,方法是围绕变量构建的,为变量服务的。
    • 通俗一点理解,当看到一个方法时,思考:什么东西进来了,什么东西被加工了,最后得到什么东西(用于传出去的)。
    • 有些理解可以滞后,比如有一个编程,大家都用这种方式做,但我看了不懂为什么这样做,他的好处是什么看不懂,于是想完全弄懂它再用它,结果不用,而不用就无法通过案例理解,就依然无法弄懂,于是就一直不用了。应该反过来,先用再理解,用的过程中,你会对他有个更好的案例理解,然后用着用着就懂了,先不用懂就能先用。

    如何设计一个角色的技能

    • 首先技能被分解成单个的效果,比如伤害、眩晕、减速。
    • 简单点的话,可以拿这些单个效果进行组合,伤害+眩晕就是一个狮吼功技能,伤害+减速就是八卦掌技能。然后,一个人比如杨过,有四个技能,狮吼功、八卦掌。。。
    • 上面这种设计方法,比较粗暴,等于是有什么就凑什么,感觉凑成一个怪物。
    • 还有一种思路,就是从一个角色出发,这个角色有四个技能,我们首先要考虑,这四个技能之间是怎么配合的。更上一层想,就是这个角色应该有一种独特的玩法,有人玩破甲流,有人玩暴击流,有人玩吸血流。在构建一个角色的技能时,需要构建出他能玩的什么流派,再根据这个流派分配四个技能,然后,再根据这四个技能各自分工,再细分每个技能要哪些单个效果,这样倒推出来的技能,才是有机的,才是最终能有一套玩法的技能,而不是互相没关系的技能组。
    展开全文
  • 关于Unity技能系统的设计(https://blog.csdn.net/u010377179/article/details/89236284?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Edefault-6.baidujs&...

    Unity 如何实现一个强大的MMO技能系统:https://blog.csdn.net/yupu56/article/details/107223165?utm_source=app&app_version=4.7.1

    常规MMO技能系统:https://zhuanlan.zhihu.com/p/26077188
    Unity ACT技能编辑器的制作(上):https://zhuanlan.zhihu.com/p/38001896
    方便扩展的被动技能,Buffer系统(和编辑器):https://zhuanlan.zhihu.com/p/38326478
    Unity3D手游开发日记(2) - 技能系统架构设计:https://blog.csdn.net/qq18052887/article/details/50358463

    技能系统拆解
    1. Buff:
    https://bbs.gameres.com/forum.php?mod=viewthread&tid=215027
    2. AOE:
    https://bbs.gameres.com/forum.php?mod=viewthread&tid=225054
    3. Skill:
    https://bbs.gameres.com/forum.php?mod=viewthread&tid=229210

     

    个人自己仿照DOTA2的技能系统结构写了一套技能系统(https://developer.valvesoftware.com/wiki/Dota_2_Workshop_Tools:zh-cn/Scripting:zh-cn/Abilities_Data_Driven:zh-cn

    初版测试通过。博文链接(https://blog.csdn.net/u010377179/article/details/104995070)。

    技能设计的逻辑实现——以RPG游戏为例(https://zhuanlan.zhihu.com/p/56879288

    如何设计一个易扩展的游戏技能系统(https://www.zhihu.com/question/29545727

    如何打造满足多种游戏类型的技能设计模块?从技能触发方式谈起

    Unity 如何实现一个强大的MMO技能系统!

    展开全文
  • Unity技能系统架构

    2021-01-11 21:35:57
    角色技能系统架构分析类的设计技能数据类技能管理类技能释放类类的调用流程封装变化具体代码技能数据类技能管理类选择攻击目标接口扇形选择攻击目标接口实现影响效果接口造成伤害接口实现技能释放器近身技能释放类...

    学习的技能系统。

    架构分析

    先看一下我Demo中的技能,我方释放了一次普通攻击,
    Boss总共释放两个近身技能,一个范围攻击,一个单体攻击
    技能的释放流程是,当按下了技能按钮或满足了条件,实例化出技能预制体,受伤方受伤
    在这里插入图片描述
    一个角色肯定要有多个技能。先来分析一下技能的共同点。

    1.技能的数据,如攻击距离,攻击角度,角色动画,使用的特效以及对自身、对敌人的影响等数据,所以将技能涉及的数据封装到一个技能数据类中。

    2.每个角色拥有多个技能,所有要有一个统一的类来进行技能数据的读取,以及配置技能以及准备技能。

    3.每一个技能释放后都有不同的效果,如攻击方式的不同,特殊的效果不同,所有将技能释放后的算法统一交给一个释放类来实现。

    类的设计

    技能的释放方挂载技能管理类。
    技能预制体挂载技能释放类。

    技能数据类

    储存所有技能的数据,方便统一管理。

    技能管理类

    通过配置或者读取Json获得并储存当前角色所拥有的所有技能数据,来准备,生成,并且开启技能的冷却,技能释放后续算法需要根据技能的数据来进行计算伤害以及其他效果,所有技能管理类需要将技能数据传给释放类,并且调用释放类中对外提供的执行算法的方法。

    技能释放类

    根据技能数据执行各种算法。

    类的调用流程

    大体来说就是技能管理器配置当前角色技能—>准备技能(查找冷却时间为0,)—>生成技能预制体—>查找生成预制体的身上的技能释放类将技能数据传递给技能释放类,并且调用技能释放类中的方法—>技能释放类根据技能数据选择攻击目标,执行各种算法。

    封装变化

    角色释放技能逻辑有很多,有的是在释放技能的圆形内寻找敌人,有的是在释放技能的一个特殊形状范围内寻找敌人,可能以后还会有特殊的选择敌人的方式。

    所有技能在释放完都要有很多逻辑,例如造成伤害,消耗法力值,这个每一个技能都不一样。

    技能释放有直接在自身就生成技能特效的就像上面图片那样,还有可能是下图这样在敌方直接生成的技能。还会有可能像火球那样移动到目标再造成伤害的。
    在这里插入图片描述

    具体代码

    技能数据类

    这个根据具体项目不同配置不同

     public class SkillData
        {
            ///<summary>技能ID</summary>
            public int skillID;
            ///<summary>技能名称</summary>
            public string name;
            ///<summary>技能描述</summary>
            public string description;
            ///<summary>冷却时间</summary>
            public int coolTime;
            ///<summary>冷却剩余</summary>
            public int coolRemain;
            ///<summary>魔法消耗</summary>
            public int costSP;
            ///<summary>攻击距离</summary>
            public float attackDistance;
            /// <summary> 移动速度</summary>
            public float moveSpeed;
            ///<summary>攻击角度</summary> 
            public float attackAngle;
            ///<summary>攻击目标tags</summary> 
            public string[] attackTargetTags = { "Enemy" };
            ///<summary>攻击目标对象数组</summary>
            [HideInInspector]
            public Transform[] attackTargets;
            ///<summary>技能影响类型</summary> 
            public string[] impactType = { "CostSP", "Damage" };
            ///<summary>连击的下一个技能编号</summary>
            public int nextBatterId;
            ///<summary>伤害比率</summary>
            public float atkRatio;
            ///<summary>持续时间</summary>
            public float durationTime;
            ///<summary>伤害间隔</summary>
            public float atkInterval;
            ///<summary>技能生成位置名称</summary>
            public string spawnPosName;
            [HideInInspector]
            ///<summary>技能生成位置</summary>
            public Transform spawnPos;
            ///<summary>技能所属</summary>
            [HideInInspector]
            public GameObject owner;
            ///<summary>技能预制件名称</summary>
            public string prefabName;
            ///<summary>预制件对象</summary>
            [HideInInspector]
            public GameObject skillPrefab;
            ///<summary>动画名称</summary> 
            public string animationName;
            ///<summary>受击特效名称</summary>
            public string hitFxName;
            ///<summary>受击特效预制件</summary>
            [HideInInspector]
            public GameObject hitFxPrefab;
            ///<summary>技能等级</summary>
            public int level;
            ///<summary>攻击类型 单攻,群攻</summary> 
            public SkillAttackType attackType;
            /<summary>选择类型 扇形(圆形),矩形</summary>  
            public SelectorType selectorType;
        }
    

    技能管理类

    public class SkillManager : MonoBehaviour 
    	{
            public SkillData[] skills;
            private void Start()
            {
                for (int i = 0; i < skills.Length; i++)
                {
                    InitSkills(skills[i]);
                }
            }
            /// <summary>
            /// 准备技能
            /// </summary>
            /// <param name="id">技能id</param>
            /// <returns></returns>
            public SkillData PrepareSkill(int id)
            {
                SkillData data = null;
                for (int i = 0; i < skills.Length; i++)
                {
                    if (skills[i].skillID ==id)
                    {
                        data = skills[i];
                    }
                }
                //如果当前技能剩余冷却时间小于0 则可以释放
                if (data.coolRemain <= 0) return data;
                else return null;
            }
            /// <summary>
            /// 生成技能
            /// </summary>
            /// <param name="data">技能数据</param>
            /// <param name="spawnPos">生成位置 默认自身位置</param>
            public void GererateSkill(SkillData data)
            {
                if (data == null) return;
                GameObject skillGo = GameObjectPool.Instance.CreateObject(data.prefabName,data.skillPrefab, data.spawnPos.position, data.spawnPos.rotation);
                SkillDeployer deployer = skillGo.GetComponent<SkillDeployer>();
                //将释放器所需要技能数据赋值
                deployer.SkillData = data;
                //释放具体技能效果
                deployer.DeploySkill();
                //开启技能冷却
                StartCoroutine("CoolTimeDown", data);
            }
            /// <summary>
            /// 初始化技能
            /// </summary>
            /// <param name="skill"></param>
            void InitSkills(SkillData data)
            {
                data.skillPrefab = ResourceManager.Load<GameObject>(data.prefabName);
                if (string.IsNullOrEmpty(data.spawnPosName))
                {
                    data.spawnPos = transform;
                }
                else
                {
                    data.spawnPos = transform.FindChildByName(data.spawnPosName);
                }
                data.owner = gameObject;
            }
            /// <summary>
            /// 技能冷却
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            IEnumerator CoolTimeDown(SkillData data)
            {
                //将剩余冷却时间设置为技能的冷却时间
                data.coolRemain = data.coolTime;
                //技能剩余冷却每秒减少1
                while (data.coolRemain>0)
                {
                    yield return new WaitForSeconds(1);
                    data.coolRemain--;
                }
            }
        }
    

    选择攻击目标接口

    public interface IAttackSelector  
    	{
            /// <summary>
            /// 计算攻击目标
            /// </summary>
            Transform[] CalculateTarget(SkillData data,Transform skillTf);
        }
    

    扇形选择攻击目标接口实现

    public class SectorAttackSelector : IAttackSelector
        {
            public Transform[] CalculateTarget(SkillData data, Transform skillTf)
            {
                List<Transform> targets = new List<Transform>();
                //通过技能标签找到所有目标
                for (int i = 0; i < data.attackTargetTags.Length; i++)
                {
                    GameObject[] tempGo = GameObject.FindGameObjectsWithTag(data.attackTargetTags[i]);
                    //Debug.Log(tempGo[i].name);
                    targets.AddRange(tempGo.Select(g=>g.transform));
                    
                }
                //通过向量判断找出集合中角度与距离在攻击范围内的
                targets = targets.FindAll(t =>
                //技能预制体距离目标距离小于技能攻击距离
                Vector3.Distance(skillTf.position, t.position) <= data.attackDistance &&
                
                //技能预制体正前方与目标之间的夹角小于攻击角度的一半
                Vector3.Angle(skillTf.forward, t.position - skillTf.position) <= data.attackAngle / 2
                );
                //寻找到生命值大于0的目标
                targets = targets.FindAll(t=>t.GetComponent<ICharacter>().HP>0);
                //将集合转化成数组
                Transform[] result = targets.ToArray();
                //判断单攻还是群攻 如果是群攻则直接返回当前数组
                if (data.attackType == SkillAttackType.Group||result.Length==0)
                {
                    return result;
                }
               
                //如果是单攻则返回距离最近的
                Transform min = result.GetMin(m=>Vector3.Distance(m.position,skillTf.position));
                return new Transform[] {min};
            }
        }
    

    影响效果接口

    public interface IImpactEffect 
    	{
            /// <summary>
            /// 触发影响效果
            /// </summary>
            void TriggerImpact(SkillDeployer skillDeployer);
        }
    

    造成伤害接口实现

    public class DamageImpactEffect : IImpactEffect
        {
            public void TriggerImpact(SkillDeployer skillDeployer)
            {
                skillDeployer.StartCoroutine(RepeatDamage(skillDeployer));
            }
            /// <summary>
            /// 重复伤害
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            IEnumerator RepeatDamage(SkillDeployer data)
            {
                float timer = 0;
                do
                {
                    OnceDamage(data.SkillData);
                    //每次执行完伤害后等待技能间隔
                    yield return new WaitForSeconds(data.SkillData.atkInterval);
                    timer += data.SkillData.atkInterval;
                    //一直持续到当前技能持续时间结束
                } while (timer<data.SkillData.durationTime);
            }
            /// <summary>
            /// 单次伤害
            /// </summary>
            /// <param name="data"></param>
            private void OnceDamage(SkillData data)
            {
                //基础攻击力乘以当前技能攻击比率最终攻击力
                float atk = data.atkRatio * data.owner.GetComponent<ICharacter>().baseAtk;
                //遍历攻击目标,造成伤害
                for (int i = 0; i < data.attackTargets.Length; i++)
                {
                    ICharacter character = data.attackTargets[i].GetComponent<ICharacter>();
                    character.Damage(atk);
                }
            }
        }
    

    技能释放器

    public abstract class SkillDeployer : MonoBehaviour 
    	{
            private SkillData skillData;
            public SkillData SkillData
            {
                get
                {
                    return skillData;
                }
                set
                {
                    skillData = value;
                    InitDeployer();
                }
            }
            /// <summary>
            /// 攻击目标接口对象
            /// </summary>
            private IAttackSelector attackSelector;
            /// <summary>
            /// 影响效果接口对象
            /// </summary>
            private IImpactEffect[] impactEffects;
            /// <summary>
            /// 初始化释放器(创建对象)
            /// </summary>
            private void InitDeployer()
            {
                //工厂模式创建对象
                attackSelector = DeployerConfigFactory.CreatAttackSelector(skillData);
                impactEffects = DeployerConfigFactory.CreatImpactEffect(skillData);
            }
            /// <summary>
            /// 计算攻击目标
            /// </summary>
            protected void CalculateTarget()
            {
                skillData.attackTargets = attackSelector.CalculateTarget(skillData,transform);
            }
            /// <summary>
            /// 造成影响效果
            /// </summary>
            protected void ImpactEffect()
            {
                for (int i = 0; i < impactEffects.Length; i++)
                {
                    impactEffects[i].TriggerImpact(this);
                }
            }
            /// <summary>
            /// 具体释放技能,子类具体实现
            /// </summary>
            public abstract void DeploySkill();
        }
    

    近身技能释放类

    近身技能在技能释放出来就可以计算伤害了所以很简单

    public class MeleeSkillDeployer : SkillDeployer
        {
            public override void DeploySkill()
            {
                CalculateTarget();
                ImpactEffect();
            }
        }
    

    技能释放类配置工厂类

    public class DeployerConfigFactory  
    	{
            /// <summary>
            /// 缓存池
            /// </summary>
            private static Dictionary<string,object> cache;
            static DeployerConfigFactory()
            {
                cache = new Dictionary<string, object>();
            }
            /// <summary>
            /// 创建选择敌人接口对象
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public static IAttackSelector CreatAttackSelector(SkillData data)
            {
                //反射创建对象自定义类名规则 TowerDemo.Skill.枚举名AttackSelector
                string className = string.Format("TowerDemo.Skill.{0}AttackSelector",data.selectorType);
                return CreatObject<IAttackSelector>(className);
            }
            /// <summary>
            /// 创建影响效果接口对象
            /// </summary>
            /// <param name="data"></param>
            /// <returns></returns>
            public static IImpactEffect[] CreatImpactEffect(SkillData data)
            {
                //初始化数组长度
                IImpactEffect[] impactEffects = new IImpactEffect[data.impactType.Length];
                //遍历技能影响效果字符串长度,赋值给影响效果接口对象数组
                for (int i = 0; i < data.impactType.Length; i++)
                {
                    //反射创建对象自定义类名规则 TowerDemo.Skill.枚举名ImpactEffect
                    string className = string.Format("TowerDemo.Skill.{0}ImpactEffect", data.impactType[i]);
                    impactEffects[i] = CreatObject<IImpactEffect>(className);
                }
                return impactEffects;
            }
            /// <summary>
            /// 通过反射创建对象
            /// </summary>
            /// <typeparam name="T">创建对象的类型</typeparam>
            /// <param name="className">类名</param>
            /// <returns></returns>
            private static T CreatObject<T>(string className) where T:class
            {
                //如果缓存池没有当前对象创建,如果有则直接返回
                if (!cache.ContainsKey(className))
                {
                    Type type = Type.GetType(className);
                    object instance = Activator.CreateInstance(type);
                    cache.Add(className,instance);
                }
                return cache[className] as T;
            }
    	}
    
    展开全文
  • unity 技能系统设计

    千次阅读 2016-01-25 16:31:02
    在网上看到这篇帖子,感觉他的技能设计思路很棒,转载下来,给自己的项目多一点借鉴的...Unity教程之-Unity游戏技能Skill系统架构设计   我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活

    在网上看到这篇帖子,感觉他的技能设计思路很棒,转载下来,给自己的项目多一点借鉴的地方

    将核心代码封装,留出灵活的上层逻辑拓展接口

    原文地址 : http://www.unity.5helpyou.com/3662.html



    Unity教程之-Unity游戏技能Skill系统架构设计

     

    我想把技能做的比较牛逼,所以项目一开始我就在思考,是否需要一个灵活自由的技能系统架构设计,传统的技能设计,做法都是填excel表,技能需要什么,都填表里,很死板,比如有的技能只需要1个特效,有的要10个,那么表格也得预留10个特效的字段.在代码里面也是写死一些东西,要增加和修改,就得改核心代码,如果我要把核心部分做成库封装起来,就很麻烦了.

    能不能做成数据驱动的方式呢?

    改技能文件就行了,即使要增加功能,也只需要扩展外部代码,而不用改核心代码,

    我是这么来抽象一个技能的,技能由一堆触发器组成,比如特效触发器,动作触发器,声音触发器,摄像机震动触发器等等,这些触发器到了某个条件就执行触发,触发条件一般是时间,如果有比较复杂的浮空技能,可以增加落地触发等.

    自定义一个技能文件,代替excel表格,看起来是这样:

    简单的技能:

    每一行都是一个触发器,这些触发器,到了某个条件会自动触发.

    上面的意思就是,第0秒开始面向目标,第0秒开始播放动作1000

    复杂的技能:

    这个技能能将目标打到空中,并完成3连击,然后从空中砸向地面,

    CurveMove(0, 0.413, 104, 0, 0, 0, 0);的意思就是,第0.413秒,开始做曲线运动,让角色飞到空中,曲线运动的ID是104,

    用这样的文件来配置一个技能,很灵活,也很快,

    ?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    private bool ParseScript(string filename)
    {
    bool ret = false;
    try
    {
    StreamReader sr = FileReaderProxy.ReadFile(filename);
    if (sr != null)
    ret = LoadScriptFromStream(sr);
    }
    catch (Exception e)
    {
    string err = "Exception:" + e.Message + "\n" + e.StackTrace + "\n";
    LogSystem.ErrorLog(err);
    }
     
    return ret;
    }
     
    private bool LoadScriptFromStream(StreamReader sr)
    {
    bool bracket = false;
    SkillInstance skill = null;
    do
    {
    string line = sr.ReadLine();
    if (line == null)
    break;
     
    line = line.Trim();
     
    if (line.StartsWith("//") || line == "")
    continue;
     
    if (line.StartsWith("skill"))
    {
    int start = line.IndexOf("(");
    int end = line.IndexOf(")");
    if (start == -1 || end == -1)
    LogSystem.ErrorLog("ParseScript Error, start == -1 || end == -1  {0}", line);
     
    int length = end - start - 1;
    if (length <= 0)
    {
    LogSystem.ErrorLog("ParseScript Error, length <= 1, {0}", line);
    return false;
    }
     
    string args = line.Substring(start + 1, length);
    int skillId = (int)Convert.ChangeType(args, typeof(int));
    skill = new SkillInstance();
    AddSkillInstanceToPool(skillId, skill, true);
    }
    else if (line.StartsWith("{"))
    {
    bracket = true;
    }
    else if (line.StartsWith("}"))
    {
    bracket = false;
     
    // 按时间排序
    skill.m_SkillTrigers.Sort((left, right) =>
    {
    if (left.GetStartTime() > right.GetStartTime())
    {
    return -1;
    }
    else if (left.GetStartTime() == right.GetStartTime())
    {
    return 0;
    }
    else
    {
    return 1;
    }
    });
    }
    else
    {
    // 解析trigger
    if (skill != null && bracket == true)
    {
    int start = line.IndexOf("(");
    int end = line.IndexOf(")");
    if (start == -1 || end == -1)
    LogSystem.ErrorLog("ParseScript Error, {0}", line);
     
    int length = end - start - 1;
    if (length <= 0)
    {
    LogSystem.ErrorLog("ParseScript Error, length <= 1, {0}", line);
    return false;
    }
     
    string type = line.Substring(0, start);
    string args = line.Substring(start + 1, length);
    args = args.Replace(" ", "");
    ISkillTrigger trigger = SkillTriggerMgr.Instance.CreateTrigger(type, args);
    if (trigger != null)
    {
    skill.m_SkillTrigers.Add(trigger);
    }
    }
    }
    } while (true);
    return true;
    }

    文件的解析,也很简单

    那么从代码上怎么实现呢?

    1.触发器:

    从同一个基类继承,

    2.工厂模式来创建注册触发器,

    在外部注册触发器的代码:

    3.技能实例来管理触发器,

    执行触发其实也可以写这里.

    4.技能系统来管理所有技能

    技能是可以复用的,技能系统就是一个技能池子,不停地new技能实例和回收技能实例

    部分Public 接口代码:

    总结一下思路,就是

    SkillSystem 管理SkillInstance,创建和回收所有技能

    SkillInstance 管理 SkillTrigger,负责触发器的触发.

    SkillTrigger 就执行具体的效果.


    展开全文
  • 关于Unity技能系统的设计

    千次阅读 多人点赞 2019-04-12 14:09:35
    分享几篇好文章,这几篇消化下,技能系统设计基本没问题了。 常规MMO技能系统:https://zhuanlan.zhihu.com/p/26077188 UnityACT技能编辑器的制作(上):https://zhuanlan.zhihu.com/p/38001896 方便扩展的被动...
  • Unity技能系统框架(一)技能效果

    千次阅读 2020-03-20 19:29:23
    这里记录下个人仿DOTA2编写的技能系统结构,借鉴了知乎博文的编辑器思想,使用了ProtoBuf和AdvancedInspector,最后仿照DOTA2的技能数据结构,编写了一套技能系统,个人感觉完全可以用在MOBA、MMORGP上,而且主动...
  • 这一篇分析一个具体的被动技能:蚁人的影矛 首先看下技能描述:“每个蚁人都是天生的掷手,投掷出长矛刺穿目标的身躯。普通攻击有几率对攻击范围内其他{0}名目标进行相同攻击。”,只要是个程序猿,智商足以总结出...
  • 看了上一篇的技能效果Demo,接下来大概说下该技能系统可实现的一些技能事件和效果。技能一般包含这几个要素: 数据(配置表和资源)、技能属性(消耗能量、冷却时间等)、事件操作(这是一个大的范畴,后面分析)...
  • unity简单技能系统

    2021-03-24 20:10:57
    unity技能系统 类类型概览 CharacterSkillManager 角色技能管理器 挂载在角色 持有SkillData与释放器 通过释放器进行技能释放 SkillDeployer 技能释放器基类 持有选取类型与影响效果两个接口 抽象函数释放方式 ...
  • 贼猫unity技能框架

    2019-10-31 20:03:34
    本人自用自开发的unity技能系统,以时间轴节点进行技能流程控制,可以单独制定每一个技能的效果逻辑,框架负责技能CD,前后摇以及取消链部分
  • unity 技能树Last month we kicked off Unite Now, a digital programming series that includes inspiring talks, demos, Q&As, and stories from Unity experts and creators. Not sure where to start? Here ...
  • 下面展示 游戏角色技能系统。 using System.Collections; using System.Collections.Generic; using UnityEngine; namespace MR_LBS.Client.Unity3D { public enum SkillType : int { Unknown, Attack, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,760
精华内容 1,504
关键字:

unity技能系统