【Unity】RPG2D龙城纷争(四)要诀、要诀数据集
更新日期:2024年6月20日。
项目源码:第五章发布(正式开始游戏逻辑的章节)
索引
- 简介
- 要诀数据集(AbilityDataSet)
- 一、定义要诀数据集类
- 二、要诀属性
- 1.要诀类型
- 2.攻击距离
- 3.基础命中、暴击率
- 4.基础属性加成
- 5.要诀特效
- 三、要诀显示面板
- 要诀(Ability)
- 一、定义要诀类
- 二、角色挂载要诀
- 三、要诀栏位
- 四、要诀栏位激活
简介
上一篇有了角色类, 这一章我们将实现要诀(也即是技能,只是这里披了另一个名字)类,同理,要诀也应当有要诀数据集类,用以描述要诀属性中的共用部分。
要诀数据集(AbilityDataSet)
与角色同理,比如20个士兵,当他们需要使用同一个要诀时,理应只需要持有同一个要诀数据集即可。
一、定义要诀数据集类
首先,我们定义要诀数据集类AbilityDataSet:
/// <summary>/// 要诀数据集/// </summary>[Serializable][CreateAssetMenu(menuName = "HTFramework/★ GameComponent/RPG2D/Ability Asset", order = 300)]public sealed class AbilityDataSet : DataSetBase{}
二、要诀属性
根据前车之鉴,我们先定义如下一系列属性:
public sealed class AbilityDataSet : DataSetBase{/// <summary>/// 要诀名称/// </summary>[Label("要诀名称")] public string Name;/// <summary>/// 要诀类型/// </summary>[Label("要诀类型")] public AbilityType Type;/// <summary>/// 攻击距离/// </summary>[Label("攻击距离"), Display("IsNoBuffProperty")] public int AttackDistance = 1;/// <summary>/// 基础命中率/// </summary>[Label("基础命中率"), Display("IsAttackProperty")] public int BaseHitRate = 100;/// <summary>/// 基础暴击率/// </summary>[Label("基础暴击率"), Display("IsAttackProperty")] public int BaseCriticalRate = 100;/// <summary>/// 速度加成/// </summary>[Label("速度加成"), Display("IsBuffProperty")] public int AddedSpeed;/// <summary>/// 生命加成(初始值)/// </summary>[Label("生命加成(初始值)"), Display("IsBuffProperty")] public int AddedHP;/// <summary>/// 攻击加成(初始值)/// </summary>[Label("攻击加成(初始值)")] public int AddedATK;/// <summary>/// 防御加成(初始值)/// </summary>[Label("防御加成(初始值)"), Display("IsBuffProperty")] public int AddedDEF;/// <summary>/// 敏捷加成(初始值)/// </summary>[Label("敏捷加成(初始值)"), Display("IsBuffProperty")] public int AddedDEX;/// <summary>/// 会心加成(初始值)/// </summary>[Label("会心加成(初始值)"), Display("IsBuffProperty")] public int AddedCRI;/// <summary>/// 生命加成(成长值)/// </summary>[Label("生命加成(成长值)"), Display("IsBuffProperty")] public int AddedHP_Inc;/// <summary>/// 攻击加成(成长值)/// </summary>[Label("攻击加成(成长值)")] public int AddedATK_Inc;/// <summary>/// 防御加成(成长值)/// </summary>[Label("防御加成(成长值)"), Display("IsBuffProperty")] public int AddedDEF_Inc;/// <summary>/// 敏捷加成(成长值)/// </summary>[Label("敏捷加成(成长值)"), Display("IsBuffProperty")] public int AddedDEX_Inc;/// <summary>/// 会心加成(成长值)/// </summary>[Label("会心加成(成长值)"), Display("IsBuffProperty")] public int AddedCRI_Inc;/// <summary>/// 要诀描述/// </summary>[Label("要诀描述"), TextArea(2, 10)] public string Description;/// <summary>/// 要诀特效/// </summary>[Label("要诀特效"), Display("IsNoBuffProperty")] public AbilityEffect Effect;}
接下来我们强行解释。
1.要诀类型
要诀类型可分为如下三种:
/// <summary>/// 要诀类型/// </summary>public enum AbilityType{/// <summary>/// 攻击型(攻击敌方)/// </summary>[Remark("攻击型")]Attack,/// <summary>/// 加成型(被动生效,永久提升属性)/// </summary>[Remark("加成型")]Buff,/// <summary>/// 治疗型(治疗友方)/// </summary>[Remark("治疗型")]Health}
2.攻击距离
这是一个相当重要的属性,他决定了攻击、治疗(忽略加成)型要诀的另一个重要归类:
| 攻击距离 | 归类 | 原地使用 | 移动后立即使用 |
|---|---|---|---|
| 1 | 近程攻击、治疗要诀 | 能 | 能 |
| >1 | 远程攻击、治疗要诀 | 能 | 不能 |
也即是说,角色移动后是无法立即使用远程攻击、治疗要诀的,这避免了无脑风筝对手,此对战机制照搬第二次超级机器人大战。
3.基础命中、暴击率
基础命中率、基础暴击率为此要诀在计算命中率、暴击率时的基础值,基础命中率、基础暴击率越高的要诀,越容易命中、暴击对手。
4.基础属性加成
加成型要诀可提供速度、生命、攻击、防御、敏捷、会心等基础属性的加成,同时伴有成长值,随角色等级成长,同理,速度是不能成长的。
5.要诀特效
攻击、治疗型要诀会在释放时播放对应的特效,这里我们使用另一个类AbilityEffect来描述,其挂载到GameObject上后,再将创建后的预制体引入到此处便可:
/// <summary>/// 要诀特效/// </summary>[DisallowMultipleComponent]public class AbilityEffect : HTBehaviour{/// <summary>/// 发射特效(发射时播放,可为空)/// </summary>[Label("发射特效"), SerializeField] protected PlayableDirector LaunchEffect;/// <summary>/// 飞行特效(飞行中播放,如果是近程攻击型,不需要远距离飞行,可为空)/// </summary>[Label("飞行特效"), SerializeField] protected PlayableDirector FlightEffect;/// <summary>/// 击中特效(击中时播放,可为空)/// </summary>[Label("击中特效"), SerializeField] protected PlayableDirector HitEffect;/// <summary>/// 飞行特效飞行时间/// </summary>[Label("飞行特效飞行时间"), SerializeField] protected float FlightTime = 1;/// <summary>/// 发射音效/// </summary>[Label("发射音效"), SerializeField] protected AudioClip LaunchAudio;/// <summary>/// 击中音效/// </summary>[Label("击中音效"), SerializeField] protected AudioClip HitAudio;}
这里的特效采用TimeLine(PlayableDirector)配置。
播放特效时,应当是具备延时性的,所以我们定义播放特效为协程方法:
public class AbilityEffect : HTBehaviour{/// <summary>/// 播放特效/// </summary>/// <param name="self">要诀所属角色</param>/// <param name="other">要诀释放的目标角色</param>public virtual IEnumerator PlayEffect(Role self, Role other){//初始所有特效不可见gameObject.SetActive(true);if (LaunchEffect != null) LaunchEffect.gameObject.SetActive(false);if (FlightEffect != null) FlightEffect.gameObject.SetActive(false);if (HitEffect != null) HitEffect.gameObject.SetActive(false);//发射特效if (LaunchEffect != null){LaunchEffect.gameObject.SetActive(true);LaunchEffect.transform.position = self.transform.position;LaunchEffect.Play();if (LaunchAudio != null) Main.m_Audio.PlayOneShoot(LaunchAudio);yield return YieldInstructioner.GetWaitForSeconds((float)LaunchEffect.duration);LaunchEffect.gameObject.SetActive(false);yield return null;}//飞行特效(飞行特效应当是连贯的,除非让飞行时间完全等于特效的播放时长)if (FlightEffect != null){FlightEffect.gameObject.SetActive(true);FlightEffect.transform.position = self.transform.position;FlightEffect.Play();FlightEffect.transform.DOMove(other.transform.position, FlightTime);yield return YieldInstructioner.GetWaitForSeconds(FlightTime);FlightEffect.gameObject.SetActive(false);yield return null;}//击中特效(击中特效应当始终播放,即便未命中敌人)if (HitEffect != null){HitEffect.gameObject.SetActive(true);HitEffect.transform.position = other.transform.position;HitEffect.Play();if (HitAudio != null) Main.m_Audio.PlayOneShoot(HitAudio);yield return YieldInstructioner.GetWaitForSeconds((float)HitEffect.duration);HitEffect.gameObject.SetActive(false);yield return null;}//直接销毁特效,由于特效分类较多,就不使用对象池缓存了,当然切换成对象池也很简单Destroy(gameObject);}}
三、要诀显示面板
在要诀数据集中,有些属性是攻击型特有的,有些属性又是加成型特有的,我们如何做到在检视器面板根据要诀类型只显示对它有效的属性(毕竟全都显示太过杂乱)?
这就需要HT.Framework.Display特性了。
比如攻击距离这个属性,很明显只有攻击、治疗型才有效:
/// <summary>/// 攻击距离/// </summary>[Label("攻击距离"), Display("IsNoBuffProperty")] public int AttackDistance = 1;
那么此处为其标记了Display特性,特性指定的方法将作为此属性的显示规则,比如此处的方法IsNoBuffProperty,根据字面意义可理解为:不是加成型要诀的属性。
而事实上它的判断规则也就是这样的:
#if UNITY_EDITOR/// <summary>/// 是否为非Buff要诀属性/// </summary>private bool IsNoBuffProperty(){return Type != AbilityType.Buff;}
#endif
Display特性仅在编辑器生效(以避免运行时多余开销),所以IsNoBuffProperty方法也请包含在UNITY_EDITOR宏定义中。
那么最终,我们的要诀数据集检视器面板显示如下:

要诀(Ability)
要诀数据集有了,同样要使用一个要诀类来持有它。
一、定义要诀类
/// <summary>/// 要诀/// </summary>[DisallowMultipleComponent]public class Ability : HTBehaviour{/// <summary>/// 所属的角色/// </summary>[Label("所属的角色")] public Role BelongRole;/// <summary>/// 要诀栏位/// </summary>[Label("要诀栏位")] public int Index = 1;/// <summary>/// 要诀数据集/// </summary>[Label("要诀数据集"), SerializeField] internal AbilityDataSet DataSet;}
要诀(Ability)类应当再次被角色(Role)类所持有,如此才能形成完备的工作链,所以Ability必须知道它所属的角色是谁。
目前我的想法是为角色标配8个要诀栏位,所以每个要诀必须知道自身所属的要诀栏位。
二、角色挂载要诀
上面说了要诀将被角色持有,所以我们将焦点切回到Role类,以定义一些新东西:
public class Role : HTBehaviour{/// <summary>/// 要诀(持有的8个要诀)/// </summary>[Label("要诀")] public Ability[] Abilities;}
然后,挂载要诀(Ability)类的物体,应当是角色(Role)类的物体的子级,如下这样:

三、要诀栏位
这8个子级物体,也即是代表了8个要诀栏位,要诀栏位检视面板如下:

要诀栏位持有何种要诀数据集,便决定了此栏位成为何种要诀,如果为null,则是一个空位置,可以学习其他要诀(要诀研习系统)。
四、要诀栏位激活
8个要诀栏位并非一出生就都激活,不然几个1级的角色也能7、8个要诀打来打去,打得天昏地暗,而所有要诀都有了,也将降低升级带来的成就感。
所以初步定义一个要诀栏位激活规则:
- 要诀栏位1:初始激活。
- 要诀栏位2:初始激活。
- 要诀栏位3:初始激活。
- 要诀栏位4:角色20级后激活。
- 要诀栏位5:角色40级后激活。
- 要诀栏位6:角色60级后激活。
- 要诀栏位7:角色80级后激活。
- 要诀栏位8:角色100级后激活。
此规则的核心奥义是:
初始3个要诀够用,每提升20级将拥有一个新的要诀栏位,使得每多出一个要诀栏位都弥足珍贵,而在角色设计之初就可以为其赋予8个完整的要诀,只是要诀栏位未激活时,要诀是不可用的。
代码实现:
/// <summary>/// 要诀位是否激活/// </summary>[PropertyDisplay("要诀位是否激活")]public virtual bool IsActive{get{if (DataSet != null){switch (Index){case 1:case 2:case 3:return true;case 4:return BelongRole.Grade >= 20;case 5:return BelongRole.Grade >= 40;case 6:return BelongRole.Grade >= 60;case 7:return BelongRole.Grade >= 80;case 8:return BelongRole.Grade >= 100;}return false;}else{return false;}}}
好了,要诀部分暂时就这些,不过我脑海中灵光一闪,第二次机战中耳熟能详的间无机制以及二反机制瞬间就有了照搬的方案,我将其命名为特殊加成型要诀,那么,期待下一次登场吧!
相关文章:
【Unity】RPG2D龙城纷争(四)要诀、要诀数据集
更新日期:2024年6月20日。 项目源码:第五章发布(正式开始游戏逻辑的章节) 索引 简介要诀数据集(AbilityDataSet)一、定义要诀数据集类二、要诀属性1.要诀类型2.攻击距离3.基础命中、暴击率4.基础属性加成5.…...
一种基于非线性滤波过程的旋转机械故障诊断方法(MATLAB)
在众多的旋转机械故障诊断方法中,包络分析,又称为共振解调技术,是目前应用最为成功的方法之一。首先,对激励引起的共振频带进行带通滤波,然后对滤波信号进行包络谱分析,通过识别包络谱中的故障相关的特征频…...
HarmonyOS Next 系列之从手机选择图片或拍照上传功能实现(五)
系列文章目录 HarmonyOS Next 系列之省市区弹窗选择器实现(一) HarmonyOS Next 系列之验证码输入组件实现(二) HarmonyOS Next 系列之底部标签栏TabBar实现(三) HarmonyOS Next 系列之HTTP请求封装和Token…...
如果xml在mapper目录下,如何扫描到xml
如果xml在mapper目录下,如何扫描到xml 项目结构 src├── main│ ├── java│ │ └── com│ │ └── bg│ │ ├── Application.java│ │ ├── domain│ │ │ └── User.java│ │ …...
什么是无限铸币攻击?它是如何运作的?
一、无限铸币攻击解释 无限铸币攻击是指攻击者操纵合约代码不断铸造超出授权供应限制的新代币。 这种黑客行为在去中心化金融 (DeFi) 协议中最为常见。这种攻击通过创建无限数量的代币来损害加密货币或代币的完整性和价值。 例如,一名黑客利用了 Paid 网络的智能…...
【Android】怎么使APP进行开机启动
项目需求 在Android系统开启之后,目标app可以在系统开机之后启动。 项目实现 使用广播的方式 首先我们要创建一个广播(这里是启动了一个Service服务) public class BootReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context context, I…...
详细分析Element Plus的el-pagination基本知识(附Demo)
目录 前言1. 基本知识2. Demo3. 实战 前言 需求:从无到有做一个分页并且附带分页的导入导出增删改查等功能 前提一定是要先有分页,作为全栈玩家,先在前端部署一个分页的列表 相关后续的功能,是Java,推荐阅读&#x…...
ubuntu换镜像源方法
查看ubuntu的版本,不同的版本对应的不同的镜像源 cat /etc/issue Ubuntu 18.04.6 LTS \n \l 先备份一个,防止更改错误 cobol cp /etc/apt/sources.list /etc/apt/sources.list.backup 先进入清华源,搜索ubuntu,点击问号 点进来可以看到可以…...
python flask配置邮箱发送功能,使用flask_mail模块
🌈所属专栏:【Flask】✨作者主页: Mr.Zwq✔️个人简介:一个正在努力学技术的Python领域创作者,擅长爬虫,逆向,全栈方向,专注基础和实战分享,欢迎咨询! 您的点…...
Flask快速入门(路由、CBV、请求和响应、session)
Flask快速入门(路由、CBV、请求和响应、session) 目录 Flask快速入门(路由、CBV、请求和响应、session)安装创建页面Debug模式快速使用Werkzeug介绍watchdog介绍快速体验 路由系统源码分析手动配置路由动态路由-转换器 Flask的CBV…...
人工智能指数报告
2024人工智能指数报告(一):研发 前言 全面分析人工智能的发展现状。 从2017年开始,斯坦福大学人工智能研究所(HAI)每年都会发布一份人工智能的研究报告,人工智能指数报告(AII&…...
聊聊 Mybatis 动态 SQL
这篇文章,我们聊聊 Mybatis 动态 SQL ,以及我对于编程技巧的几点思考 ,希望对大家有所启发。 1 什么是 Mybatis 动态SQL 如果你使用过 JDBC 或其它类似的框架,你应该能理解根据不同条件拼接 SQL 语句有多痛苦,例如拼…...
【windows|004】BIOS 介绍及不同品牌电脑和服务器进入BIOS设置的方法
🍁博主简介: 🏅云计算领域优质创作者 🏅2022年CSDN新星计划python赛道第一名 🏅2022年CSDN原力计划优质作者 🏅阿里云ACE认证高级工程师 🏅阿里云开发者社区专家博主 💊交流社…...
lvgl的应用:移植MusicPlayer(基于STM32F407)
目录 概述 1 软硬件环境 1.1 UI开发版本 1.2 MCU开发环境 1.3 注意点 2 GUI Guider开发UI 2.1 使用GUI Guider创建UI 2.2 GUI Guider编译项目和测试 2.2.1 GUI Guider编译项目 2.2.2 编译 2.3 了解GUI Guider生成代码 3 移植项目 3.1 Keil中加载代码 3.2 调用G…...
Hadoop3:MapReduce中的Shuffle机制
一、流程图 Shuffle是Map方法之后,Reduce方法之前的数据处理过程称。 二、图解说明 1、数据流向 map方法中context.write(outK, outV);开始,写入环形缓冲区,再进行分区排序,写到磁盘 reduce方法拉取磁盘上的数据,…...
从设计到实践:高速公路监控技术架构全剖析
随着高速公路网络的迅速扩展和交通流量的日益增加,高效的监控系统成为保障交通安全、提升管理效率的重要手段。本文将深入探讨高速公路监控技术架构,从设计理念到实际应用,全面解析这一关键技术的各个环节。 ### 一、系统设计理念 #### 1. 高…...
Go Context
Context 介绍 Context 代表了协程的上下文,用以在父子协程之间传递控制信号,共享变量等操作// context.Context 接口 type Context interface {// 当Context自动取消或者到了取消时间被取消后返回Deadline() (deadline time.Time, ok bool)// 当Contex…...
centOS Stream9配置NAT8网络
首先将VMware关机,添加网络适配器 启动虚拟机,查看ens192是否打开连接 安装的图形化需要查看右上角电源处网卡是否连接 最小化安装一般不会出现未连接的状态 使用ip a 查看 配置网卡文件 cd /etc/NetworkManager/system-connections/cd到当前目录下…...
Linux - 进程
一、什么是进程 首先,Linux是一个多用户多进程的操作系统,系统上可以同时运行多个进程。 进程的产生:①是在执行程序或者命令时产生的;②定时任务进程 进程的类型:前台进程/后台进程 前台进程:一个终端…...
nginx+tomcat负载均衡、动静分离群集【☆☆☆☆☆】
Nginx是一款非常优秀的HTTP服务器软件,性能比tomcat更优秀,它支持高达50 000个并发连接数,拥有强大的静态资源处理能力,运行稳定,内存、CPU等系统资源消耗非常低。目前很多大型网站都应用Nginx服务器作为后端网站程序的…...
接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
观成科技:隐蔽隧道工具Ligolo-ng加密流量分析
1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...
第19节 Node.js Express 框架
Express 是一个为Node.js设计的web开发框架,它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用,和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...
算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
代码规范和架构【立芯理论一】(2025.06.08)
1、代码规范的目标 代码简洁精炼、美观,可持续性好高效率高复用,可移植性好高内聚,低耦合没有冗余规范性,代码有规可循,可以看出自己当时的思考过程特殊排版,特殊语法,特殊指令,必须…...
0x-3-Oracle 23 ai-sqlcl 25.1 集成安装-配置和优化
是不是受够了安装了oracle database之后sqlplus的简陋,无法删除无法上下翻页的苦恼。 可以安装readline和rlwrap插件的话,配置.bahs_profile后也能解决上下翻页这些,但是很多生产环境无法安装rpm包。 oracle提供了sqlcl免费许可,…...
