GML方法继承问题:子类无法覆盖父类execute方法
Pizza Tower模组触发系统:子类方法覆盖异常问题
我在开发Pizza Tower模组的触发系统时,设置了父对象obj_trigger和子对象obj_delay,父对象的核心触发逻辑由execute方法实现。但尝试用子类的execute覆盖父类同名方法时,实际生成了新的匿名脚本(父类对应gml_Script_anon_gml_Object_obj_trigger_Create_0_0_gml_Object_obj_trigger_Create_0,子类生成gml_Script_anon_gml_Object_obj_delay_Create_0_0_gml_Object_obj_delay_Create_0),使用的工具是UndertaleModTool。
相关代码
父对象obj_trigger
Create事件
trigger_id = -1; target_trigger_id = -1; on_enter = 1; on_touch = 0; on_trigger = 0; multi = 0; activated = 0; execute = function(triggered) //gml_Script_anon_gml_Object_obj_trigger_Create_0_0_gml_Object_obj_trigger_Create_0 { var triggered = argument0; }
Room Start事件
if (on_enter && (!activated)) { execute(false) if (!multi) activated = 1; }
子对象obj_delay
Create事件
event_inherited() delay = 1 execute = function(argument0) //gml_Script_anon_gml_Object_obj_delay_Create_0_0_gml_Object_obj_delay_Create_0 { var triggered = argument0 if (triggered && (!on_trigger)) return; if (triggered && activated) return; if (triggered && (!multi)) activated = 1 if ((delay == 0)) alarm[0] = 1 else alarm[0] = (delay * room_speed) }
问题原因
这不是UndertaleModTool的问题,而是GML中匿名函数的赋值逻辑导致的:
- 父类在Create事件里给
execute变量赋值了一个匿名函数,子类调用event_inherited()继承父类的变量后,又给execute重新赋值了一个新的匿名函数——这本质是变量赋值覆盖,不是面向对象中的方法重写。 - UndertaleModTool会给每个匿名函数生成唯一的脚本ID,所以子类的新匿名函数会得到独立的标识,这是工具的正常行为。
解决方案
方案1:使用独立脚本资源替代匿名函数
- 创建父类逻辑脚本
scr_trigger_execute:
var triggered = argument0; // 父类核心触发逻辑
- 修改父对象
obj_trigger的Create事件,将execute指向该脚本:
// 保留原有变量初始化代码 execute = scr_trigger_execute;
- 创建子类逻辑脚本
scr_delay_execute:
var triggered = argument0; if (triggered && (!on_trigger)) return; if (triggered && activated) return; if (triggered && (!multi)) activated = 1; if (delay == 0) alarm[0] = 1; else alarm[0] = delay * room_speed;
- 修改子类
obj_delay的Create事件,覆盖execute为子类脚本:
event_inherited(); delay = 1; execute = scr_delay_execute;
方案2:使用自定义事件实现重写
- 在父对象
obj_trigger中创建自定义事件(比如命名为ev_execute),写入父类的execute逻辑:
var triggered = argument0; // 父类核心触发逻辑
- 修改父对象的Room Start事件,调用自定义事件替代直接调用
execute:
if (on_enter && (!activated)) { event_perform(ev_custom, ev_execute, false); if (!multi) activated = 1; }
- 在子类
obj_delay中重写ev_execute自定义事件,写入子类的逻辑:
var triggered = argument0; if (triggered && (!on_trigger)) return; if (triggered && activated) return; if (triggered && (!multi)) activated = 1; if (delay == 0) alarm[0] = 1; else alarm[0] = delay * room_speed;
内容的提问来源于stack exchange,提问作者SalticHash
相关产品推荐
相关产品推荐

