创意来源:
https://rpg.blue/thread-369217-1-1.html
非常感谢原作者给我提供了思路,但是原本的脚本存在几个问题:数据收集不全,统计方式错误,实际用起来效果并不理想
所以我请DeepSeek帮我拓展了一下脚本,修复了原本脚本的bug基础上,多了一些花里胡哨但其实没太大用的统计功能
不要问我为什么是V3
如何判断发生了内存泄漏:
在游戏运行一段时间后,明明没干什么特别的事情,游戏突然变得卡顿,而且越来越卡,最后闪退,就很可能是内存泄漏
如果同时还导致了其他程序的崩溃,那就基本可以确定了
为什么会发生内存泄漏:
Rpgmaker中一部分资源是需要使用dispose手动清理的,如果没人清理,即使使用资源的变量已经销毁,也不会释放内存
如何修复内存泄漏:
我唯一能给出的建议就是拿着内存泄漏的脚本去问AI
如何找到发生内存泄漏的脚本:
RUBY 代码
[code]#==============================================================================
# ■ RGSS3 检测内存泄漏V3 by SaiCateDoan
#------------------------------------------------------------------------------
# 创意来源:taroxd
#
# 使用方法:
# 1.插入到Main脚本的上面,所有其他脚本的下面
# 2.正常玩游戏一段时间,进行几次战斗
# 3.在地图界面按下Alt,建议多按几次
# 4.重复2-3数次,或重复到游戏卡顿(当然你也可以偷懒)
# 5.检查未释放对象数量是否异常增长
# 具体来说,如果有数百个未释放对象,那其实是正常的(来源于脚本的Cache)
# 但如果未释放对象数量上千,并且还在不断增加,那就很可能发生了内存泄漏
# 6.在控制台中检查调用栈,寻找其中重复出现的关键词
# 7.将关键词写到下面的配置中,然后重复以上步骤(可选)
# 如果想追踪内存泄漏发生的时间,就修改TRIGGER_KEYWORD,然后时刻检查控制台
# 如果想追踪内存泄漏的速度,就修改STAT_KEYWORDS,检查不同脚本泄漏的数量
# 8.在脚本编辑器界面按下Ctrl+Shift+F,全局搜索关键词,找到发生内存泄漏的脚本
# 9.修复它!(如果看不懂,就去问AI吧)
#------------------------------------------------------------------------------
# 内存泄露检测系统配置(可修改)
TRIGGER_KEYWORD = '我是关键词' # 触发详细调用栈打印的关键词
STAT_KEYWORDS = [:我是关键词, :我也是关键词] # 需要统计的关键词列表
# 扩展Viewport类添加内存释放标记功能
class Viewport
def_before(:dispose){@__disposed__ = true}
def disposed?; @__disposed__; end
end
need_dispose = [Bitmap, Sprite, Window, Plane, Tilemap, Viewport] # 需要监控的对象类型
$caller_stack_db = {} # 存储对象创建信息的全局数据库
not_disposed = [] # 记录当前未释放的对象列表
# 为所有监控类添加创建追踪功能
need_dispose.eachdo |klass|
klass.class_evaldo
# 追踪initialize操作创建的对象
def_after(:initialize)do |*|
record_creation_info(self)
end
alias_method :original_clone, :clone
alias_method :original_dup, :dup
# 追踪clone操作创建的对象
def clone
obj = original_clone
record_creation_info(obj)
obj
end
# 追踪dup操作创建的对象
def dup
obj = original_dup
record_creation_info(obj)
obj
end
end
end
# 记录对象创建时的调用栈和相关信息
def record_creation_info(obj)
stack = Kernel.caller
contains_keyword = stack.any? { |line| line.include?(TRIGGER_KEYWORD)}
# 触发关键词命中时打印完整调用栈
if contains_keyword
puts"[#{TRIGGER_KEYWORD}触发] 对象类型: #{obj.class}"
puts"完整调用栈:"
stack.each{ |line| puts"> #{line}"}
puts"-" * 20
end
# 保存对象创建信息到全局数据库
$caller_stack_db[obj] = {
:stack => stack,
:timestamp => Time.now,
:location => stack.first.to_s
}
end
# 在场景切换时捕获未释放对象
Scene_Base.class_evaldo
def_after :terminatedo
current_not_disposed = []
need_dispose.eachdo |klass|
ObjectSpace.each_object(klass)do |obj|
current_not_disposed