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

Godot 3.5.1中动态调用自定义按品质随机选择方法失败的问题求助

Godot 3.5.1中动态调用自定义按品质随机选择方法失败的问题求助

嘿,我完全懂你现在的困扰!跟着教程搭好了基础的随机物品系统,想扩展成按抽到的品质来随机英雄,结果动态调用方法的时候直接翻车了对吧?咱们来一步步拆解问题,找到解决办法~

问题出在哪?

你用的call("RandomPicker.new().pick_random_" + Portrait1 + "(items_array)")写法是有问题的——call()方法只能调用当前节点对象的方法,没办法直接解析这种“创建实例+调用方法”的复合字符串。而且这种写法也很容易出错,比如拼写问题或者方法不存在时直接报错。

解决方案1:先实例化Picker,再动态调用方法

先创建RandomPicker的实例,再用call()调用它的对应方法,这样就符合Godot的方法调用规则了:

func _on_RollButton_pressed():
    randomize()
    var picker = RandomPicker.new()
    # 先抽到品质
    var Portrait1 = picker.pick_random_item(items_array)
    
    # 动态调用对应品质的抽取方法
    var method_name = "pick_random_" + Portrait1
    if picker.has_method(method_name):
        var champion = picker.call(method_name, items_array)
        # 这里处理抽到的英雄,比如赋值给UI之类的
        print("抽到的", Portrait1, "英雄:", champion)
    else:
        print("警告:找不到对应品质的抽取方法 -> ", method_name)

这里加了has_method()检查,能避免因为拼写错误(比如你代码里写的item.commmon多了一个m!)或者没有定义对应方法导致的崩溃,更安全。

解决方案2:用通用方法替代多个重复的pick函数(更推荐)

你现在写了pick_random_item、pick_random_Common等多个逻辑几乎一样的方法,其实可以合并成一个通用的“按品质抽取”方法,这样以后加新品质(比如Epic、Legendary)也不用写新方法,维护起来轻松很多:

第一步:修改RandomItem.gd,用统一的品质字段代替单个布尔值

把原来的export(bool) var common: bool = false改成通用的品质字符串(或者用枚举更规范,不过字符串更直观):

extends Resource
class_name RandomItem

export(String) var VALUE
export(int) var PICK_CHANCE: int = 1
export(bool) var can_be_picked: bool = true
export(String) var quality: String # 比如填"Common"、"Uncommon"、"Rare"等

第二步:在RandomPicker.gd里写通用的抽取方法

extends Node
class_name RandomPicker

export(Array, Resource) var items_list: Array = []

# 原来的随机抽品质方法保留
func pick_random_item(items_array: Array = items_list):
    var chosen_value = null
    if items_array.size() > 0:
        var overall_chance: int = 0
        for item in items_array:
            if item.can_be_picked:
                overall_chance += item.PICK_CHANCE

        var random_number = randi() % overall_chance
        var offset: int = 0
        for item in items_array:
            if item.can_be_picked:
                if random_number < item.PICK_CHANCE + offset:
                    chosen_value = item.VALUE
                    break
                else:
                    offset += item.PICK_CHANCE
    return chosen_value

# 新增:按指定品质随机抽取的通用方法
func pick_random_by_quality(target_quality: String, items_array: Array = items_list):
    var chosen_value = null
    if items_array.size() == 0:
        return chosen_value

    # 1. 计算该品质下所有可抽物品的总权重
    var overall_chance: int = 0
    for item in items_array:
        if item.quality == target_quality and item.can_be_picked:
            overall_chance += item.PICK_CHANCE

    # 如果该品质没有可抽物品,直接返回
    if overall_chance == 0:
        print("没有可抽取的", target_quality, "品质英雄!")
        return chosen_value

    # 2. 生成随机数
    var random_number = randi() % overall_chance

    # 3. 遍历抽取对应品质的物品
    var offset: int = 0
    for item in items_array:
        if item.quality == target_quality and item.can_be_picked:
            if random_number < item.PICK_CHANCE + offset:
                chosen_value = item.VALUE
                break
            else:
                offset += item.PICK_CHANCE

    return chosen_value

第三步:调用的时候就超简单啦

func _on_RollButton_pressed():
    randomize()
    var picker = RandomPicker.new()
    # 先抽品质
    var current_quality = picker.pick_random_item(items_array)
    # 再按品质抽英雄
    var chosen_champion = picker.pick_random_by_quality(current_quality, items_array)
    
    print("抽到品质:", current_quality, ",对应英雄:", chosen_champion)
    # 这里把英雄赋值到UI上即可

额外小建议

  1. 可以把RandomPicker设置成AutoLoad单例,这样不用每次点击都new()一个实例,不仅更高效,还能统一管理物品列表,避免重复加载资源。
  2. 检查拼写!你代码里的if item.commmon:多了一个m,这种小错误很容易导致逻辑失效,一定要注意~

备注:内容来源于stack exchange,提问作者Jellyfish

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 09:38:06