ET介绍——数值组件设计

这篇具有很好参考价值的文章主要介绍了ET介绍——数值组件设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

类似魔兽世界,moba这种技能极其复杂,灵活性要求极高的技能系统,必须需要一套及其灵活的数值结构来搭配。数值结构设计好了,实现技能系统就会非常简单,否则就是一场灾难。比如魔兽世界,一个人物的数值属性非常之多,移动速度,力量,怒气,能量,集中值,魔法值,血量,最大血量,物理攻击,物理防御,法术攻击,法术防御,等等多达几十种之多。属性跟属性之间又相互影响,buff又会给属性增加绝对值,增加百分比,或者某种buff又会在算完所有的增加值之后再来给你翻个倍。

普通的做法:

一般就是写个数值类:

class Numeric
{
    public int Hp;
    public int MaxHp;
    public int Speed;
    // 能量
    public int Energy;
    public int MaxEnergy;
    // 魔法
    public int Mp;
    public int MaxMp;
    .....
}

 

仔细一想,我一个盗贼使用的是能量,为什么要有一个Mp的值?我一个法师使用的是魔法为什么要有能量的字段?纠结这个搞毛,当作没看见不就行了吗?实在不行,我来个继承?

// 法师数值
calss MageNumeric: Numeric
{
    // 魔法
    public int Mp;
    public int MaxMp;
}

// 盗贼数值
calss RougeNumeric: Numeric
{
    // 能量
    public int Energy;
    public int MaxEnergy;
}

 

10个种族,每个种族7,8种英雄,光这些数值类继承关系,你就得懵逼了吧。面向对象是难以适应这种灵活的复杂的需求的。

再来看看Numeric类,每种数值可不能只设计一个字段,比如说,我有个buff会增加10点Speed,还有种buff增加50%的speed,那我至少还得加三个二级属性字段

class Numeric
{
    // 速度最终值
    public int Speed;
    // 速度初始值
    public int SpeedInit;
    // 速度增加值
    public int SpeedAdd;
    // 速度增加百分比值
    public int SpeedPct;
}

 

SpeedAdd跟SpeedPct改变后,进行一次计算,就可以算出最终的速度值。buff只需要去修改SpeedAdd跟SpeedPct就行了。

Speed = (SpeedInit + SpeedAdd) * (100 + SpeedPct) / 100

 

每种属性都可能有好几种间接影响值,可以想想这个类是多么庞大,初略估计得有100多个字段。麻烦的是计算公式基本一样,但是就是无法统一成一个函数,例如MaxHp,也有buff影响

class Numeric
{
    public int Speed;
    public int SpeedInit;
    public int SpeedAdd;
    public int SpeedPct;
    
    public int MaxHp;
    public int MaxHpInit;
    public int MaxHpAdd;
    public int MaxHpPct;
}

 

也得写个Hp的计算公式

MaxHp=(MaxHpInit + MaxHpAdd) * (100  + MaxHpPct) / 100

 

几十种属性,就要写几十遍,并且每个二级属性改变都要正确调用对应的公式计算. 非常麻烦! 这样设计还有个很大的问题,buff配置表填对应的属性字段不是很好填,例如疾跑buff(增加速度50%),在buff表中怎么配置才能让程序简单的找到并操作SpeedPct字段呢?不好搞。

ET框架采用了Key Value形式保存数值属性

using System.Collections.Generic;

namespace Model
{
    public enum NumericType
    {
        Max = 10000,

        Speed = 1000,
        SpeedBase = Speed * 10 + 1,
        SpeedAdd = Speed * 10 + 2,
        SpeedPct = Speed * 10 + 3,
        SpeedFinalAdd = Speed * 10 + 4,
        SpeedFinalPct = Speed * 10 + 5,

        Hp = 1001,
        HpBase = Hp * 10 + 1,

        MaxHp = 1002,
        MaxHpBase = MaxHp * 10 + 1,
        MaxHpAdd = MaxHp * 10 + 2,
        MaxHpPct = MaxHp * 10 + 3,
        MaxHpFinalAdd = MaxHp * 10 + 4,
        MaxHpFinalPct = MaxHp * 10 + 5,
    }

    public class NumericComponent: Component
    {
        public readonly Dictionary<int, int> NumericDic = new Dictionary<int, int>();

        public void Awake()
        {
            // 这里初始化base值
        }

        public float GetAsFloat(NumericType numericType)
        {
            return (float)GetByKey((int)numericType) / 10000;
        }

        public int GetAsInt(NumericType numericType)
        {
            return GetByKey((int)numericType);
        }

        public void Set(NumericType nt, float value)
        {
            this[nt] = (int) (value * 10000);
        }

        public void Set(NumericType nt, int value)
        {
            this[nt] = value;
        }

        public int this[NumericType numericType]
        {
            get
            {
                return this.GetByKey((int) numericType);
            }
            set
            {
                int v = this.GetByKey((int) numericType);
                if (v == value)
                {
                    return;
                }

                NumericDic[(int)numericType] = value;

                Update(numericType);
            }
        }

        private int GetByKey(int key)
        {
            int value = 0;
            this.NumericDic.TryGetValue(key, out value);
            return value;
        }

        public void Update(NumericType numericType)
        {
            if (numericType > NumericType.Max)
            {
                return;
            }
            int final = (int) numericType / 10;
            int bas = final * 10 + 1; 
            int add = final * 10 + 2;
            int pct = final * 10 + 3;
            int finalAdd = final * 10 + 4;
            int finalPct = final * 10 + 5;

            // 一个数值可能会多种情况影响,比如速度,加个buff可能增加速度绝对值100,也有些buff增加10%速度,所以一个值可以由5个值进行控制其最终结果
            // final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;
            this.NumericDic[final] = ((this.GetByKey(bas) + this.GetByKey(add)) * (100 + this.GetByKey(pct)) / 100 + this.GetByKey(finalAdd)) * (100 + this.GetByKey(finalPct)) / 100;
            Game.EventSystem.Run(EventIdType.NumbericChange, this.Entity.Id, numericType, final);
        }
    }
}

 

1.数值都用key value来保存,key是数值的类型,由NumericType来定义,value都是整数,float型也可以转成整数,例如乘以1000;key value保存属性会变得非常灵活,例如法师没有能量属性,那么初始化法师对象不加能量的key value就好了。盗贼没有法力值,没有法术伤害等等,初始化就不用加这些。

2.魔兽世界中,一个数值由5个值来影响,可以统一使用一条公式:

final = (((base + add) * (100 + pct) / 100) + finalAdd) * (100 + finalPct) / 100;

 

比如说速度值speed,有个初始值speedbase,有个buff1增加10点绝对速度,那么buff1创建的时候会给speedadd加10,buff1删除的时候给speedadd减10,buff2增加20%的速度,那么buff2创建的时候给speedpct加20,buff2删除的时候给speedpct减20.甚至可能有buff3,会在最终值上再加100%,那么buff3将影响speedfinalpct。这5个值发生改变,统一使用Update函数就可以重新计算对应的属性了。buff配置中对应数值字段相当简单,buff配置中填上相应的NumericType,程序很轻松就能操作对应的数值。

3.属性的改变可以统一抛出事件给其它模块订阅,写一个属性变化监视器变得非常简单。例如成就模块需要开发一个成就生命值超过1000,会获得长寿大师的成就。那么开发成就模块的人将订阅HP的变化:

    /// 监视hp数值变化
    [NumericWatcher(NumericType.Hp)]
    public class NumericWatcher_Hp : INumericWatcher
    {
        public void Run(long id, int value)
        {
            if (value > 1000)
            {
                //获得成就长寿大师成就
            }
        }
    }

 

同理,记录一次金币变化大于10000的异常日志等等都可以这样做。

有了这个数值组件,一个moba技能系统可以说已经完成了一半。

ET开源地址地址:egametang/ET: Unity3D Client And C# Server Framework (github.com)   qq群:474643097文章来源地址https://www.toymoban.com/news/detail-450357.html

到了这里,关于ET介绍——数值组件设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 魔兽世界私服架设教程—魔兽大服务器合并列表

    都说魔兽世界是最经典的网游,可惜我沉迷于程序的世界, 用以下命令down源码 git clone git://github.com/mangos/mangos.git 编译的时候会出错,找不到以下两个文件 revision.h SystemConfig.h 其实以上文件只是简单的定义同个编译的宏而已,自己动手写一个就可以了! 然后编译就没有问题了

    2023年04月18日
    浏览(115)
  • 魔兽世界宏命令完全指南

    一、基本宏命令 1.什么是宏 ? 宏是由一组宏命令语句 组成的 集合 。以下是一些普通宏命令的示例 :/say (/s, /说) /whisper (/w, /talk, /t, /告诉) /reply (/r, /回复) /emote (/e, /em, /me, /表情) /dance (/跳舞) 喜爱PVP的人 ,应该不会忘了这个:/spit (/吐口水) 把宏 放到技能栏上,我们就可以

    2024年02月13日
    浏览(58)
  • 开源魔兽世界服务器搭建

    本文档是原创的,具有可操作性,不是网络上互相抄袭的博客。 觉得有用就赞一个。 项目官网: http://everwar.cn 同名原创文章(界面样式更简洁一些): 开源魔兽世界私服搭建 - 狂奔的骆驼 - 博客园 60魔兽经典旧世是最经典的版本,遗憾的是60年代时还在大学读书,穷得很,

    2024年02月02日
    浏览(38)
  • 魔兽世界私人服务器怎么开

    开设魔兽世界的私人服务器涉及到一系列复杂的步骤和技术要求。下面是一个大致的指南,以供参考: 1. 硬件需求:首先,你需要一台强大的服务器来承载游戏服务器。服务器的规模和配置将取决于你计划同时容纳多少玩家以及服务器的性能要求。推荐选择一台高性能的专用

    2024年02月12日
    浏览(65)
  • 魔兽世界全版本GM命令全集

    命令: .levelup 79 (升级数1-79) .modify money 999999999 增加金币 .modify hp 9999999 9999999 增加被选择人物的血量 .modify mana 9999999 9999999 增加被选择人物的蓝量 .modify speed 30 加速人物跑步 .modify speed 1 还原人物跑步 .modify aspeed 1 还原人物游泳 .gm fly on 开启GM飞行模式 .gm fly off 关闭GM飞行模式

    2024年02月09日
    浏览(53)
  • 魔兽世界经典旧世私服搭建教程

    60魔兽经典旧世是最经典的版本,遗憾的是60年代时还在大学读书,穷得很,买不起点卡,后来工作了,大概70年代开始玩的。 多年以前,玩游戏时,一直非常期望能够自己控制角色的属性级别,得到各种装备。 多年以后,在这款纯粹的开源服务器问世后,终于如愿以偿。 直

    2024年02月04日
    浏览(52)
  • 开源魔兽世界服务器everwar搭建

    本文档是原创的,具有可操作性,不是网络上互相抄袭的博客。 觉得有用就赞一个。 项目官网: http://everwar.cn 同名原创文章(界面样式更简洁一些): 开源魔兽世界私服搭建 - 狂奔的骆驼 - 博客园 60魔兽经典旧世是最经典的版本,遗憾的是60年代时还在大学读书,穷得很,

    2024年02月13日
    浏览(50)
  • 魔兽世界私服架设教程—GM命令大全

    如果需要什么命令可以按ctrl+f查找,比如泰坦之握,就会直接定位到你想要的命令那里。 橙色武器: 85版本 橙匕首,龙父之牙 戈拉德,龙王之暮 提里奥什,远古噩梦 77949 77950 橙杖,可以变龙 巨龙之怒,泰蕾苟萨的寄魂杖 71086 80版本 橙斧 影之哀伤 49623 橙锤 瓦兰奈尔,远古

    2024年02月04日
    浏览(53)
  • 魔兽世界私服架设 服务器架设简易教程

    今天早晨明杰终于把魔兽世界的私服搭建成功可以运行了。挺happy。 记录一下搭建的全过程: 1.先下载私服服务器端:从mangoscn.com下载大芒果ftp://www.mangoscn.com/TCCN-3.2.2-Trinity5749.exe 从这个地址下载不需要注册,如果从mangoscn.com的网页上直接点击,还需要邀请码,注册以后才能

    2024年02月04日
    浏览(56)
  • 魔兽世界60级1.12私服搭建架设教程

    60 魔兽经典旧世是最经典的版本,遗憾的是 60 年代时还在大学读书,穷得很,买不起点卡,后来工作了,大概 70 年代开始玩的。 多年以前,玩游戏时,一直非常期望能够自己控制角色的属性级别,得到各种装备。 多年以后,在这款纯粹的开源服务器问世后,终于如愿以偿。

    2024年02月05日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包