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

Project1

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

[讨论] RGSS1 的「又一」坑人 BUG

[复制链接]

Lv4.逐梦者 (版主)

梦石
0
星屑
9532
在线时间
5073 小时
注册时间
2013-6-21
帖子
3580

开拓者贵宾剧作品鉴家

跳转到指定楼层
1
发表于 2019-8-25 10:41:32 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 RyanBern 于 2019-8-25 10:44 编辑

不知道大家在战斗中触发事件时有没有这样的体会:整个游戏会出现明显卡顿。按 F2 查看 FPS 时发现帧率只有 10 左右甚至个位数。
例如使用 Steam 版的最新 RMXP 创建新工程,在没有额外添加任何脚本的情况下就会出现下面这个图的情况。



这个图中我只是用了一个显示文章的命令,游戏的帧率直接跌到个位数。如果是显示战斗动画这种肉眼可见的事件那么体感会更加明显。在事件执行完成之后,游戏的 FPS 立即恢复了正常的水平。而在地图上执行各种事件我们并没有发现什么异常。

问题就出现在 Scene_Battle 刷新机制上。打开脚本编辑器后找到 Scene_Battle 1 可以看到定义 update 方法的部分:
RUBY 代码复制
  1. def update
  2.     # If battle event is running
  3.     if $game_system.battle_interpreter.running?
  4.       # Update interpreter
  5.       $game_system.battle_interpreter.update
  6.       # If a battler which is forcing actions doesn't exist
  7.       if $game_temp.forcing_battler == nil
  8.         # If battle event has finished running
  9.         unless $game_system.battle_interpreter.running?
  10.           # Rerun battle event set up if battle continues
  11.           unless judge
  12.             setup_battle_event
  13.           end
  14.         end
  15.         # If not after battle phase
  16.         if @phase != 5
  17.           # Refresh status window
  18.           @status_window.refresh
  19.         end
  20.       end
  21.     end

刷新机制表明如果战斗事件不为空就优先刷新事件解释器。但问题就出现在这个过程的最后一步。
RUBY 代码复制
  1. if @phase != 5
  2.   @status_window.refresh
  3. end

这句话的意思是说如果战斗的阶段不在第五阶段,那么就需要对 @status_window 的内容进行重新描绘。战斗的第五阶段实际上是显示战利品,获得 EXP 的阶段,除了这个阶段以外,只要事件解释器运行,每次 update 都会重新刷新一次状态窗口。这个 @status_window 就是显示角色 HP、SP、当前状态的那个窗口。

写过 RMXP 脚本的人都知道,refresh 操作一般是对 bitmap 进行各种绘制,里面调用的方法执行起来通常是比较慢的。反复调用 refresh 操作应该极力避免。这也就不难理解为什么在战斗中执行事件会导致帧率下降了。
为了测试是否真的是这个地方的锅,可以直接将这一段注释掉,结果发现帧率直接恢复正常。



那么为啥默认系统要放一个 @status_window.refresh 在这呢?当然是因为状态窗口有时候在执行事件指令之后是需要刷新的,例如:增减 HP/SP更改角色姓名更改角色状态。不过即使在这些场合需要刷新,也不需要每帧都进行检查。最简单的修复办法就是在刷新之前增加一个判定标志,当只有执行特定事件的一瞬间才去刷新状态窗口。我们先在 Game_Temp 中增加一个刷新战斗状态窗口的标志。
RUBY 代码复制
  1. class Game_Temp
  2.   attr_accessor :battle_status_need_refresh
  3.   def initialize
  4.     # ...
  5.     @battle_status_need_refresh = false
  6.   end
  7. end

然后再需要刷新窗口的时候打开这个标志。以增减 HP 为例,它的事件指令编号是 311。
RUBY 代码复制
  1. class Interpreter
  2.   def command_311
  3.     # Get operate value
  4.     value = operate_value(@parameters[1], @parameters[2], @parameters[3])
  5.     # Process with iterator
  6.     iterate_actor(@parameters[0]) do |actor|
  7.       # If HP are not 0
  8.       if actor.hp > 0
  9.         # Change HP (if death is not permitted, make HP 1)
  10.         if @parameters[4] == false and actor.hp + value <= 0
  11.           actor.hp = 1
  12.         else
  13.           actor.hp += value
  14.         end
  15.       end
  16.     end
  17.     # Determine game over
  18.     $game_temp.gameover = $game_party.all_dead?
  19.     # 刷新状态窗口
  20.     if $game_temp.in_battle
  21.       $game_temp.battle_status_need_refresh = true
  22.     end
  23.     # Continue
  24.     return true
  25.   end
  26. end

在这个指令增加一个开启刷新标志的命令。最后就是修改 Scene_Battle 1 的刷新判定了。
RUBY 代码复制
  1. if @phase != 5 && $game_temp.battle_status_need_refresh
  2.   @status_window.refresh
  3.   $game_temp.battle_status_need_refresh = false
  4. end

大功告成。

评分

参与人数 9+9 收起 理由
e900003 + 1 精品文章
89444640 + 1 精品文章
W.Q.C. + 1 精品文章
kirh_036 + 1 醋虾
真·可乐 + 1 精品文章
miantouchi + 1 精品文章
kklt + 1 精品文章
百里_飞柳 + 1 我很赞同
灯笼菜刀王 + 1 精品文章

查看全部评分

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

2
发表于 2019-8-25 15:52:20 | 只看该作者
23333机智的我早就注释掉了

点评

如果不用那几个命令确实注释掉更简单粗暴。  发表于 2019-8-25 18:34
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 反对

使用道具 举报

Lv3.寻梦者

双子人

梦石
0
星屑
3185
在线时间
3618 小时
注册时间
2009-4-4
帖子
4154

开拓者

3
发表于 2019-8-25 19:24:18 | 只看该作者
本帖最后由 hys111111 于 2019-8-25 19:28 编辑

类似的,
做ARPG事件多的时候,地图很卡,因为Game_Character下的def passable?(x,y,d)会先调用Game_Map下的def passable?(x,y,d,self_event = nil),
然而这两个类下的passable?都会执行for event in $game_map.events.values循环,很不舒服。直接不要Game_Map下的passable?了(整合到Game_Character下了,循环执行两次变为一次)。
到后面直接连check_event_trigger_there也整合到passable?里面去了

点评

很好奇两个passable是怎样合并的?看了半天表示很晕。(=_=)  发表于 2020-1-27 04:21

评分

参与人数 2+2 收起 理由
灯笼菜刀王 + 1 我很赞同
guoxiaomi + 1 我很赞同

查看全部评分

回复 支持 反对

使用道具 举报

Lv2.观梦者

梦石
0
星屑
358
在线时间
296 小时
注册时间
2013-6-1
帖子
121
4
发表于 2019-8-26 20:18:32 | 只看该作者
本帖最后由 e900003 于 2019-8-26 21:36 编辑

我目前測試  套用此設定之後 用公共事件設定造成傷害的設定
不會在造成傷害時候刷新HP跟MP
只能等下一回合之後才會刷新一次
有什麼解決辦法可以解決這個沒有自動刷新HP跟MP的問題

更新: 找到方案了,謝謝
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4598
在线时间
484 小时
注册时间
2017-7-7
帖子
139

R考场第七期纪念奖

5
发表于 2019-8-26 21:41:34 | 只看该作者
e900003 发表于 2019-8-26 20:18
我目前測試  套用此設定之後 用公共事件設定造成傷害的設定
不會在造成傷害時候刷新HP跟MP
只能等下一回合 ...


公共事件里用事件脚本手动$game_temp.battle_status_need_refresh = true一下就好了
-
咳,不好意思没看到已经解决了
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
42404
在线时间
7602 小时
注册时间
2009-7-6
帖子
13506

开拓者贵宾

6
发表于 2019-8-26 22:31:19 | 只看该作者
这,简直强到不可思议,我一直以为是fps统计方式有问题

点评

这鸡假装没注意到。实际上已经自己修好了。  发表于 2019-8-26 23:38
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-23 17:06

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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