You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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:使用独立脚本资源替代匿名函数

  1. 创建父类逻辑脚本scr_trigger_execute:
var triggered = argument0;
// 父类核心触发逻辑
  1. 修改父对象obj_trigger的Create事件,将execute指向该脚本:
// 保留原有变量初始化代码
execute = scr_trigger_execute;
  1. 创建子类逻辑脚本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;
  1. 修改子类obj_delay的Create事件,覆盖execute为子类脚本:
event_inherited();
delay = 1;
execute = scr_delay_execute;

方案2:使用自定义事件实现重写

  1. 在父对象obj_trigger中创建自定义事件(比如命名为ev_execute),写入父类的execute逻辑:
var triggered = argument0;
// 父类核心触发逻辑
  1. 修改父对象的Room Start事件,调用自定义事件替代直接调用execute:
if (on_enter && (!activated))
{
    event_perform(ev_custom, ev_execute, false);
    if (!multi)
        activated = 1;
}
  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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:46:34