设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 4940|回复: 9
打印 上一主题 下一主题

[已经解决] 关于YEP-ATB战斗实时化的问题

[复制链接]

Lv2.观梦者

梦石
0
星屑
842
在线时间
174 小时
注册时间
2012-2-7
帖子
43
跳转到指定楼层
1
发表于 2017-2-21 17:10:23 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 yahzj 于 2017-2-22 14:23 编辑

之前的表述可能不太清楚,感觉几位回答的大佬都没明白我的困惑,所以编辑了重新写下

YEP氏的MV系统十分强大,但是关于ATB战斗这方面,无法做到实时制:既每个人物行动都是独立的,行动时其他人不会暂停或者排队(DoubleX氏的PATB可以做到半实时,但是所有人行动都是排队轮流进行,无法做到同时)

所以目前的想法是,基于YEP氏现有的代码上修改,目前进度....读代码中.....因为缺少中间注释,所以分析起来比较困难,如果有大佬知道相关代码是哪一段或者如何解决,望能指出

Lv1.梦旅人

梦石
0
星屑
55
在线时间
407 小时
注册时间
2011-4-10
帖子
359
2
发表于 2017-2-21 18:47:52 | 只看该作者
YEP的Action Sequence Pack系列里,用指令播放动画,默认是不等待动画完成的。这完全可以满足你的要求。
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
842
在线时间
174 小时
注册时间
2012-2-7
帖子
43
3
 楼主| 发表于 2017-2-21 19:38:35 | 只看该作者
本帖最后由 yahzj 于 2017-2-21 22:26 编辑
sutao80216 发表于 2017-2-21 18:47
YEP的Action Sequence Pack系列里,用指令播放动画,默认是不等待动画完成的。这完全可以满足你的要求。 ...


我试了下,没有办法貌似,因为我是要释放完技能就直接轮到下个人,不需要等待动画或者伤害跳出,变成接近半回合制那种
现在的情况是,可以在播放动画的时候 变成下个人行动,但是伤害效果会在播放动画的同时产生,如果选择延迟,下一个人行动也会被等待
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
440
在线时间
679 小时
注册时间
2014-3-15
帖子
292

开拓者

4
发表于 2017-2-22 01:04:02 | 只看该作者
你需要用animation wait:X来暂停一段时间比如
<target action>
motion spell: user
animation wait: 20
animation 1: target
animation wait: 20
action effect
animation wait: 20
</target action>
即使用者作出spell动作,等待20帧 在target上播放动画 等待20帧,发挥伤害效果,在等待20帧,结束
所以你需要根据播放动画的情况准确预测播放时间即其中时间如何处理动作与伤害
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
842
在线时间
174 小时
注册时间
2012-2-7
帖子
43
5
 楼主| 发表于 2017-2-22 08:58:21 | 只看该作者
sonicdonggua 发表于 2017-2-22 01:04
你需要用animation wait:X来暂停一段时间比如

motion spell: user

animation wait试过了,一旦暂停,就必须等待到所有暂停时间结束,才能轮到下个人
我需要的是 选择释放技能后就轮到下个人,而不用等待动画和技能效果结束

目前采用的是
  1. <Cast Animation: 0>
  2. <setup action>
  3. </setup action>  
  4. <whole action>
  5. </whole action>
  6. <target action>
  7. </target action>
  8. <finish action>
  9. animation 66: target
  10. action effect
  11. </finish action>
复制代码

这样来用完技能可以直接结束行动,轮到下个人行动同时播放动画,但是伤害也变成和动画一起产生,加入延迟后就必须等待延迟结束才能到下个人行动,无法做到延迟
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
676
在线时间
224 小时
注册时间
2006-12-7
帖子
839
6
发表于 2017-2-22 12:28:09 | 只看该作者
同一个目标好象是不能同时播放两个动画的,
要是是想做合击之类的直接用action sequence代码操作第二个行动人物就行了
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
842
在线时间
174 小时
注册时间
2012-2-7
帖子
43
7
 楼主| 发表于 2017-2-22 14:01:28 | 只看该作者
doranikofu 发表于 2017-2-22 12:28
同一个目标好象是不能同时播放两个动画的,
要是是想做合击之类的直接用action sequence代码操作第二个行动 ...

并不是合击,仅仅是想取消行动时其他人的暂停
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
165
在线时间
85 小时
注册时间
2016-4-26
帖子
15
8
发表于 2017-5-5 01:03:49 | 只看该作者
本帖最后由 DoubleX 于 2017-5-5 01:11 编辑

要做到全实时的话,必须要对RMMV的战斗系统的本质有一个彻底的领悟。
简言之,此战斗系统基於2大假设:
1. 同一帧数(frame,下同)内不能有多於一个正在执行的行动(Game_Action丶下同)
2. 同一帧数内不能有多於一个正在执行行动的战斗者(Game_Battler丶下同)
任何试图推翻至少一个2大假设的插件都必须将BattleManager推倒重来,这将意味着该插件将与绝大部分依赖战斗流程的插件不相容。
这是因为在本质上RMMV战斗里的行动是阻塞的(blocking丶下同),而真正的全实时则要求行动是非阻塞的(non blocking丶下同)。

从本质上来说,要做到真正的全实时只有2个方法:
1. 把每一个战斗者和正在执行的行动都视为一个事件(event丶下同),也就是用ABS的运作摸式来运行ATB(需要注意的是,所有行动都是在实际执行的瞬间击中目标,即使单看动画的话看似并非如此
2. 把每一个战斗者都视为一个执行绪(thread丶下同)丶每一个正在执行的行动都视为一个程序(process丶下同),也就是透过多线程(multithreading丶下同)来运行ATB
第一个方法的问题在於,既然都动用ABS的运作摸式了,为何不乾脆做ABS插件(或是Moghunter的LMBS)?
第二个方法的问题在於,多线程将出现极度麻烦且灾难性的同步(synchronization丶下同)问题,因为在全实时下,在同一帧数,战斗者可透过正在执行的行动建立一个多对多(many to many丶下同)的连结甚至循环,因此需要处理战斗者之间的并发性(concurrency丶下同)问题。而且由於每一个正在执行行动的战斗者都需要一个执行绪,4个己方和8个敌方在同一帧数中执行行动的话便需要12个执行绪,即使是动用执行绪池,这样的插件也只能在顶尖级别的个人电脑下运行。

不过,虽然要做到真正的全实时未免过於不切实际,可是要做到近似的全实时还是可行的,只是要做得好的话难度极高,以及用家必须接受偶而的瞬间延迟。
需要注意的一致性(consistency丶下同)问题有2个:
1. 多於一个正在执行的行动在同一帧数应用於同一个目标,因为改变它们的先後次序将改变整体的效果(如其中一个行动是回血,另一个是放血,先後次序不同将决定目标的死活)
2. 一个正在执行的行动的战斗者在同一帧数又是另一个正在执行的行动的目标(其中的极端是循环依赖,即A1是A2的目标丶A2是A3的目标丶A3是A4的目标丶…AN是A1的目标),因为「前者先执行行动再被後者的行动击中」和「前者先被後者的行动击中再执行行动」将改变前执行的行动的效果(因为有些行动是基於使用者使用时的状态)
解决第一个问题的方法可以是让插件用家用Javascript编写决定先後次序的规则,当然这意味着此这样的插件只能给进阶的用家使用,而且在教导玩家方面也得下苦功。
解决第二个问题的方法可以是在执行行动的帧数中,先将执行行动的战斗者进行深拷贝(deep copy丶下同),然後再用深拷贝的战斗者执行行动,这样不管原本的战斗者如何被执行的行动击中,都不会影响深拷贝的战斗者。当然,如何高效地深拷贝一个战斗者本身便是一个极为头痛的问题。

当然,即使只是近似的全实时,要实现的话还是必须要对ATB战斗系统的本质有一个彻底的领悟,以及拥有编写至少一个高阶、复杂(需要专攻至少一个领域且规模是10K LoC左右级别的)且高质素的插件的经验。不然的话我会先建议楼主尝试写一个半实时的ATB插件 :)

P.S.:其实我原本也打算编写一个新的ATB插件,将支援近似的全实时,不过自从我成为全职程式编写员後,便很难再抽空编写插件(特别是ATB这种需要数以星期计的工作量的),因此我不敢说我必定能在出现新的RM版本前完成:D

评分

参与人数 1星屑 +10 收起 理由
guoxiaomi + 10 受益匪浅

查看全部评分

回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
50
在线时间
25 小时
注册时间
2017-3-27
帖子
10
9
发表于 2017-5-5 12:47:22 | 只看该作者
本帖最后由 TTIAN 于 2017-5-5 12:54 编辑

YEP中并没有将每个角色单独处理,而是当做整体纳入了一个speed->input->charge->action的体系当中。

你说的这个东西的代码应该是这里:
BattleManager.update = function() {
    if (this.isATB()) {
      if (this.isBusy()) return;
      if (this.updateEvent()) return;
      if (this._phase === 'battleEnd') {
        return Yanfly.ATB.BattleManager_update.call(this);
      }
      if (this.checkBattleEnd()) return;
      if (this._phase === 'atb') {
        this.updateATBPhase();
      } else {
        Yanfly.ATB.BattleManager_update.call(this);
      }

    } else {
      Yanfly.ATB.BattleManager_update.call(this);
    }
};

可以看出在角色行动时,YEP还是使用了和基础战斗系统相同的方法,只是在需要进度条的“atb”阶段进行了单独处理。
如果你能在Yanfly.ATB.BattleManager_update.call(this);前插入一个你写的方法,用来update其他处于speed或是charge阶段的角色,应该就OK了。

但这玩意感觉好容易出问题,你主要角色没有update的时候其他角色却在update,如果你有buff之类的牵扯到时间逻辑,可能直接就乱掉了。
如果真要改,建议遵循楼上的建议,重写一套逻辑比较好。。。。
回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
842
在线时间
174 小时
注册时间
2012-2-7
帖子
43
10
 楼主| 发表于 2017-5-31 10:40:23 | 只看该作者
感谢楼上给出的意见,其实近期工作忙(进新公司做程序员),关于ATB的研究几乎处于荒废阶段了
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-12-1 12:45

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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