骑马与砍杀中文站论坛

 找回密码
 注册(Register!)

QQ登录

只需一步,快速开始

搜索
购买CDKEY 小黑盒加速器
查看: 6111|回复: 8

[版主推荐] 战团-顶点动画综合控制理论体系,独家研究

[复制链接]

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
发表于 2023-1-5 16:51:19 | 显示全部楼层 |阅读模式
本帖最后由 vegetto 于 2023-1-6 17:04 编辑

前言:在骑砍里大家所接触到的动画大多是骨骼动画,并且是代码程序可控的;还有少量顶点动画,大多数人处理的场合就是大地图的图标以及部分盾牌弓箭类的武器;以及shader等手段产生的类似UV材质变化的动画效果。实际上动画对于游戏是一个比较广义的概念,比如粒子的放大缩小、贴图的rgb变化都可以看作动画,并且部分系统能够用代码进行模拟也可以用模型手段做出。所以我将对大家不经常或缺乏必要技术研究支持的顶点动画和2D序列图动画系统作出独家系统研究体系的分享和讲解。
本贴主要讲下顶点动画。主要是场景物的顶点动画,因为其他武器大地图图标的常规ms不可控并且不是技术盲区可搜索到,所以这些我不讲。


一、顶点动画模型的制作
1.骑砍适用的顶点动画即md3格式的动画模型的来历:
最初来自一款射击游戏鼻祖雷神之锤的续作quake3,基于制作反恐精英cs的半条命1代,steamG胖发家的游戏就是由这个quake1和2代引擎结合编出来的,quake系列123,分别采用的模型格式mdl、md2、md3进化,也就是md3是最古老的真正的3d动画格式,是游戏史上顶点动画向骨骼动画的最后的过渡技术(因为md3其实也算骨骼动画,quake3的人物基本分成upper上半身,lower下半身和head头部,三个部分,每个部分都是纯md3顶点动画,但是有一个cfg文件强行以骨骼模拟的方式在upper与head,lower与upper之间分别构造了一根骨骼,也就是两个单根骨骼动画串了3个顶点动画,所以说这个是骨骼动画过渡的雏形)。


2.md3动画技术在骑砍深度运用的模型动画技术瓶颈:
一般对于有一点模型动画软件使用基础的人来说,顶点动画的制作他们会采用模型动画软件对动画模型逐帧导出obj再导入openbrf在满足各帧模型顶点面数坐标一样时全选右键点击“merge frames as in a vertex ani”合成顶点动画模型,这个是一个繁琐的方法,试问,如果帧数成百上千,你该怎么办,如果模型具有多个分割部分对应多个材质贴图,那你还要每个mesh部分分别合成帧,你的工作量又是成倍,甚至你导出后并不能保证各帧模型顶点面数坐标一样。


3.模型动画技术瓶颈在骑砍如何突破:
所以我手上有一个这种动画高效处理的软件,可以对主流绑定动画的模型格式dae,fbx等等进行一键整体转化md3,哪怕一万帧也是几秒转化的事情,这个软件看大家对此技术学习的需求积不积极再分享。

所以我的制作步骤是,先准备好绑定全体动画的动画模型,最佳模型格式是fbx(最好设置成2014二进制格式,ASCII版本整体转换后容易塌陷)或mdl(这个常见半条命反恐精英这种游戏,因为mdl是md3的儿子,转换会比较完美),如果是max请导出fbx,dae等容易被其他动画格式导出塌陷。然后用我的软件资源直接转换md3格式.

其他建议:如果源动画比较多,最好在max里先等比压缩一下关键帧数量再导出fbx等常规动画模型再转md3.  给个参考数据,单个顶点动画导入brf后的brf文件大小一般是模型面数(单位:万)x关键帧数/5~7 =。。。(单位MB),也就是打比方我的嘉然模拟器一个嘉然顶点动画模型就是接近20万面的模型x26帧数,结果到达80多兆,所以单体玩家使用的顶点动画模型你可以偶尔有个达到100兆的,但是其他ai单位最好限制在20兆以下。至于brf最大能容纳多大一个顶点动画模型,我最大塞过500兆的,但是塞之前的原始md3模型没这么大,因为塞进去后brf大小会是模型大小扩大后的3~6倍,所以一般往brf塞80兆以上的md3原始文件就容易导致brf奔溃跳出了。至于对性能的影响,这个不能抛开数量谈性能,就是哪怕你一个动画模型200兆,只要你只一个场景加载一两个,不会影响流畅,如果电脑比较好,理想情况是运行还流畅着然后很快到了内存溢出的上限c++run error,所以就看吧,你一个场景加载的这种模型总大小有没有超出1个gb,太多容易跳出。


然后是关于碰撞体设置的问题,场景物的顶点动画不会改变碰撞体,也就是场景物定义的是什么碰撞体模型,无论怎么播放动画都不会改变,所以这个碰撞体怎么设置要具体对象具体分析,比如和战团差不多的人如果采用跟随agent换皮控制的方式,可以不设实际的场景物碰撞体为空,如果是一些机械类,可以根据本身的形态简化处理,降低负担,比如坦克,你可以两个柱体重合加个杆子,避免直接按原始高面数生成碰撞体,因为场景物控制运动带来的负担受模型面数的影响,碰撞体的面数影响是远大于显示的模型外形本身的。

4.一些顶点动画模型参考实例:
我的魔兽争霸modhttps://bbs.mountblade.com.cn/thread-2094063-1-1.html和七龙珠modhttps://bbs.mountblade.com.cn/thread-2093251-1-1.html拥有骑砍界绝大部分的高帧顶点动画模型数量,包含各种生物机械装置战车飞行器以及含有顶点动画的特效模型。你在其他mod基本很少能看到这类模型,有也不超过30帧并且动作种类单一。可以参考看看,但是不要随意提取用到其他mod里.然后下面我具体代码示例的魔兽英雄模型是到第一个链接里找所有human_,orc_,nightelf_,undead_,monster_这些前缀的brf,这些一个brf装一个英雄或普通单位动画模型。然后动画特效一般是eft后缀的brf里。


二、相关op制作mod的骑砍版本最好要高于1.161,也就是你一般骑砍版本高于1.161就会得到很多新的神奇实用操作,基本满足目前特殊题材mod制作的高度和大部分mod的运行,后续版本更新的东西只是为了dlc的小补充,所以如果不用最新版本制作至少也要保证版本大于1.161


讲op前先介绍相关参数在brf里的体现:打开有顶点动画模型的brf,选中顶点动画模型看右侧面板的数据,和动画帧数有关的有两个格子的数据排列,右处为帧时刻,是下列op的value或frame要填的数据,也就是动画模型的某帧状态的控制参数,而左侧数据代表的关键帧序号,没有任何op需要这个数据,因为关键帧序号就是一个连续从0开始用于关键帧排序的序号,相连关键帧之间可以填间隔不同的帧时间,比如0号关键帧是0时刻,1号关键帧是5时刻,2号关键帧是15时刻,那么动画第1帧代表的模型形态变到第2帧所用的时间是第0帧变第1帧的2倍时间,但一般为了控制方便,宜设置间隔连续均匀。
可能大家没处理过,不了解,一般你导入做好的顶点动画模型后各帧时刻参数会均为0或者散乱不成等差数列,所以以前我这个帖子说了下如何快速让顶点动画的各帧序的帧时刻从0开始成差值为10的等差数列https://bbs.mountblade.com.cn/thread-2050522-1-1.html,假如你学会了顶点动画的制作,这个小细节不掌握也会使你在代码控制前的模型处理环节就卡住思路。

此外注意没有顶点动画的场景物也可以控制帧状态,所以这种特殊的情况可以用来还没有制作动画时随便用一个没有动画的模型先留空写好代码,以及利用顶点动画控制op是可以操作模型在一个帧时刻区间变换时限定总完成时间的特性,构造一个看不见的无动画模型将控制顶点动画来当作一个计时器来使用。但是注意控制顶点动画的场景物可以没有顶点动画但是需要有具体模型,也就是要有点线面,如果你的模型是none空的,顶点动画op强制执行到某帧时刻后你获取的当前帧时刻始终为0。


prop_instance_deform_to_time                = 2610  # (prop_instance_deform_to_time, <prop_instance_no>, <value>),
                                                    # value参数代表帧时刻,也就是prop_instance_no场景物id的场景物一次性设置到value这个帧时刻


prop_instance_deform_in_range               = 2611  # (prop_instance_deform_in_range, <prop_instance_no>, <start_frame>, <end_frame>, <duration-in-1/1000-seconds>),
                                                    # 强制场景物id<prop_instance_no>的场景物自起点帧时刻<start_frame>向终点帧时刻<end_frame>匀速变化,在<duration-in-1/1000-seconds>(单位千分之一秒)时间内完成一次动画,然后模型便停留在终点帧时刻<end_frame>的形态上。此外注意这里面控制动画变化区间的时候是可以取值到<end_frame>,不要去类比is between、try for range这些取不到终值的op,因为这个是行为操作而不是判断类操作。


prop_instance_deform_in_cycle_loop          = 2612  # (prop_instance_deform_in_cycle_loop, <prop_instance_no>, <start_frame>, <end_frame>, <duration-in-1/1000-seconds>),
                                                    # 强制场景物id<prop_instance_no>的场景物自起点帧时刻<start_frame>向终点帧时刻<end_frame>匀速变化,在<duration-in-1/1000-seconds>(单位千分之一秒)时间内完成一次动画,然后重新到<start_frame>时刻反复循环动画。也就是与上面的op区别是一个不循环动画一个循环动画,这个你们要结合骨骼动画的机理联系想想。


prop_instance_get_current_deform_progress   = 2615  # (prop_instance_get_current_deform_progress, <destination>, <prop_instance_no>),
                                                    # 获取<prop_instance_no>场景物正在用2611或2612操作播放顶点动画时,已经播放的百分比0-100取值<destination>,实际上,这个用的不多,下面的op具有等效替代作用。




prop_instance_get_current_deform_frame      = 2616  # (prop_instance_get_current_deform_frame, <destination>, <prop_instance_no>),
                                                    #获取<prop_instance_no>场景物操作播放顶点动画时,当前时点播放到的帧时刻<destination>。



该系列op功能的总体分析(为了写方便,下面以op的序号简称):
1.实际上操作号2611,2612和2616已经可以满足顶点动画控制的需求,操作号2610和2615用的场合不多并且可以被其他3个op等效操作。

2.<duration-in-1/1000-seconds>的填写与<end_frame>-<start_frame>的差值的关系有一点关系但不多,具体填多少还要看你关键帧动画变化的幅度结合实际行为,比如说同样是两个顶点动画人物的走路动画,一个步伐夸张一个步伐缓慢甚至有切变多动作,或者一个模型走路动画每10帧数动作变化幅度较明显,但另一个模型的走路动画每10帧甚至不仔细看都没怎么动作幅度,所以这两个模型一个特定动画区间的长度相等时,满足我们观感适宜的<duration-in-1/1000-seconds>值很多时候不一定相等。这个要在brf里手动播放帧数记录各行为关键帧起始终止帧时刻时看感觉心中有个估值设置好后到游戏调整。然后如果涉及到动作有被加减速动画速度的条件,比如施法加速技能,那这些<duration-in-1/1000-seconds>值还要进一步变量化控制。


3.2611和2612代表了顶点动画的不循环和循环,这个要类比骨骼动画smd特别是其标签作用,骨骼动画按照一些标签应付不同场合的需求,需要动作可以循环执行或仅执行一次,然后我们再类比下,骨骼动画强制切换动作是怎么做的,其实采用的是具有高优先级标签的动作去覆盖当前正在执行的动作,优先级高,则直接打断,优先级次一点,可能等当前动作做完续上或不打断。



所以对于同一个物体的顶点动画中两个不同区间的帧动画进行切换时,操作号2611或2612需要和2616来组合使用,比如某物体假设是一个怪兽,顶点动画总共0-400的帧时间,通过我自己的人为设定,停止发呆动作的帧时刻区间是0-100,走路是101-200(看到没有,因为动画控制可以取终值,所以这个相邻两个区间前一个终值100不可以等于后一个起始值101),攻击是201-300,死亡是301-400。所以这个也表明了大部分情况,你需要把一个顶点动画所有行为压到一个顶点动画模型里,然后记个笔记人为分分类,哪个区间是作什么行为作用的动画来使用。


这时候你们要联系实际生活和玩过的游戏来想怎么把这不同行为的动画区间控制好,首先动画是抽象行为的具体表象,所以先让总体行为指导动画的触发,比如我看到你腿在动的动画,那当前你就是在走路。则通过行为判断的条件,比如走路(先不区分前后左右跑步还是慢跑,假设上面的怪兽只有一种前进动作,其他靠转弯),那么,(key_is_down, key_W)即按着w键便是一种判断当前是否要执行走路动画的条件。然后就是停止待命动画,一般在动画领域这个动作叫idle动作,是很多动作首先要做的动画,因为你无论是走路还是攻击释放技能,最终执行完这些行为后,都要恢复idle站着等待执行其他行为或就像一些任务型人物就呆在一个地方不动,这也说明了idle是优先级最低的动作,也是几乎所有动作的中转动作行为,所以我们进行顶点动画多区间行为化的模型进行多种动画行为控制时,要先分析不同动画区间代表的不同行为优先级的排序。类似动作A在执行时动作B不执行,动作A执行完毕时如果不继续触发动作A的条件则自动切换到动作C,等等。


所以代码控制顶点动画的基本思路就是:
满足动画A(帧时刻范围在(b,c))的条件触发时,op操作号2616得到当前帧数a
如果a在(b,c)值域内,也就是你目前就是在执行A动作动画过程中,出现行为条件的改变,则判断你实际需要触发的事件本应该执行什么动作来决定如何执行2611或2612 op操作号,具体循环与否看你的事件触发条件是否是持续的还是一次性事件,比如走路和待机就是持续性事件采用2612循环动作,而非持续施法的技能和攻击行为以及死亡便是非循环单次事件要用2611,其他特殊情况特殊分析。
然后如果突然又出现了动画B(帧时刻范围在(d,e))的条件触发时,直接按照相同的套路强制执行2611或2612 操作号,打断当前执行的其他动作,或者等目前执行的单次行为动作事件执行完毕即播放到目前行为动画的尾帧时刻再执行新的动画播放。
综述就是:同一个顶点动画模型的不同帧时刻区间定义的不同动作的切换,就是靠op操作号2616得到当前帧数作为判断条件是否处于某个行为事件,再根据你实际需要触发的其他行为条件需要强制执行2611或2612 操作号去转接播放其他帧时刻区间的顶点动画,然后比较优先级,是直接打断当前动画执行还是等原来的执行完。




三、接下来我把我魔兽争霸的顶点动画人物控制代码写下,作为案例注释助大家理解下。

首先做顶点动画模型,此处制作过程省略,然后新建一个excel表做笔记

表格设置的一些解释:看我如下表格,我将我的魔兽人物目前简单定义了几个行为动作与动画的对应,停止待命idle,跑步run,前两个的特殊special状态(比如人族步兵举盾还是不举盾),atk1-double即三种攻击动作(因为玩过网易游戏的会了解,像这种moba人物不像格斗动作游戏一样,很多会采用有限普通攻击动作,具有代表性的是三段击,也就是三个动作循环,攻击力一个比一个高),skill1-4是四个技能动作,因为我大部分英雄是qwer的技能设置,laugh是嘲讽动作娱乐性作用,die是死亡动作,后面带Summoning是含有技能召唤物的比如血法师的凤凰,一般英雄没有,就会像我开头备注的文字if none anim ,control frame  89999-99999,and force it to idle一样,无效动作帧数设置89999-99999方便集中判断无效动作以idle动作代替。


然后为什么要做这样的表格呢,因为起初我做龙珠mod的时候,我采用的是每个人物都写一遍结构很相似的触发器,只不过执行动画帧区间时填的帧时刻参数不一样而已。对于很多会动的生物来说其实大家行为都差不多,人蛇昆虫鸟,都会有idle(待命)-walk/run(走/跑)-attack(攻击)-underattack(被打)-die(死)这些共同的基础动作,然后其他特有动作另写,一般优先级高于基础动作,除了死亡,死亡是优先级最高的动作,因为死了啥事都做不了。比如你释放技能时,根据你玩游戏的经验看,很多技能动作会强制打断待命走路攻击有时不执行结束技能动作还不能进行其他动作(这个一般指的即时释放的技能,持续释放的技能略有差别)


所以说对于不同的顶点动画生物控制,他们各种行为对应的动画帧区间的起点终点值抽象成一个参数、控制量、变量即可保证大部分生物都能通用一套触发器控制,然后初始化比如spawn刷出时进行赋值,把类似动画序列表的数据一次性赋值给这个场景物的sceneprop slot来储存。然后控制动画时读取这些动画帧时刻参数即可。

表格 (scene_prop_set_slot, reg0, 101, 60), 这个数据的生成我采用了“=CONCATENATE(D66,F66)”这个excel函数,目的是为了把D66格子的(scene_prop_set_slot, reg0, 101和F66格子的, 60),这两个格子的数据合并,为什么要这么写呢,是因为我要让101这个数据可以被excel向下拉的时候自动填充并+1,因为我这么多动作需要使用大量的slot存值,如果一个个手写,手都要断了,所以合理利用excel自动填充的特性来处理这种需要大量初始赋值参数的场合便极为方便高效。
魔兽人物仅仅设定了十几个通用动作的参数,龙珠是它的好几倍动作数量,比较复杂,所以下面仅仅以我魔兽争霸mod的动作设定来作为参考例:


表格如下:


---------------------------------------------------------------------------------------------------------------

if none anim ,control frame  89999-99999,and force it to idle
but if atk only one anim,other atk frame set the same
grovekeeper-树林守护者war3grovekeeper-树林守护者dota老鹿none-原始模板备份
以下写了英文的是动作行为名称,每个动作存动画区间的起始和尾帧时刻参数,如idle待机动作的101slot代表起始帧时刻,102代表尾帧时刻动作分布
1
2
3
1
2
idle(scene_prop_set_slot, reg0, 101
, 60),, 60),, 0),(scene_prop_set_slot, reg0, 101
, 60),
(scene_prop_set_slot, reg0, 101
, 60),
(scene_prop_set_slot, reg0, 102
, 390),, 390),, 0),(scene_prop_set_slot, reg0, 102
, 390),
(scene_prop_set_slot, reg0, 102
, 390),
idle—special(scene_prop_set_slot, reg0, 103
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 103
, 89999),
(scene_prop_set_slot, reg0, 103
, 89999),
(scene_prop_set_slot, reg0, 104
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 104
, 99999),
(scene_prop_set_slot, reg0, 104
, 99999),
run(scene_prop_set_slot, reg0, 105
, 660),, 660),, 0),(scene_prop_set_slot, reg0, 105
, 660),
(scene_prop_set_slot, reg0, 105
, 660),
(scene_prop_set_slot, reg0, 106
, 760),, 760),, 0),(scene_prop_set_slot, reg0, 106
, 760),
(scene_prop_set_slot, reg0, 106
, 760),
run—special(scene_prop_set_slot, reg0, 107
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 107
, 89999),
(scene_prop_set_slot, reg0, 107
, 89999),
(scene_prop_set_slot, reg0, 108
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 108
, 99999),
(scene_prop_set_slot, reg0, 108
, 99999),
atk1(scene_prop_set_slot, reg0, 109
, 1340),, 1340),, 0),(scene_prop_set_slot, reg0, 109
, 1340),
(scene_prop_set_slot, reg0, 109
, 1340),
(scene_prop_set_slot, reg0, 110
, 1590),, 1590),, 0),(scene_prop_set_slot, reg0, 110
, 1590),
(scene_prop_set_slot, reg0, 110
, 1590),
atk2(scene_prop_set_slot, reg0, 111
, 1340),, 1340),, 0),(scene_prop_set_slot, reg0, 111
, 1340),
(scene_prop_set_slot, reg0, 111
, 1340),
(scene_prop_set_slot, reg0, 112
, 1590),, 1590),, 0),(scene_prop_set_slot, reg0, 112
, 1590),
(scene_prop_set_slot, reg0, 112
, 1590),
atk double(scene_prop_set_slot, reg0, 113
, 1340),, 1340),, 0),(scene_prop_set_slot, reg0, 113
, 1340),
(scene_prop_set_slot, reg0, 113
, 1340),
(scene_prop_set_slot, reg0, 114
, 1590),, 1590),, 0),(scene_prop_set_slot, reg0, 114
, 1590),
(scene_prop_set_slot, reg0, 114
, 1590),
skill1(scene_prop_set_slot, reg0, 115
, 400),, 400),, 0),(scene_prop_set_slot, reg0, 115
, 400),
(scene_prop_set_slot, reg0, 115
, 400),
(scene_prop_set_slot, reg0, 116
, 650),, 650),, 0),(scene_prop_set_slot, reg0, 116
, 650),
(scene_prop_set_slot, reg0, 116
, 650),
skill2(scene_prop_set_slot, reg0, 117
, 2730),, 2730),, 0),(scene_prop_set_slot, reg0, 117
, 2730),
(scene_prop_set_slot, reg0, 117
, 2730),
(scene_prop_set_slot, reg0, 118
, 2990),, 2990),, 0),(scene_prop_set_slot, reg0, 118
, 2990),
(scene_prop_set_slot, reg0, 118
, 2990),
skill3(scene_prop_set_slot, reg0, 119
, 2400),, 2400),, 0),(scene_prop_set_slot, reg0, 119
, 2400),
(scene_prop_set_slot, reg0, 119
, 2400),
(scene_prop_set_slot, reg0, 120
, 2720),, 2720),, 0),(scene_prop_set_slot, reg0, 120
, 2720),
(scene_prop_set_slot, reg0, 120
, 2720),
skill4(scene_prop_set_slot, reg0, 121
, 2400),, 2400),, 0),(scene_prop_set_slot, reg0, 121
, 2400),
(scene_prop_set_slot, reg0, 121
, 2400),
(scene_prop_set_slot, reg0, 122
, 2720),, 2720),, 0),(scene_prop_set_slot, reg0, 122
, 2720),
(scene_prop_set_slot, reg0, 122
, 2720),
laugh(scene_prop_set_slot, reg0, 123
, 2400),, 2400),, 0),(scene_prop_set_slot, reg0, 123
, 2400),
(scene_prop_set_slot, reg0, 123
, 2400),
(scene_prop_set_slot, reg0, 124
, 2720),, 2720),, 0),(scene_prop_set_slot, reg0, 124
, 2720),
(scene_prop_set_slot, reg0, 124
, 2720),
die(scene_prop_set_slot, reg0, 125
, 770),, 770),, 0),(scene_prop_set_slot, reg0, 125
, 770),
(scene_prop_set_slot, reg0, 125
, 770),
(scene_prop_set_slot, reg0, 126
, 1330),, 1330),, 0),(scene_prop_set_slot, reg0, 126
, 1330),
(scene_prop_set_slot, reg0, 126
, 1330),
Summoning-idle(scene_prop_set_slot, reg0, 127
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 127
, 89999),
(scene_prop_set_slot, reg0, 127
, 89999),
(scene_prop_set_slot, reg0, 128
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 128
, 99999),
(scene_prop_set_slot, reg0, 128
, 99999),
Summoning-run(scene_prop_set_slot, reg0, 129
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 129
, 89999),
(scene_prop_set_slot, reg0, 129
, 89999),
(scene_prop_set_slot, reg0, 130
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 130
, 99999),
(scene_prop_set_slot, reg0, 130
, 99999),
Summoning-atk(scene_prop_set_slot, reg0, 131
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 131
, 89999),
(scene_prop_set_slot, reg0, 131
, 89999),
(scene_prop_set_slot, reg0, 132
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 132
, 99999),
(scene_prop_set_slot, reg0, 132
, 99999),
Summoning-idle(scene_prop_set_slot, reg0, 133
, 89999),, 89999),, 89999),(scene_prop_set_slot, reg0, 133
, 89999),
(scene_prop_set_slot, reg0, 133
, 89999),
(scene_prop_set_slot, reg0, 134
, 99999),, 99999),, 99999),(scene_prop_set_slot, reg0, 134
, 99999),
(scene_prop_set_slot, reg0, 134
, 99999),
(scene_prop_set_slot, reg0, 135
, 5000),, 5000),, 5000),(scene_prop_set_slot, reg0, 135
, 5000),
(scene_prop_set_slot, reg0, 135
, 5000),
(scene_prop_set_slot, reg0, 136
, 3600),, 3600),, 2400),(scene_prop_set_slot, reg0, 136
, 3600),
(scene_prop_set_slot, reg0, 136
, 3600),
(scene_prop_set_slot, reg0, 137
, 3600),, 3600),, 2400),(scene_prop_set_slot, reg0, 137
, 3600),
(scene_prop_set_slot, reg0, 137
, 3600),
(scene_prop_set_slot, reg0, 138
, 1200),, 1200),, 1200),(scene_prop_set_slot, reg0, 138
, 1200),
(scene_prop_set_slot, reg0, 138
, 1200),
(scene_prop_set_slot, reg0, 139
, 1200),, 1200),, 600),(scene_prop_set_slot, reg0, 139
, 1200),
(scene_prop_set_slot, reg0, 139
, 1200),
(scene_prop_set_slot, reg0, 140
, 1200),, 1200),, 800),(scene_prop_set_slot, reg0, 140
, 1200),
(scene_prop_set_slot, reg0, 140
, 1200),
(scene_prop_set_slot, reg0, 141
, 1200),, 1200),, 800),(scene_prop_set_slot, reg0, 141
, 1200),
(scene_prop_set_slot, reg0, 141
, 1200),
(scene_prop_set_slot, reg0, 142
, 2000),, 2000),, 5000),(scene_prop_set_slot, reg0, 142
, 2000),
(scene_prop_set_slot, reg0, 142
, 2000),
(scene_prop_set_slot, reg0, 143
, 2000),, 2000),, 2000),(scene_prop_set_slot, reg0, 143
, 2000),
(scene_prop_set_slot, reg0, 143
, 2000),
(scene_prop_set_slot, reg0, 144
, 300),, 300),, 50),(scene_prop_set_slot, reg0, 144
, 300),
(scene_prop_set_slot, reg0, 144
, 300),
(scene_prop_set_slot, reg0, 145
, 50),, 50),, 50),(scene_prop_set_slot, reg0, 145
, 50),
(scene_prop_set_slot, reg0, 145
, 50),
(scene_prop_set_slot, reg0, 146
, 300),, 300),, 50),(scene_prop_set_slot, reg0, 146
, 300),
(scene_prop_set_slot, reg0, 146
, 300),
(scene_prop_set_slot, reg0, 147
, 300),, 300),, 250),(scene_prop_set_slot, reg0, 147
, 300),
(scene_prop_set_slot, reg0, 147
, 300),

关于135以后slot含义表格漏了,另外附下:

idle动画基础速度(scene_prop_set_slot, reg0, 135
run动画基础速度(scene_prop_set_slot, reg0, 136
atk动画基础速度(scene_prop_set_slot, reg0, 137
sk1动画基础速度(scene_prop_set_slot, reg0, 138
sk2动画基础速度(scene_prop_set_slot, reg0, 139
sk3动画基础速度(scene_prop_set_slot, reg0, 140
sk4动画基础速度(scene_prop_set_slot, reg0, 141
laugh动画基础速度(scene_prop_set_slot, reg0, 142
die动画基础速度(scene_prop_set_slot, reg0, 143
效果持续时间1(scene_prop_set_slot, reg0, 144
效果持续时间2(scene_prop_set_slot, reg0, 145
效果持续时间3(scene_prop_set_slot, reg0, 146
效果持续时间4(scene_prop_set_slot, reg0, 147
---------------------------------------------------------------------------------------------------------------
上面这些表格的内容在刷出顶点动画人物后把类似(scene_prop_set_slot, reg0, 101, 60),结构的所有竖行都复制过去,进行初始化存数据,然后以下涉及镜头控制、stoprun变量控制的dynamic强制停止位移,aaa变量控制的rts等等参数的变化和控制代码写在其他触发器, 因为有很多配套代码要阉割出来比较麻烦,所以有些东西就下面的主体动画控制触发器里注释简单提及一下,不写出来了,主要提供最主要的动画控制代码的一个触发器(脚本)给大家看个整体思路:
以下添加到module_mission_templates.PY需要的场景里,比如lead charge 野战,或者直接全部脚本化后每个场景触发器都引用一遍:
条件推荐0.00000,0.00000,0.00000
(set_fixed_point_multiplier, 1000),
(store_add, ":var_0", "$heroswitch", 647),                                 
(troop_get_slot, ":var_1", "trp_player", ":var_0"),             #以上表示:var_0这个是由$heroswitch决定的我不同的可选魔兽英雄的操作序号,形成了slot序号,由trp_player troop slot 此序号提前在其他触发器存储了英雄的顶点动画场景物的spr id,设为:var_1
(scene_prop_get_num_instances, ":var_2", ":var_1"),            
(eq, ":var_2", 1),                                                   #英雄顶点动画模型数量为1时开始执行,在其他触发器里面集中执行了战斗场景应该刷出玩家选择的什么英雄对应的场景物模型
(get_player_agent_no, ":var_3"),
(agent_get_troop_id, ":var_4", ":var_3"),
(agent_get_position, pos15, ":var_3"),
(agent_get_team, ":var_5", ":var_3"),
(store_agent_hit_points, ":var_6", ":var_3", 0),
(scene_prop_get_instance, ":var_7", ":var_1", 0),         #代表了玩家换皮顶点动画场景物的魔兽英雄模型,单体实例id设为:var_7
(scene_prop_get_instance, ":var_8", "spr_plpoint", 0),    #含有跳动动画的光标模型,表示rts模式的人物选中状态,玩家和ai都有这个东西,在我其他触发器初始化时刷出的,本贴触发器省略不写
(prop_instance_get_position, pos2, ":var_7"),                  #代码块1-用于获取玩家当前位置到RTS控制需要去的目的地(scripted_destination)的位置水平投影的间距,用于下面判断RTS模式($aaa为1或2时)是采用走路还是待命顶点动画动作的判定
(prop_instance_get_position, pos5, ":var_7"),
(agent_get_scripted_destination, pos6, ":var_3"),          #你们可能奇怪为什么玩家也可以用这个op,虽然玩家的移动行为一般情况是靠wasd,但是你set_scripted_destination到一个pos然后用get_scripted_destination是可以获取到这个pos的                                                                                                                                                                                                              #,或者换个说法,假如你按作弊ctrl+f5系统托管玩家控制,玩家就可以响应set_scripted_destination到脚本目的地,所以玩家有scripted_destination的作用,但是一般情况会被wasd等基础系统机制覆盖效果。
(position_set_z, pos5, 0),                                             #为了只获取水平投影的间距,z坐标统一设0
(position_set_z, pos6, 0),
(get_distance_between_positions, ":var_9", pos5, pos6),      #代码块1-结束
(agent_get_position, pos1, ":var_3"),
(2616, ":var_10", ":var_7"),                                         #获取英雄顶点动画模型当前运行到的帧时刻,因为我txt做mod,习惯用数字表示这一系列的操作号。
(agent_get_attack_action, ":var_11", ":var_3"),
(agent_get_simple_behavior, ":var_12", ":var_3"),
(store_random_in_range, ":var_13", 0, 1000),              #这个随机数很下面的try for agents里的代码会用到,是顶点动画三种不同攻击动作的概率
(try_begin),
    (agent_slot_eq, ":var_3", 333, 0),        #玩家agent slot333号代表了这个英雄有没有额外的运动控制,如果没有,即slot为0时,常规情况英雄顶点动画模型和头顶表示人物选中的光标模型将始终设置于玩家agent的位置上,因为其他触发器设定了玩家agent影身,所以用顶点动画场景物的形象和动作代表了玩家控制的新形象和动作行为
    (prop_instance_set_position, ":var_7", pos15),
    (prop_instance_set_position, ":var_8", pos15),
(try_end),
(agent_get_slot, ":var_14", ":var_3", 500),         #代码块2-slot503-506代表了技能的持续时间进程控制,slot501代表了移动动画播放速度的变速控制影响量(比如受技能改变加速)在其他触发器默认初始化设为4,slot502代表了攻击动画播放速度的变速控制影响量(比如受技能改变加速)在其他触发器默认初始化设为4slot500已经废弃,原本是控制攻击力变化的,后来换了算法
(agent_get_slot, ":var_15", ":var_3", 501),
(agent_get_slot, ":var_16", ":var_3", 502),
(agent_get_slot, ":var_17", ":var_3", 503),
(agent_get_slot, ":var_18", ":var_3", 504),
(agent_get_slot, ":var_19", ":var_3", 505),
(agent_get_slot, ":var_20", ":var_3", 506),                   #代码块2-结束
(scene_prop_get_slot, ":var_21", ":var_7", 101),            #代码块3-看我上面附的大表格,是用来获取英雄顶点动画模型包含的各个行为动作的动画起点终点帧时刻数以及动作持续时间技能持续时间已经在其他触发器初始化存好到各个prop slot的参数
(scene_prop_get_slot, ":var_22", ":var_7", 102),
(scene_prop_get_slot, ":var_23", ":var_7", 103),
(scene_prop_get_slot, ":var_24", ":var_7", 104),
(scene_prop_get_slot, ":var_25", ":var_7", 105),
(scene_prop_get_slot, ":var_26", ":var_7", 106),
(scene_prop_get_slot, ":var_27", ":var_7", 107),
(scene_prop_get_slot, ":var_28", ":var_7", 108),
(scene_prop_get_slot, ":var_29", ":var_7", 109),
(scene_prop_get_slot, ":var_30", ":var_7", 110),
(scene_prop_get_slot, ":var_31", ":var_7", 111),
(scene_prop_get_slot, ":var_32", ":var_7", 112),
(scene_prop_get_slot, ":var_33", ":var_7", 113),
(scene_prop_get_slot, ":var_34", ":var_7", 114),
(scene_prop_get_slot, ":var_35", ":var_7", 115),
(scene_prop_get_slot, ":var_36", ":var_7", 116),
(scene_prop_get_slot, ":var_37", ":var_7", 117),
(scene_prop_get_slot, ":var_38", ":var_7", 118),
(scene_prop_get_slot, ":var_39", ":var_7", 119),
(scene_prop_get_slot, ":var_40", ":var_7", 120),
(scene_prop_get_slot, ":var_41", ":var_7", 121),
(scene_prop_get_slot, ":var_42", ":var_7", 122),
(scene_prop_get_slot, ":var_43", ":var_7", 123),
(scene_prop_get_slot, ":var_44", ":var_7", 124),
(scene_prop_get_slot, ":var_45", ":var_7", 125),
(scene_prop_get_slot, ":var_46", ":var_7", 126),
(scene_prop_get_slot, ":var_47", ":var_7", 127),
(scene_prop_get_slot, ":var_48", ":var_7", 128),
(scene_prop_get_slot, ":var_49", ":var_7", 129),
(scene_prop_get_slot, ":var_50", ":var_7", 130),
(scene_prop_get_slot, ":var_51", ":var_7", 131),
(scene_prop_get_slot, ":var_52", ":var_7", 132),
(scene_prop_get_slot, ":var_53", ":var_7", 133),
(scene_prop_get_slot, ":var_54", ":var_7", 134),
(scene_prop_get_slot, ":var_55", ":var_7", 135),
(scene_prop_get_slot, ":var_56", ":var_7", 136),
(scene_prop_get_slot, ":var_57", ":var_7", 137),
(scene_prop_get_slot, ":var_58", ":var_7", 138),
(scene_prop_get_slot, ":var_59", ":var_7", 139),
(scene_prop_get_slot, ":var_60", ":var_7", 140),
(scene_prop_get_slot, ":var_61", ":var_7", 141),
(scene_prop_get_slot, ":var_62", ":var_7", 142),
(scene_prop_get_slot, ":var_63", ":var_7", 143),
(scene_prop_get_slot, ":var_64", ":var_7", 144),
(scene_prop_get_slot, ":var_65", ":var_7", 145),
(scene_prop_get_slot, ":var_66", ":var_7", 146),
(scene_prop_get_slot, ":var_67", ":var_7", 147),            #代码块3-结束
(troop_get_slot, ":var_68", "trp_player", 729),
(troop_get_slot, ":var_69", "trp_player", 730),
(troop_get_slot, ":var_70", "trp_player", 731),
(troop_get_slot, ":var_71", "trp_player", 732),          #以上trp slot729-732分别代表了不同伤害的定义值,写在其他触发器,了解含义即可,比如729代表普通攻击伤害,后面三个是有关技能的伤害
(try_begin),                                                   #代码块4-以下有4个相似的代码块,用来处理503-506agent slot代表的qwer四个英雄技能持续时间进程控制,比如503agentslot值由0变1则开始触发效果,在0到prop144号slot取值之间的区间进行持续+1变化,到峰值归0终止效果。
    (eq, ":var_17", 0),
    (eq, "$ccd1", 2),
    (agent_slot_eq, ":var_3", 307, 0),
    (agent_set_slot, ":var_3", 503, 1),
(else_try),
    (is_between, ":var_17", 1, ":var_64"),
    (val_add, ":var_17", 1),
    (try_begin),
        (eq, ":var_17", 3),
        (str_store_troop_name, s15, ":var_4"),
        (str_store_item_name, s16, "itm_wardenskilll"),
        (display_message, "str_showskill"),
    (try_end),
    (agent_set_slot, ":var_3", 503, ":var_17"),
(else_try),
    (eq, ":var_17", ":var_64"),
    (agent_set_slot, ":var_3", 503, 0),
    (str_store_troop_name, s15, ":var_4"),
    (str_store_item_name, s16, "itm_wardenskilll"),
    (display_message, "str_diskill"),
(try_end),
(try_begin),
    (eq, ":var_18", 0),
    (eq, "$ccd2", 2),
    (agent_slot_eq, ":var_3", 307, 0),
    (agent_set_slot, ":var_3", 504, 1),
(else_try),
    (is_between, ":var_18", 1, ":var_65"),
    (val_add, ":var_18", 1),
    (try_begin),
        (eq, ":var_18", 3),
        (str_store_troop_name, s15, ":var_4"),
        (str_store_item_name, s16, "itm_wardenskill2"),
        (display_message, "str_showskill"),
    (try_end),
    (agent_set_slot, ":var_3", 504, ":var_18"),
(else_try),
    (eq, ":var_18", ":var_65"),
    (agent_set_slot, ":var_3", 504, 0),
    (str_store_troop_name, s15, ":var_4"),
    (str_store_item_name, s16, "itm_wardenskill2"),
    (display_message, "str_diskill"),
(try_end),
(try_begin),
    (eq, ":var_19", 0),
    (eq, "$ccd3", 2),
    (agent_slot_eq, ":var_3", 307, 0),
    (agent_set_slot, ":var_3", 505, 1),
(else_try),
    (is_between, ":var_19", 1, ":var_66"),
    (val_add, ":var_19", 1),
    (try_begin),
        (eq, ":var_19", 3),
        (str_store_troop_name, s15, ":var_4"),
        (str_store_item_name, s16, "itm_wardenskill3"),
        (display_message, "str_showskill"),
    (try_end),
    (agent_set_slot, ":var_3", 505, ":var_19"),
(else_try),
    (eq, ":var_19", ":var_66"),
    (agent_set_slot, ":var_3", 505, 0),
    (str_store_troop_name, s15, ":var_4"),
    (str_store_item_name, s16, "itm_wardenskill3"),
    (display_message, "str_diskill"),
(try_end),                                                                                   
(try_begin),
    (eq, ":var_20", 0),
    (eq, "$ccd4", 2),
    (agent_slot_eq, ":var_3", 307, 0),
    (agent_set_slot, ":var_3", 506, 1),
(else_try),
    (is_between, ":var_20", 1, ":var_67"),
    (val_add, ":var_20", 1),
    (try_begin),
        (eq, ":var_20", 3),
        (str_store_troop_name, s15, ":var_4"),
        (str_store_item_name, s16, "itm_wardenskill4"),
        (display_message, "str_showskill"),
    (try_end),
    (agent_set_slot, ":var_3", 506, ":var_20"),
(else_try),
    (eq, ":var_20", ":var_67"),
    (str_store_troop_name, s15, ":var_4"),
    (str_store_item_name, s16, "itm_wardenskill4"),
    (display_message, "str_diskill"),
    (agent_set_slot, ":var_3", 506, 0),
(try_end),                                                                      #代码块5-结束
(store_div, ":var_72", 400, ":var_14"),                           #原先代表攻击力调整,现废除无用
(store_div, ":var_73", ":var_56", ":var_15"),                #调整移动动画速度的基础变化,:var_56是propslot136号的基础赋值,":var_15"是agentslot501号的赋值作为速度调节器类似modified类op的效果
(store_div, ":var_74", ":var_57", ":var_16"),                  #调整攻击动画速度的基础变化,:var_57是propslot137号的基础赋值,":var_16"是agentslot502号的赋值作为速度调节器类似modified类op的效果
(try_begin),                                                    #代码块6-控制玩家不进行除待机走路以外的动作时,控制待机走路这两个动作触发的条件和优先级关系
    (neg|gt, ":var_10", ":var_30"),                               # 判断当前是否处于攻击1号动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_29"),
(else_try),
    (neg|gt, ":var_10", ":var_32"),                            # 判断当前是否处于攻击2号动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_31"),
(else_try),                                                         
    (neg|gt, ":var_10", ":var_34"),                         # 判断当前是否处于攻击3号动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_33"),
(else_try),
    (neg|gt, ":var_10", ":var_36"),                            # 判断当前是否处于1技能动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_35"),
(else_try),
    (neg|gt, ":var_10", ":var_38"),                         # 判断当前是否处于2技能动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_37"),
(else_try),
    (neg|gt, ":var_10", ":var_40"),                          # 判断当前是否处于3技能动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_39"),
(else_try),
    (neg|gt, ":var_10", ":var_42"),                         # 判断当前是否处于4技能动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_41"),
(else_try),
    (neg|gt, ":var_10", ":var_44"),                # 判断当前是否处于嘲讽动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_43"),
(else_try),
    (neg|gt, ":var_10", ":var_46"),                  #判断当前是否处于死亡动作动画区间内作为条件反向筛选
    (ge, ":var_10", ":var_45"),
(else_try),                                                   #对如上非待机走路行为动作的条件判断转折后,剩下的条件便是为待机走路这两个动作行为的条件,以此接下来开始对待机走路这两个动作进行更细的区别控制
    (try_begin),
        (neg|eq, "$aaa", 0),                             #$aaa是我用来控制RTS鼠标框选点击地面移动机制的判断条件,不为0则是RTS模式,了解即可,本贴暂时不提供魔兽RTS操作代码。
        (try_begin),
            (ge, ":var_9", 100),                           #:var_9是我开头写的玩家当前位置与脚本强制命令走动到目的地目标的位置的水平投影间距,因为rts控制移动就不是靠wasd按键条件,所以要判断此刻和下一刻玩家的位移变化值来判断玩家是否想要移动还是静止待命。
            (try_begin),
                (neg|gt, ":var_10", ":var_26"),            
                (ge, ":var_10", ":var_25"),
            (else_try),
                (2612, ":var_7", ":var_25", ":var_26", ":var_73"),   #以上表示:var_10就是op2616操作号获取的英雄顶点动画场景物的当前动画帧数,如果当前帧数不在(:var_25,:var_26)这个走动动画的帧时刻区间,则直接op2612操作号强制场景物运行(:var_25,:var_26)区间的循环顶点动画。
            (try_end),
        (else_try),
            (neg|ge, ":var_9", 100),                        
            (try_begin),
                (neg|gt, ":var_10", ":var_22"),
                (ge, ":var_10", ":var_21"),
            (else_try),
                (2612, ":var_7", ":var_21", ":var_22", ":var_55"),     #以上表示:var_10就是op2616操作号获取的英雄顶点动画场景物的当前动画帧数,如果当前帧数不在(:var_21,:var_22)这个待机动画的帧时刻区间,则直接op2612操作号强制场景物运行(:var_21,:var_22)区间的循环顶点动画。
            (try_end),
        (try_end),
    (else_try),
        (eq, "$aaa", 0),                       #$aaa是我用来控制RTS鼠标框选点击地面移动机制的判断条件,为0则是正常的第三/一人称视角模式
        (try_begin),
            (this_or_next|key_is_down, key_w),            #第三/一人称视角模式,如果图方便借用原本的位移机制换皮,则wasd按键控制便是触发走路动画的条件,但是我根据我的需求,moba英雄没有后退行为,所以屏蔽了s按键,并在下方的$stoprun变量判断此情况玩家不会因为按了s二移动
            (this_or_next|key_is_down, key_a),
            (key_is_down, key_d),
            (neg|key_is_down, key_s),
            (try_begin),                                          
                (neg|gt, ":var_10", ":var_26"),
                (ge, ":var_10", ":var_25"),
            (else_try),
                (2612, ":var_7", ":var_25", ":var_26", ":var_73"),
            (try_end),
        (else_try),
            (try_begin),
                (neg|gt, ":var_10", ":var_22"),
                (ge, ":var_10", ":var_21"),
            (else_try),
                (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
            (try_end),                                                              #以上和$aaa不等于0时类似,$aaa为0时,按wasd按键条件区分什么时候用走路动画,什么时候用待机动画
        (try_end),
    (try_end),
(try_end),
(try_begin),                                                       #以下到并列的try end 是对技能和嘲讽动作行为控制
    (neg|gt, ":var_10", ":var_46"),
    (ge, ":var_10", ":var_45"),                               #以上两行是为了判断死亡动作的情况,进而写下面非死亡动作条件的技能动作事件,为什么不判断上面走路和待机的动作条件,是因为我认定技能动作优先级要比走路待机以及下面的攻击事件要高。
(else_try),                          
    (try_begin),                                                      
        (key_clicked, key_left_alt),                #对嘲讽动作事件的控制,按key_left_alt即左边的alt键将按下面执行动画
        (try_begin),
            (neg|gt, ":var_10", ":var_44"),
            (ge, ":var_10", ":var_43"),
        (else_try),
            (2611, ":var_7", ":var_43", ":var_44", ":var_62"),
        (try_end),                                                    #以上表示当前是否当前帧时刻:var_10处于(:var_43,:var_44)这个嘲讽动画的帧时刻区间,不在就执行一遍(:var_43,:var_44)区间的顶点动画(不循环用2611,因为对于这个动作以及下面的技能动作,按键一次只触发一次)
    (else_try),                                                      
        (eq, ":var_10", ":var_44"),                                          #所以为什么我上面要用2611,嘲讽动作判断动作执行完成一次终止回归到待机动作,因为如果是采用2612循环,在到动画时刻:var_44时会很快循环重置到起始帧时刻:var_43,导致(eq, ":var_10", ":var_44"), 常常来不及检测到这个终值。
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),          #和上一行条件组合判断执行表示当前是否当前帧时刻:var_10处于:var_44这个嘲讽动画的帧时刻的终点时刻,就执行(:var_21,:var_22)这个待机动画的帧时刻区间进行循环动画,
    (try_end),      
    (try_begin),         #代码块7-ccd1是一技能触发的条件,类比上面嘲讽动作触发的定义,因为一些其他触发条件导致ccd1为1开始执行一次一技能动作动画,执行完后回归待机动作动画,ccd1是一个变化的量,本代码不涉及到,在我其他触发器后会根据技能的cd长短从1循环到一定值后归0
        (eq, "$ccd1", 1),
        (stop_all_sounds, 1),
        (play_sound_at_position, "snd_juggw", pos15),
        (try_begin),
            (neg|gt, ":var_10", ":var_36"),
            (ge, ":var_10", ":var_35"),
        (else_try),
            (2611, ":var_7", ":var_35", ":var_36", ":var_58"),
        (try_end),
    (else_try),
        (eq, ":var_10", ":var_36"),
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (try_end),                                                               #代码块7-结束
    (try_begin),
        (eq, "$ccd2", 1),
        (stop_all_sounds, 1),
        (play_sound_at_position, "snd_juggw", pos15),
        (try_begin),
            (neg|gt, ":var_10", ":var_38"),
            (ge, ":var_10", ":var_37"),
        (else_try),
            (2611, ":var_7", ":var_37", ":var_38", ":var_59"),
        (try_end),
    (else_try),
        (eq, ":var_10", ":var_38"),
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (try_end),                                                                          #以上表示二技能的动作动画控制,参考我上面的嘲讽动作和一技能动作代码注释的解释理解,其中$ccd2用于控制二技能的触发和cd,其值的变化写在其他触发器上
    (try_begin),
        (eq, "$ccd3", 1),
        (stop_all_sounds, 1),
        (play_sound_at_position, "snd_juggw", pos15),
        (try_begin),
            (neg|gt, ":var_10", ":var_40"),
            (ge, ":var_10", ":var_39"),
        (else_try),
            (2611, ":var_7", ":var_39", ":var_40", ":var_60"),
        (try_end),
    (else_try),
        (eq, ":var_10", ":var_40"),
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (try_end),                                         #以上表示三技能的动作动画控制,参考我上面的嘲讽动作和一技能动作代码注释的解释理解,其中$ccd3用于控制三技能的触发和cd,其值的变化写在其他触发器上
    (try_begin),
        (eq, "$ccd4", 1),
        (stop_all_sounds, 1),
        (play_sound_at_position, "snd_juggw", pos15),
        (try_begin),
            (neg|gt, ":var_10", ":var_42"),
            (ge, ":var_10", ":var_41"),
        (else_try),
            (2611, ":var_7", ":var_41", ":var_42", ":var_61"),
        (try_end),
    (else_try),
        (eq, ":var_10", ":var_42"),
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (try_end),                                                                                  #以上表示四技能的动作动画控制,参考我上面的嘲讽动作和一技能动作代码注释的解释理解,其中$ccd4用于控制四技能的触发和cd,其值的变化写在其他触发器上
(try_end),
(try_for_agents, ":var_75"),                                       #以下到同级的try end 为对攻击动画和新攻击判断事件的控制
    (agent_is_alive, ":var_75"),
    (agent_is_human, ":var_75"),
    (agent_get_team, ":var_76", ":var_75"),
    (neg|eq, ":var_75", ":var_3"),
    (neg|eq, ":var_76", ":var_5"),
    (neg|eq, ":var_76", 5),
    (neg|eq, ":var_76", 6),                               #以上表示攻击的对象不是玩家自己和自己阵营的人,且不是team编号5、6的人(因为team5,6我有其他中立的作用)
    (agent_get_position, pos10, ":var_75"),
    (copy_position, pos11, pos2),
    (position_move_y, pos11, -10),
    (copy_position, pos12, pos2),
    (position_move_y, pos12, 10),
    (get_distance_between_positions, ":var_77", pos11, pos10),
    (get_distance_between_positions, ":var_78", pos12, pos10),         #以上表示获取英雄场景物的坐标pos2(开头定义的比较远往上翻翻可以看到)前面10cm的位置和后面10cm的位置分别与循环的潜在攻击对象:var_75agent位置的距离
    (try_begin),
        (neg|eq, "$aaa", 0),
        (neg|ge, ":var_77", ":var_78"),         #如果是RTS模式,":var_78"大于":var_77",说明玩家自身前面的坐标位置到攻击对象的位置的距离要大于自身后面的坐标位置到攻击对象的位置的距离,这说明这个条件筛选的是敌人是否处于玩家身后的位置,因为这个是反向筛选条件,我们需要判断攻击的对象应该是玩家面前的人,所以先判断身后的目标else排除一下,其实也可以用in sight 和behind之类的操作op,但是这样判断在执行频率比较高但对判断事物是面向范围但不需要判断是否正对的时候会更省系统负担
    (else_try),
        (neg|eq, "$aaa", 0),                          
        (ge, ":var_77", ":var_78"),
        (neg|is_between, ":var_78", 50, 180),      #结合上一个else条件判断,这个是为了筛掉RTS模式下虽然在自身面前但是距离过近和过远的敌人,即在面前距离(50cm,180cm)范围的敌人,进而避免隔空打人或穿模模型重合打人的情况
    (else_try),
        (eq, "$aaa", 0),
        (neg|key_is_down, key_left_mouse_button),   #判断非RTS模式玩家没有按鼠标左键,else反向筛掉这个条件就是我希望非RTS模式按鼠标左键时可以触发顶点动画的攻击动画
    (else_try),
        (neg|eq, "$aaa", 0),
        (neg|key_is_down, key_left_control),         #判断RTS模式玩家没有按左ctrl键,else反向筛掉这个条件就是我希望RTS模式按左ctrl键时可以触发顶点动画的攻击动画
    (else_try),
        (try_begin),
            (neg|gt, ":var_10", ":var_30"),
            (ge, ":var_10", ":var_29"),
        (else_try),
            (neg|gt, ":var_10", ":var_32"),
            (ge, ":var_10", ":var_31"),
        (else_try),
            (neg|gt, ":var_10", ":var_34"),
            (ge, ":var_10", ":var_33"),
        (else_try),
            (neg|gt, ":var_10", ":var_36"),
            (ge, ":var_10", ":var_35"),
        (else_try),
            (neg|gt, ":var_10", ":var_38"),
            (ge, ":var_10", ":var_37"),
        (else_try),
            (neg|gt, ":var_10", ":var_40"),
            (ge, ":var_10", ":var_39"),
        (else_try),
            (neg|gt, ":var_10", ":var_42"),
            (ge, ":var_10", ":var_41"),
        (else_try),
            (neg|gt, ":var_10", ":var_44"),
            (ge, ":var_10", ":var_43"),
        (else_try),
            (neg|gt, ":var_10", ":var_46"),
            (ge, ":var_10", ":var_45"),
        (else_try),                                                      #上面一堆else看我判断待机走路的代码注释,为了判断当前没有处于死亡攻击技能嘲讽这些动作行为,也就是动作优先级死亡>技能&嘲讽>攻击>待机&走路
            (troop_slot_eq, "trp_player", 705, 1),           #这个705号trp slot是为了判断我当前有没有使用附身小兵并重新采用战团骨骼动画的判定,主体代码不在本触发器,了解意思即可
        (else_try),
            (try_begin),
                (is_between, ":var_13", 0, 400),
                (2611, ":var_7", ":var_29", ":var_30", ":var_74"),
            (else_try),
                (is_between, ":var_13", 400, 800),
                (2611, ":var_7", ":var_31", ":var_32", ":var_74"),
            (else_try),
                (is_between, ":var_13", 800, 1000),
                (2611, ":var_7", ":var_33", ":var_34", ":var_74"),
            (try_end),                                                      #以上表示一定概率条件下,即把":var_13"随机数在0-1000的取值按4:4:2划分概率区间,分别用来触发三种不同的攻击动作,因为我上面的else屏蔽了攻击动画的条件,所以这个触发攻击动作后一定会等待攻击动作执行完毕一次后才能触发下一次攻击动作,不会因为狂点鼠标而鬼畜从动画中间打断攻击重置。
        (try_end),
    (try_end),
    (this_or_next|eq, ":var_10", ":var_29"),
    (this_or_next|eq, ":var_10", ":var_31"),
    (eq, ":var_10", ":var_33"),
    (ge, ":var_77", ":var_78"),                                    
    (is_between, ":var_78", 50, 180),                           #以上是判断攻击动画执行后是否有有效攻击单位执行攻击有效伤害的条件,也就是在攻击动画帧时刻分别处于3种攻击动画任意一种的起始帧时刻时且面前范围距离自身范围(50cm,180cm)时触发
    (try_begin),
        (item_slot_eq, "itm_monkeykingbar", 308, 0),             #没有装备金箍棒被动时,itemslot308用来判断是否装备此物品并可执行被动技能
        (prop_instance_get_position, pos40, ":var_7"),            
        (position_move_z, pos40, 150),
        (position_move_y, pos40, 20),
        (position_move_x, pos40, -40),
        (add_missile, ":var_3", 40, 64000, 0, 0, "itm_melee", 0),
        (position_move_x, pos40, 40),
        (add_missile, ":var_3", 40, 64000, 0, 0, "itm_melee", 0),
        (position_move_x, pos40, 40),
        (add_missile, ":var_3", 40, 64000, 0, 0, "itm_melee", 0),           #向面前发射三处无形模型的箭矢,重力比较大,会近处掉落,加上上面判断必须面向有人且(50cm,180cm)距离范围才会触发,所以会近似打击面前的单位,类似近战攻击效果。注意这个一看就知道是平射,如果高低坡的敌人容易打不到,因为我的魔兽争霸mod就是moba题材的机制,所以本来就是这个设定,高坡攻击miss,并且由于箭矢个头小就近射也容易miss,所以加了一些装备来弥补这个自身原始攻击方式的不足,比如金箍棒可以无视一定高坡集中攻击,鹰脚弓可以让近战英雄在第一人称时发射与自己视角协调的箭矢剑气
    (else_try),
        (agent_deliver_damage_to_agent, ":var_3", ":var_75", ":var_68"),      #如果装备了金箍棒物品的被动,则可以对面前一定范围的人造成群体分裂伤害
    (try_end),
(try_end),
(try_begin),                                                                      #代码块8-判断是否装备了鹰脚弓被动,作用是近战英雄攻击时可以发出远程剑气,可选内容,了解即可
    (troop_slot_eq, "trp_player", 705, 0),                 
    (item_slot_eq, "itm_eaglehorn", 308, 1),                      #slot308表示是否有这个装备的被动功能,鹰脚弓eaglehorn,由于暂时缺少蝴蝶模型,所以这个来自dota的装备先扮演蝴蝶的作用然后又自行加了这个特殊被动
    (this_or_next|eq, ":var_10", ":var_29"),
    (this_or_next|eq, ":var_10", ":var_31"),
    (eq, ":var_10", ":var_33"),           
    (prop_instance_get_position, pos40, ":var_7"),
    (position_move_z, pos40, 150),
    (position_move_y, pos40, 20),
    (copy_position, pos41, pos40),
    (try_begin),
        (eq, "$aaa", 0),
        (eq, "$cam1", 1),                                                              #cam1变量是判断是否除以新镜头控制代码的第一三人称镜头控制,为1是第一人称,因为我r键作为四技能使用了,并且顶点动画人物怪物体型和战团人物差别比较大,所以另外重写了第一三人称镜头切换控制
        (agent_get_look_position, pos42, ":var_3"),
        (position_copy_rotation, pos41, pos42),                             #以上表示第1人称镜头下下面用于发射箭矢的pos41角度要与玩家视角复制一致,也就是装备eaglehorn可以使得玩家选择近战英雄控制的时候,第一人称发射任意视角方向的远程剑气
    (try_end),
    (add_missile, ":var_3", 41, 64000, 0, 0, "itm_swift", 0),
(try_end),                                                                  #代码块8-结束
(try_begin),                                                                 #代码块9-判断玩家控制的顶点动画英雄是否是远程还是近战英雄,如果是远程英雄,则按左ctrl键可以不受面前近距离是否有敌人的条件释放箭矢missle,代码结构比较像我上面的循环近战攻击代码,可选内容,了解即可。
    (agent_slot_eq, ":var_3", 331, 1),                              #slot331号的agentslot为1代表这个英雄是远程英雄,这个会在其他触发器设定取值
    (key_is_down, key_left_control),
    (try_begin),
        (neg|gt, ":var_10", ":var_30"),
        (ge, ":var_10", ":var_29"),
    (else_try),
        (neg|gt, ":var_10", ":var_32"),
        (ge, ":var_10", ":var_31"),
    (else_try),
        (neg|gt, ":var_10", ":var_34"),
        (ge, ":var_10", ":var_33"),
    (else_try),
        (neg|gt, ":var_10", ":var_36"),
        (ge, ":var_10", ":var_35"),
    (else_try),
        (neg|gt, ":var_10", ":var_38"),
        (ge, ":var_10", ":var_37"),
    (else_try),
        (neg|gt, ":var_10", ":var_40"),
        (ge, ":var_10", ":var_39"),
    (else_try),
        (neg|gt, ":var_10", ":var_42"),
        (ge, ":var_10", ":var_41"),
    (else_try),
        (neg|gt, ":var_10", ":var_44"),
        (ge, ":var_10", ":var_43"),
    (else_try),
        (neg|gt, ":var_10", ":var_46"),
        (ge, ":var_10", ":var_45"),
    (else_try),
        (troop_slot_eq, "trp_player", 705, 1),
    (else_try),
        (try_begin),
            (is_between, ":var_13", 0, 400),
            (2611, ":var_7", ":var_29", ":var_30", ":var_74"),
        (else_try),
            (is_between, ":var_13", 400, 800),
            (2611, ":var_7", ":var_31", ":var_32", ":var_74"),
        (else_try),
            (is_between, ":var_13", 800, 1000),
            (2611, ":var_7", ":var_33", ":var_34", ":var_74"),
        (try_end),
    (try_end),
    (this_or_next|eq, ":var_10", ":var_29"),
    (this_or_next|eq, ":var_10", ":var_31"),
    (eq, ":var_10", ":var_33"),
    (prop_instance_get_position, pos40, ":var_7"),
    (position_move_z, pos40, 150),
    (position_move_y, pos40, 20),
    (copy_position, pos41, pos40),
    (try_begin),
        (eq, "$aaa", 0),
        (eq, "$cam1", 1),
        (agent_get_look_position, pos42, ":var_3"),
        (position_copy_rotation, pos41, pos42),
    (try_end),
    (agent_get_slot, ":var_79", ":var_3", 332),
    (add_missile, ":var_3", 41, 64000, 0, 0, ":var_79", 0),
(try_end),                                                                #代码块9-结束
(try_begin),                                                            #代码块10-集中判断一些一次性执行的动画动作终止的条件,一般就是像上面嘲讽动作一样,动画播放到尾帧时刻回归执行idle的待机动作
    (eq, ":var_10", ":var_33"),
    (stop_all_sounds, 1),
    (play_sound_at_position, "snd_juggatkdouble", pos15),             # 以上表示如果开始播放第三个动作的起始帧,就会发出暴击的音效
(else_try),
    (this_or_next|eq, ":var_10", ":var_46"),
    (this_or_next|eq, ":var_10", ":var_30"),
    (this_or_next|eq, ":var_10", ":var_32"),
    (eq, ":var_10", ":var_34"),
    (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (eq, ":var_10", ":var_46"),
    (stop_all_sounds, 1),
    (play_sound_at_position, "snd_reborn", pos15),                   # 以上表示如果播放到3种攻击动作或死亡动画的尾帧时刻,则回归执行idle的待机动作,特别的,如果执行到死亡的尾帧时刻,播放重生音效。死亡动作的设定在ti kill这个 trigger的触发器里另外写,不在本触发器里。
(else_try),
    (eq, ":var_10", ":var_45"),
    (stop_all_sounds, 1),
    (play_sound_at_position, "snd_dotadeath", pos15),      # 以上表示如果播放到死亡动画的起始帧时刻,播放死亡音效
(try_end),                                                                     #代码块10-结束
(try_begin),                                                                 
    (neg|gt, ":var_10", ":var_26"),
    (ge, ":var_10", ":var_25"),
    (assign, "$stoprun", 0),
(else_try),
    (assign, "$stoprun", 1),
(try_end),                                                                   #以上是判断顶点动画处于跑步行为的帧时刻区间时$stoprun设0,其他情况设1,对$stoprun的判断写在了其他触发器里,作用是和其他变量一起组合判断玩家是否要用agent set no dynamic这个op来强制玩家不可以随便移动,                                                                                一般$stoprun为1的情况是不可以移动的,比如我释放技能和攻击时会强制玩家no dynamic进而取消了系统控制的位移行为。
(try_begin),                                                                      #RTS-2镜头状态和第1/3人称时的镜头控制在其他触发器里,
RTS-1镜头状态即$aaa为1时因为一些不同英雄的镜头需求写在了这里
    (eq, "$aaa", 1),
    (agent_get_look_position, pos4, ":var_3"),
    (position_copy_rotation, pos2, pos4),
    (position_move_y, pos2, "$rog"),
    (position_move_z, pos2, 90),
    (mission_cam_set_mode, 1),
    (mission_cam_set_position, pos2),
(try_end),
(try_begin),                                                              #    到上面为止示例基本结束了,以下的代码是对一些特殊补丁添加的新英雄的判断,不多解释,目的为了开局执行一下idle待机动作,因为部分采用引用本脚本动作控制的英雄,需要重新覆盖一个新的propslot动作序列参数,导致重新赋值时动画开在一个循环类的高优先级动作上比如技能动作,所以要开局卡一定cd后给予一个判断重置动作到idle的量
    (troop_slot_ge, "trp_player", 736, 1),
    (agent_get_slot, ":var_80", ":var_3", 335),
    (try_begin),
        (is_between, ":var_80", 1, 30),
        (val_add, ":var_80", 1),
        (agent_set_slot, ":var_3", 335, ":var_80"),
        (eq, ":var_80", 20),
        (2612, ":var_7", ":var_21", ":var_22", ":var_55"),
    (try_end),
    (try_begin),
        (agent_slot_eq, ":var_3", 335, 0),
        (agent_set_slot, ":var_3", 335, 1),
    (else_try),
        (agent_slot_eq, ":var_3", 335, 30),
        (troop_slot_ge, "trp_player", 679, 2),
        (agent_set_slot, ":var_3", 335, 0),
    (try_end),
(try_end),



















评分

参与人数 2荣誉 +1 第纳尔 +60 互助 +3 魅力 +60 收起 理由
Aomine Daiki + 1 + 50 + 2 + 50 感谢发表精华文章!
幼稚园殺手 + 10 + 1 + 10 原创内容,值得鼓励!

查看全部评分

鲜花鸡蛋

幼稚园殺手  在2023-1-5 19:28  送朵鲜花  并说:我非常同意你的观点,送朵鲜花鼓励一下

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-1-9 11:05:53 | 显示全部楼层
对于上面的一系列知识基础内容和代码实例做一些额外说明:

1.场景物顶点动画的研究对象类型范围:
(1)整体采用有全额有效动画帧数的顶点动画模型,比如我实例的魔兽争霸人物
(2) 无有效动画帧数但拥有实体的模型,比如我上面说的这种可以留空或作为计时器
(3)组合模型的分部mesh模型部分有有效帧动画部分没有有效帧动画,这个联系第(2)种情况,也就是你整体没有动画也能拥有帧时刻变换的抽象参数属性,那么你模型组成中一部分有动画一部分没有动画也可以整体控制,比如你的战车就一个轮子有滚动的顶点动画但是其他车身等部分没有顶点动画,此时你可以选择把车身和轮子拆开成两个场景物,然后只控制轮子的顶点动画,也可以合并,按照轮子的动画控制整个车的顶点动画帧时刻参数状态。
  (4)一部分采用骨骼动画的agent系统+一部分采用含顶点动画的场景物作为机体一部分或武器或配件。举个例子,你要做表情系统眼睛和嘴巴会动,这时候你就可以隐藏头盔或脑袋模型,然后附加一个顶点动画特制头模型设置在头骨骼的坐标位置上一起从动运动。再举个例子,特殊的含动画的武器,比如你们用烂的链枷。


2.对于动作事件的复合处理:
我上面仅仅示范了我魔兽争霸moba人物简单的十几种动作事件的处理方法,但是实际上,比如对于我的龙珠拥有近百种动作来说,特别是魔兽争霸还不像我的龙珠一样对同类型动作有不同随机动作选择,则不能单纯像我魔兽争霸这种代码结构一样采用动作动画区间的枚举法判定条件,这样代码会写的很长并且头会乱。就需要对动画事件进行分类形成slot待判定量,比如有的时候,打击和防御动作可以统一分类为近战行为,当人物处于近战格斗的一系列行为时,哪些事件会发生,哪些其他动作动画不可以打断当前近战动作会被当前近战动作打断,等等。所以从0开始构造一个生物的行为,是比较复杂的,考虑的关联冲突事件多级关系会比较多。





55

主题

2701

回帖

1747

积分

子爵[版主]

吟游诗人

Rank: 7Rank: 7Rank: 7

UID
3054380
第纳尔
24009
精华
2
互助
56
荣誉
44
贡献
916
魅力
1418
注册时间
2019-1-18

骑砍中文站APP会员勋章原版正版勋章战团正版勋章火与剑正版勋章拿破仑正版勋章维京征服正版勋章霸主正版勋章剧本设计大奖赛骑友真人秀Ⅷ勋章骑友真人秀Ⅶ勋章骑友真人秀Ⅸ勋章

QQ
鲜花(505) 鸡蛋(2)
发表于 2023-1-5 19:27:58 | 显示全部楼层
这个真的很好,我以后慢慢学习!谢谢你的”独家秘笈“
珍惜 奉献 不负韶华

15

主题

734

回帖

365

积分

子爵[版主]

汉[Han]
联机ID:Han_DongHai

Rank: 7Rank: 7Rank: 7

UID
3033293
第纳尔
10325
精华
0
互助
24
荣誉
2
贡献
360
魅力
184
注册时间
2018-10-3

第十届战团中国联赛征战勋章汉匈决战正版勋章战团正版勋章霸主正版勋章

QQ
鲜花(37) 鸡蛋(0)
发表于 2023-2-17 18:38:34 | 显示全部楼层
快点更新!

30

主题

200

回帖

169

积分

见习骑士

Rank: 3

UID
2462463
第纳尔
1472
精华
0
互助
20
荣誉
0
贡献
0
魅力
50
注册时间
2015-3-3
鲜花(43) 鸡蛋(0)
发表于 2023-3-13 22:40:06 | 显示全部楼层
本帖最后由 战争傀儡阿格兰 于 2023-3-13 22:52 编辑

大佬大佬,为啥我做好顶点动画的brf,按照你的方法设置好5帧动画,每个10间隔,自己写的
(scene_prop_get_instance, ":wheel_id", "spr_xxx", 0),
(prop_instance_deform_in_cycle_loop, ":wheel_id",1,5,5000),


不是应该5秒钟时间,从第一帧走到第五帧吗,为啥没反应呢?
是不是需要module_scene_props.py里对"spr_xxx"进行什么设置啊

(prop_instance_deform_in_cycle_loop, <prop_instance_no>, <start_frame>, <end_frame>, <duration-in-1/1000-seconds>),
lunbrf.jpg


202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-3-13 23:18:05 | 显示全部楼层
本帖最后由 vegetto 于 2023-3-14 07:51 编辑

[quote][url=forum.php?mod=redirect


仔细看,我说的很清楚,代码控制的是右边格子的参数,左边的叫关键帧序号,右边的数据是帧时刻,你这样的写法相当于,brf设置后右边数据处于0~9时刻只对应着左边数据的第0序号关帧帧,代码控制物体动画1~5时刻变化所以形态只固定在0帧序上。


然后五秒时间太长了,一般相邻两个关键帧的变化幅度不要超过0.1秒,相邻两个序号的关键帧之间相隔时间太长时,系统会自动在之间构造均匀变化的中间形态(比如播放速度太慢时系统在0和1号关键帧之间构造一个在openbrf没有体现的0.5帧形态。),会产生一些扭曲变形不符合实际的中间态(比如你的轮子转三百六十度但是实际上你每个帧让他转了六十度那么多,那么相邻两个帧如果完成时间较大播放进度较慢,达到了半秒以上这种视觉效果能察觉的时间,系统会在这段时间内将你两个关键帧之间系统自个儿思考如何构造中间态,然后就会产生奇妙的变化,比如系统觉得从一个帧转六十度到另一个帧不是旋转变化过去的,系统会将你的模型先自动压扁缩小消失然后再放大到转个六十度的状态)。

所以关键帧数量精度一定要匹配的上总变化时间,即帧数所占的单位完成时间一定要合理,所以你动画精度不够,是无法很好的表现这个东西,或者只能表现高速运转的状态(比如你只有六帧,你的车轮速度只能保持在高速运转状态也就是零点几秒转一圈,就不能体现速度的调控,速度慢了就会出现上面的中间态扭曲问题。),但是如果关键帧数量精度足够了,也会导致模型体积以及对性能的消耗就会很大。对于轮子转动这个也可以考虑用Animate转动,但是需要克服延迟。

此外,模型和代码技术同样重要,首先学一下动画的基本术语概念和做法,再考虑代码对它的控制。这种动画最好是在模型软件做好完整的精度够的md3再导,而不是靠只在brf里慢慢合几个静态模型,为什么我的处理方法要把间隔处理成10,因为当你的帧数成千上百,你一个一个手动输入时刻数据会很头大,所以我介绍了那个快速方法,帧数少的时候也可以手输右侧的数据去对应左侧的数据,并且那个快速方法只能让时刻以10按序号成等差数列。反正一定要注意这个代码op引用的frame数据是帧时刻,你就算是骨骼动画action.txt每个引用动作也是填右侧帧时刻区间而不是左侧序号区间。就算是其他游戏代码也是操作时刻而不是关键帧序列,无论哪个引擎的动画控制代码都是靠控制帧时刻的状态去逆推当前用什么序号的关键帧形态。为什么要呈等差数列,那是因为你的关键帧一般是按匀速动作设的每帧形态,你对应的实际代码引用的帧时刻不按等差数据,则控制帧时刻变化对应的间接控制的每个关键帧相邻变化时间就不等,动作就不均匀变化


30

主题

200

回帖

169

积分

见习骑士

Rank: 3

UID
2462463
第纳尔
1472
精华
0
互助
20
荣誉
0
贡献
0
魅力
50
注册时间
2015-3-3
鲜花(43) 鸡蛋(0)
发表于 2023-3-14 16:27:07 | 显示全部楼层
vegetto 发表于 2023-3-13 23:18
[quote][url=forum.php?mod=redirect

大佬太6了!终于理解了右边的数据的意义了,已成功。另,真的被你说中了,先把轮胎缩回去,再变大。。。现在只能继续改模型了,多谢多谢!

202

主题

984

回帖

986

积分

子爵[版主]

Rank: 7Rank: 7Rank: 7

UID
2893127
第纳尔
14521
精华
0
互助
90
荣誉
18
贡献
325
魅力
775
注册时间
2017-11-5
鲜花(428) 鸡蛋(0)
 楼主| 发表于 2023-3-14 16:50:47 | 显示全部楼层
本帖最后由 vegetto 于 2023-3-14 16:53 编辑
战争傀儡阿格兰 发表于 2023-3-14 16:27
大佬太6了!终于理解了右边的数据的意义了,已成功。另,真的被你说中了,先把轮胎缩回去,再变大。。。 ...

你现在的模型面数如果做30帧大概模型大小单个能到4兆左右,要减面,不然只能给玩家或几个单位用。你现在还是用一个一个合成的这种低效方法做这个动画吗

115

主题

307

回帖

197

积分

见习骑士

Rank: 3

UID
3136443
第纳尔
1060
精华
0
互助
14
荣誉
0
贡献
0
魅力
44
注册时间
2020-2-14

第二届拿破仑中国刺刀联赛近卫勋章拿破仑开拓者勋章拿破仑正版勋章战团正版勋章汉匈决战正版勋章

鲜花(50) 鸡蛋(0)
发表于 2023-4-27 18:23:24 | 显示全部楼层
大佬,有什么办法可以获取游戏内鼠标的信息吗
您需要登录后才可以回帖 登录 | 注册(Register!)

本版积分规则

Archiver|手机版|小黑屋|骑马与砍杀中文站

GMT+8, 2024-3-29 12:54 , Processed in 0.162940 second(s), 31 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表