设为首页
收藏本站
切换到宽版
官网
论坛
资格申请
更新日志
游戏体验
热搜
活动
交友
discuz
登录
|
VV Engine 官方中心
»
论坛
›
引擎交流
›
引擎教程
›
生命周期、身份、行为三条线讲清英雄系统 ...
返回列表
发新帖
查看:
34
|
回复:
1
生命周期、身份、行为三条线讲清英雄系统
[复制链接]
13674307070
13674307070
当前离线
积分
1301
30
主题
72
回帖
1301
积分
金牌会员
金牌会员, 积分 1301, 距离下一级还需 1699 积分
金牌会员, 积分 1301, 距离下一级还需 1699 积分
积分
1301
发消息
发表于 2026-8-21 07:56:12
|
显示全部楼层
|
阅读模式
一、英雄的生命周期:取名、创建、召唤、收回、删除
英雄和普通玩家最大的不同在于它的生命周期 —— 英雄不是注册就有的,而是玩家在游戏过程中创建的。创建之后可以召唤出来并肩作战,也可以收回去,最终还可以删除重建。
取名
是英雄创建的第一步,用 checkheroname 接口。这个接口不是直接设置名字,而是 "检查名字"—— 提交一个名字给引擎,引擎去查重、过滤敏感词、检查长度,然后通过触发告诉你结果。检查成功触发 checkusernameok,检查失败触发 checkusernameno。
这种 "先检查再创建" 的两步式设计,和人物改名的思路是一样的。名字不能随便设,得先确认可用,才能进入下一步。文档里的示例代码很清晰:先调 checkheroname 提交名字,在 checkusernameok 触发里调 createhero 真正创建英雄,在 checkusernameno 触发里提示玩家名字不可用。
创建
用 createhero 接口,传玩家对象、英雄名称、职业、性别。职业和人物一样,0 是战士、1 是法师、2 是道士。性别 0 男 1 女。创建成功后触发 createherook,文档里的示例是在这个触发里直接调 recallhero 把英雄召唤出来 —— 创建完直接放出来,符合玩家的预期。
召唤
用 recallhero,把英雄从 "收着" 的状态变成 "放出来" 的状态,英雄出现在玩家身边,可以战斗。
收回
用 unrecallhero,反过来,把英雄收回去,英雄消失,不再战斗。
召唤和收回是英雄系统最高频的操作。玩家打不过了收回英雄保命,打得过了放出来帮忙。这两个接口都只需要一个玩家对象参数,因为每个玩家只能有一个英雄,不需要指定是哪个英雄。
删除
用 delhero,删掉玩家的英雄。删除之后玩家可以重新创建新英雄。这个接口的应用场景主要是 "英雄转职" 或者 "重新选择英雄职业"—— 玩家不满意当前英雄的职业,删掉重建。删除是不可逆操作,实际使用的时候最好加二次确认,避免玩家误删。
英雄的生命周期看下来,和人物的注册登录有相似之处,但更灵活 —— 人物是注册了就一直在,英雄可以创建、召唤、收回、删除,整个生命周期由玩家控制。这种设计让英雄更像是一个 "可携带的伙伴",而不是一个独立的账号。
二、英雄对象与身份:获取、判断、状态
英雄创建之后,本质上是一个特殊的游戏对象。英雄系统给了一套接口来获取英雄对象、判断身份、查询状态。
获取英雄对象
用 gethero,传玩家对象,返回英雄对象。如果玩家没有英雄或者英雄没被召唤,返回字符串 "0"。这个返回值的处理要注意 —— 不是返回 nil,而是返回字符串 "0",判断的时候要写 if hero and hero ~= "0" then,不能只写 if hero then,因为字符串 "0" 在 Lua 里是真值。
拿到英雄对象之后,就可以用人物系统的大部分接口来操作英雄了 —— 改属性、给装备、加经验、查血量、放技能,都可以。因为英雄本质上就是一个特殊的玩家对象,人物接口对它同样适用。这也是为什么英雄系统的专属接口这么少 —— 大部分功能复用人物系统就行了。
是否有英雄
用 hashero,返回布尔值。这个接口比 gethero 轻量,只需要知道 "有没有",不需要拿到对象的时候用这个。比如 NPC 对话里判断 "有英雄才能接这个任务",就用 hashero,不用拿对象。
判断对象是否为英雄
用 ishero,传任意对象,返回是不是英雄。这个接口的应用场景是在通用逻辑里区分对象类型 —— 比如一个范围伤害技能,命中了目标之后需要知道目标是玩家、怪物还是英雄,不同类型处理方式可能不同(比如英雄死了不掉装备,玩家死了可能掉)。用 ishero 判断一下就行。
英雄是否唤出
用 isherorecall,传玩家对象,返回英雄是不是在放出来的状态。这个和 gethero 的返回值有关联 —— 英雄唤出了 gethero 才能拿到对象,没唤出返回 "0"。但 isherorecall 更直接,只需要知道状态就用这个。
英雄的身份体系看起来简单,但有一个核心思路:
英雄是玩家的附属对象,所有英雄相关的操作都通过玩家对象来定位
。 gethero(play)、hashero(play)、isherorecall(play)、recallhero(play)、unrecallhero(play),全部是传玩家对象,因为英雄属于玩家,通过玩家就能找到英雄,不需要单独的英雄 ID 来定位。
这种设计简化了接口 —— 不需要记英雄的 ID,只要有玩家对象就能操作英雄。但也意味着每个玩家只能有一个英雄,因为接口没有提供 "指定第几个英雄" 的参数。对于传奇类游戏来说,一个玩家一个英雄是标准设计,所以这个简化是合理的。
三、英雄改名:和人物改名同构的多阶段回调
英雄改名用 changeheroname 接口,但真正的逻辑不在这个接口里,而在它配套的一整套触发回调里。文档里列了九个回调函数,覆盖了改名的整个流程:
queryingheroname 是正在查询名字, queryheronameok 是查询成功(名字可用), changeingheroname 是正在修改, changeheronameok 是修改成功, heronameLengthfail 是名字长度不符合, heronamefilter 是名字包含非法字符, heronameexists 是名字已经被占用, changeheronamefail 是改名失败。
这套回调和人物改名的回调几乎是一模一样的结构 —— 查询中、查询成功、修改中、修改成功、长度失败、过滤失败、重名失败、通用失败。这说明引擎在改名这个功能上做了统一的设计,不管是人物改名还是英雄改名,走的都是同一套多阶段流程。
为什么改名需要这么多阶段?因为改名不是一个简单的赋值操作,它涉及到几个步骤:先查询名字是否合法(长度、敏感词),再查询是否重名,然后执行修改,最后通知结果。每个步骤都可能失败,每个失败原因都不一样,玩家需要知道具体是因为什么失败了 —— 是名字太长?有敏感词?还是被人占用了?不同的失败原因给不同的提示,体验才好。
文档里的示例回调都是给玩家发红色文字提示,内容很具体 ——"名字长度不允许超过 30 个字符"" 该名字存在非法字符 ""该名字已经被其他玩家占用"。这种具体的错误提示比统一的 "改名失败" 要好得多。
实际开发中的心得:
改名的回调函数要全部实现,不要只写成功回调
。如果只写了 changeheronameok,没写各种失败回调,玩家改名失败了就收不到任何提示,会以为游戏卡了。把九个回调都写好,每个失败原因给对应的提示,体验才完整。
还有一个细节:英雄改名的长度限制是 30 个字符,比人物名字长。这是因为英雄名字通常可以起得更个性化一些,限制宽松一点。实际用的时候注意不要超过这个限制。
四、英雄行为模式:攻击、跟随、休息三种状态
英雄放出来之后,不是傻站着的,它有自己的行为模式。VV 引擎给了三种模式:攻击、跟随、休息。
攻击模式
(模式 0)下,英雄会主动攻击周围的敌人,和主体一起战斗。这是最常用的模式,打怪 PK 的时候用。
跟随模式
(模式 1)下,英雄不主动攻击,只是跟着主体移动。遇到危险的时候切换到跟随模式,英雄不会主动引怪,更安全。跑图、过地图的时候也用跟随模式,避免英雄到处乱跑引怪。
休息模式
(模式 2)下,英雄站在原地不动,也不攻击,也不跟随。这个模式用得比较少,一般是需要英雄待在某个固定位置的时候用 —— 比如主体去引怪,英雄在远处等着,或者英雄卡在某个位置当肉盾。
模式的获取和设置用 getherosta 和 setherosta,都是传玩家对象和模式值。接口很简单,但模式切换是英雄操作中很高频的行为 —— 玩家打不同的怪、在不同的场景,需要频繁切换英雄模式。
实际开发中的心得:
模式切换最好做快捷键或者一键切换
,让玩家方便地在攻击和跟随之间切换。如果每次都要打开面板点按钮,体验很差。很多版本会做一个英雄切换的快捷键,按一下切攻击,再按一下切跟随,非常方便。
还有一个接口 herofollow,让英雄传送到主体身边。这个接口的应用场景是英雄卡住了或者离主体太远,一键拉回来。英雄在复杂地形里有时候会被卡住或者绕路,玩家等不及了就用这个接口直接把英雄拉到身边。做英雄系统的时候建议把这个功能也做成快捷键,玩家会经常用到。
五、英雄和主体的协同:合击与配合的底层支撑
英雄系统的专属接口里没有直接提到 "合击技能",但合击是英雄系统最核心的玩法之一。合击技能需要主体和英雄配合释放,底层依赖的是英雄对象的获取和操作。
从接口设计来看,合击技能的实现逻辑应该是这样的:玩家释放合击技能时,引擎先通过 gethero 获取英雄对象,确认英雄存在且唤出,然后同时对主体和英雄释放技能动画,计算合击伤害。这些逻辑引擎底层应该已经做好了,脚本层不需要自己实现合击的判定和伤害计算。
脚本层能做的是合击相关的外围逻辑 —— 比如合击技能的学习、合击等级的提升、合击怒气值的管理。这些可以通过人物系统的接口来实现,因为英雄也是玩家对象,可以给英雄加技能、改属性、管理怒气值。
英雄和主体的配合还体现在装备和成长上。英雄有自己的装备栏,可以穿装备,这些操作通过人物系统的装备接口来完成(因为英雄是玩家对象)。英雄也有自己的等级和经验,可以通过 changeexp 等接口给英雄加经验。英雄升级了属性会成长,和主体一样。
这里有一个重要的心得:
操作英雄的时候,先 gethero 拿到英雄对象,然后把它当普通玩家对象来用
。人物系统的接口(改属性、给经验、穿装备、放技能)大部分都适用于英雄。不要因为它是 "英雄" 就去找英雄专属接口,大部分操作没有专属接口,直接用人物接口就行。
比如要给英雄加 1000 经验,不是找什么 addheroexp 接口(没有这个),而是:
plaintext
local hero = gethero(play)if hero and hero ~= "0" then changeexp(hero, "+", 1000)end
先拿英雄对象,然后用人物的 changeexp 接口给英雄加经验。这个思路适用于几乎所有英雄操作 —— 拿对象,然后当普通玩家操作。
理解了这一点,英雄系统就变得非常简单了。专属接口只处理英雄特有的操作(创建、召唤、收回、改名、模式),其余全部复用人物系统。这种 "复用 + 专属" 的设计,既保证了英雄的特殊性,又避免了重复造轮子。
六、几个实际使用中的心得和坑
把英雄系统过完,结合传奇类游戏的开发经验,总结几个心得和容易踩的坑。
第一,gethero 没英雄时返回字符串 "0",不是 nil。
这个前面说了,再强调一次。判断的时候一定要写 if hero and hero ~= "0",不要只写 if hero。字符串 "0" 是真值,会通过判断,然后对字符串 "0" 调用人物接口就会报错。这个坑非常隐蔽,因为有英雄的时候一切正常,没英雄的时候才炸。
第二,英雄改名的回调要全部实现。
九个回调函数(查询中、查询成功、修改中、修改成功、长度失败、过滤失败、重名失败、通用失败)都要写,不要只写成功的。玩家改名失败了收不到提示会困惑。每个失败原因给具体的提示文字,体验才好。
第三,操作英雄之前先确认英雄唤出了。
很多操作(加经验、穿装备、放技能)需要英雄对象存在,也就是英雄被召唤出来了。如果英雄没唤出, gethero 返回 "0",操作会失败。在操作英雄之前先 isherorecall 判断一下,没唤出就先 recallhero 或者提示玩家先召唤英雄。
第四,英雄删除是不可逆的,加二次确认。
delhero 删掉英雄之后,英雄的等级、装备、技能都会丢失,玩家只能重新创建。实际使用的时候一定要加确认步骤 ——"确定要删除英雄吗?删除后无法恢复",避免玩家误操作。尤其是如果英雄身上穿了好装备,删除后装备怎么处理(是返还到背包还是一起删除)要想清楚,文档里没说,需要自己测试确认。
第五,英雄模式切换和英雄跟随建议做快捷键。
这两个是玩家高频操作,每次开面板点按钮体验很差。做快捷键或者一键按钮,玩家体验会好很多。攻击 / 跟随切换、英雄召回,这两个功能几乎是英雄玩家每分钟都要用的。
第六,英雄创建时的职业和性别选择要谨慎。
createhero 创建之后职业和性别就定了,不能改(除非删了重建)。创建前要让玩家充分确认,尤其是职业选择 —— 战士、法师、道士的玩法差异很大,选错了只能删号重来。建议在创建流程里加预览和确认步骤,不要一步就创建了。
第七,英雄取名的检查是异步的,不要在 checkheroname 之后直接创建。
checkheroname 只是提交名字检查,结果通过回调返回。不要在调用 checkheroname 的下一行就调 createhero,那时候检查结果还没回来。正确的做法是在 checkusernameok 回调里调 createhero,文档里的示例就是这么写的。
回复
举报
13674307070
13674307070
当前离线
积分
1301
30
主题
72
回帖
1301
积分
金牌会员
金牌会员, 积分 1301, 距离下一级还需 1699 积分
金牌会员, 积分 1301, 距离下一级还需 1699 积分
积分
1301
发消息
楼主
发表于 2026-8-21 07:56:57
|
显示全部楼层
挠头的500贡献
回复
举报
返回列表
发新帖
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
本版积分规则
发表回复
回帖后跳转到最后一页
浏览过的版块
素材分享
快速回复
返回顶部
返回列表