扫描二维码关注官方公众号
返回列表
+ 发新帖
查看: 96|回复: 0

[转载发布] [案例分析]字体频繁更新导致的Joiplay非典型内存泄漏

[复制链接]
累计送礼:
0 个
累计收礼:
0 个
  • TA的每日心情
    开心
    2025-7-8 01:43
  • 签到天数: 157 天

    连续签到: 2 天

    [LV.7]常住居民III

    2448

    主题

    498

    回帖

    1万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    VIP
    6
    卡币
    13119
    OK点
    16
    推广点
    0
    同能卷
    0
    积分
    16093

    灌水之王

    发表于 昨天 11:19 | 显示全部楼层 |阅读模式
    一般来说,我们认为RGSS的内存泄漏通常发生在需要主动dispose的资源类型上,
    其他的数据类型如果不是刻意为之,很难导致严重的内存泄漏,
    但是,由于Joiplay的引擎底层跟RPGMaker PC端并不完全一致,
    可能就会导致一些在PC端上没有任何问题的脚本,在Joiplay上出现严重的问题
    其中,Joiplay的字体缓存就是重灾区

    请看以下这段代码:
    RUBY 代码
    1. def draw_text(x,y,w)
    2.     returnunless@cur_val
    3.     @window.contents.font.name = "VL GOTHIC"
    4.     @window.change_color(@window.system_color)
    5.     @window.draw_text(x, y, 30, @window.line_height, @vocab)
    6.     @window.change_color(@window.normal_color)
    7.     @window.change_color(@window.crisis_color)if@cur_val < @max_val / 4
    8.     xr = x + w
    9.     if w < 96
    10.       @window.draw_text(xr - 40, y, 42, @window.line_height, @cur_val.to_i, 2)
    11.     else
    12.       @window.draw_text(xr - 92, y, 42, @window.line_height, @cur_val.to_i, 2)
    13.       @window.change_color(@window.normal_color)
    14.       @window.draw_text(xr - 52, y, 12, @window.line_height, "/", 2)
    15.       @window.draw_text(xr - 42, y, 42, @window.line_height, @max_val, 2)
    16.     end
    17.     @window.contents.font.name = Font.default_name[0]
    18.   end
    复制代码

    这段代码看起来就是很普通的切换显示字体,显示文本,然后把字体切回去
    在PC端上,引擎会从内建的字体缓存中切换字体,几乎没有性能开销
    但是在Joiplay上,每次执行这段代码,Joiplay都会尝试重新读取字体,
    而不幸的是,这段代码被放在了角色状态栏的动画效果中,
    只要进行战斗动作就会随着HPMP的动画效果每帧执行,
    最终的结果就是平均每回合提升约60MB的内存占用

    那么应该怎么解决呢?
    唔呣,既然Joiplay没有字体缓存,那么我们就只好自己创建字体缓存了
    具体来说,是把每个Font当作缓存来用,不到万不得已不直接修改Font里的内容
    例如,在这个案例中,我选择在类里面塞两个Font作为缓存,
    需要用的时候直接切换整个font,这样就可以避免对Font内部做修改导致的Joiplay问题
    RUBY 代码
    1. class Special_Gauge
    2.   @@original_gauge_font = nil
    3.   @@custom_gauge_font = nil
    4.   attr_accessor :cur_val
    5.   def initialize(x,y,w,r,c1,c2,window,height = SPECIAL_GAUGES::DEFAULT_HEIGHT)
    6.     @x = x
    7.     @y = y
    8.     @width = w
    9.     @cur_rate = r
    10.     @max_rate = r
    11.     @color1 = c1
    12.     @color2 = c2
    13.     @window = window
    14.     @speed = 0
    15.     @speed_rate = 0
    16.     @height = height
    17.     @fall_sprites = []
    18.     # 修复:初始化字体缓存
    19.     if @@custom_gauge_font.nil?
    20.       @@original_gauge_font = @window.contents.font.deep_copy# 其实就是新建了一个字体然后把所有属性搬过去
    21.       @@custom_gauge_font = @window.contents.font.deep_copy(false)# 少搬一个名字,避免又主动读取字体
    22.       @@custom_gauge_font.name = SPECIAL_GAUGES::CUSTOM_FONT_NAME
    23.     end
    24.     refresh
    25.   end
    26.   def draw_text(x,y,w)
    27.     returnunless@cur_val
    28.     # 修复:使用字体缓存切换字体而不是名字
    29.     @window.contents.font = @@custom_gauge_font
    30.     @window.change_color(@window.system_color)
    31.     @window.draw_text(x, y, 30, @window.line_height, @vocab)
    32.     @window.change_color(@window.normal_color)
    33.     @window.change_color(@window.crisis_color)if@cur_val < @max_val / 4
    34.     xr = x + w
    35.     if w < 96
    36.       @window.draw_text(xr - 40, y, 42, @window.line_height, @cur_val.to_i, 2)
    37.     else
    38.       @window.draw_text(xr - 92, y, 42, @window.line_height, @cur_val.to_i, 2)
    39.       @window.change_color(@window.normal_color)
    40.       @window.draw_text(xr - 52, y, 12, @window.line_height, "/", 2)
    41.       @window.draw_text(xr - 42, y, 42, @window.line_height, @max_val, 2)
    42.     end
    43.     @window.contents.font = @@original_gauge_font
    44.   end
    复制代码

    另外,Joiplay上经常出现的字体透明度错误的问题,也是因为字体缓存没有及时刷新导致的
    但是这个问题我还没有研究透彻,也没有找到主动刷新缓存的方案
    如果有大佬知道,还请指点一下


                本帖来自P1论坛作者saicatedoan,因Project1站服务器在国外有时候访问缓慢不方便作者交流学习,经联系P1站长fux2同意署名转载一起分享游戏制作经验,共同为国内独立游戏作者共同创造良好交流环境,原文地址:https://rpg.blue/forum.php?mod=viewthread&tid=497767  若有侵权,发帖作者可联系底部站长QQ在线咨询功能删除,谢谢。
    天天去同能,天天有童年!
    回复 送礼论坛版权

    使用道具 举报

    文明发言,和谐互动
    文明发言,和谐互动
    高级模式
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    关闭

    幸运抽奖

    社区每日抽奖来袭,快来试试你是欧皇还是非酋~

    立即查看

    聊天机器人
    Loading...

    QQ|Archiver|手机版|小黑屋|同能RPG制作大师 ( 沪ICP备12027754号-3 )

    GMT+8, 2025-7-24 07:04 , Processed in 0.133928 second(s), 54 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.

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