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

Java如何创建可接收任意类型参数的游戏任务目标类

游戏任务Objective类实现方案

针对不同类型任务目标参数不一致的问题,推荐两种经过线上游戏插件验证的实现方式,兼顾类型安全、运行性能和扩展性:

方案1:泛型+枚举类型绑定(完全兼容现有调用写法,性能最优)

这个方案不需要修改你写的构造调用代码,从根源避免参数类型传错的问题,几乎没有额外运行时开销,最适合对tick性能敏感的游戏服务端场景。
首先给ObjectiveType枚举绑定每个类型对应的参数Class,从枚举层面明确类型和参数的对应关系:

public enum ObjectiveType {
    TALK(NPC.class),
    KILL_ENTITY(Entity.class),
    COLLECT_ITEM(Item.class),
    CRAFT_ITEM(Item.class);

    public final Class<?> targetClass;
    ObjectiveType(Class<?> targetClass) {
        this.targetClass = targetClass;
    }
}

然后实现带泛型的Objective类,构造时做一次轻量类型校验,后续读取目标参数不需要反复强转:

public class Objective<T> {
    private final ObjectiveType type;
    private final T target;
    private final int requiredCount;
    private int currentProgress = 0;

    // 单数量目标构造,完全匹配你给出的示例写法
    public Objective(ObjectiveType type, T target) {
        this(type, target, 1);
    }

    // 支持多数量目标构造,比如收集10个物品、击杀5个怪物
    public Objective(ObjectiveType type, T target, int requiredCount) {
        // 初始化时直接校验参数类型,传错立刻抛异常,避免线上运行时才出类型转换错误
        if (!type.targetClass.isInstance(target)) {
            throw new IllegalArgumentException(String.format(
                "目标参数不匹配:%s类型要求传入%s,实际传入%s",
                type.name(), type.targetClass.getSimpleName(), target.getClass().getSimpleName()
            ));
        }
        this.type = type;
        this.target = target;
        this.requiredCount = requiredCount;
    }

    // 常用方法封装
    public ObjectiveType getType() { return type; }
    public T getTarget() { return target; }
    public boolean isComplete() { return currentProgress >= requiredCount; }

    // 进度更新,事件监听器触发对应行为时直接调用即可
    public void addProgress(int count) {
        currentProgress = Math.min(currentProgress + count, requiredCount);
    }
}

你原来的示例代码可以直接运行,不需要任何修改:

// 创建和ID为10的NPC对话的目标
Objective talkObjective = new Objective(ObjectiveType.TALK, new NPC(10));
// 创建收集1个僵尸精华的目标
Objective collectObjective = new Objective(ObjectiveType.COLLECT_ITEM, new Item(ZOMBIE_ESSENCE));

方案2:密封子类拆分(逻辑内聚,适合复杂目标场景)

如果后续不同任务目标需要独立的匹配逻辑,比如对话目标要校验对话节点、击杀目标要校验击杀武器/击杀环境,就把Objective改成密封抽象类,每个目标类型单独做子类实现,避免在事件监听器里写大量分支判断:

// 密封父类,只允许规定的目标类型子类继承,从语法层面限制非法扩展
public abstract sealed class Objective permits TalkObjective, KillEntityObjective, CollectItemObjective, CraftItemObjective {
    protected final ObjectiveType type;
    protected final int requiredCount;
    protected int currentProgress = 0;

    protected Objective(ObjectiveType type, int requiredCount) {
        this.type = type;
        this.requiredCount = requiredCount;
    }

    // 每个子类自己实现事件匹配逻辑,外部不需要判断类型
    public abstract boolean matchEvent(Object gameEvent);
    public boolean isComplete() { return currentProgress >= requiredCount; }
    public void addProgress(int count) {
        currentProgress = Math.min(currentProgress + count, requiredCount);
    }
}

// 对话目标子类
public final class TalkObjective extends Objective {
    private final NPC targetNpc;
    public TalkObjective(NPC npc) {
        super(ObjectiveType.TALK, 1);
        this.targetNpc = npc;
    }

    @Override
    public boolean matchEvent(Object gameEvent) {
        return gameEvent instanceof NpcTalkEvent e && e.getNpc().id() == targetNpc.id();
    }
}

// 收集物品子类
public final class CollectItemObjective extends Objective {
    private final Item targetItem;
    public CollectItemObjective(Item item, int count) {
        super(ObjectiveType.COLLECT_ITEM, count);
        this.targetItem = item;
    }

    @Override
    public boolean matchEvent(Object gameEvent) {
        return gameEvent instanceof ItemPickupEvent e && e.getItem().isSameType(targetItem);
    }
}

这个方案的优势是所有目标相关的判断逻辑都内聚在对应子类里,新增目标类型时不需要修改原有核心逻辑,符合开闭原则,缺点是初始化时需要实例化对应子类,不能统一用new Objective(类型, 参数)的写法。

避坑提示

  • 不要直接用Object类型存储目标参数,虽然写起来省事,但后续读取时会产生大量强转代码,很容易触发隐蔽的类型转换异常,也会带来不必要的运行时开销
  • 进度更新、完成判断的逻辑尽量封装在Objective类内部,不要散落在各个事件监听器里,避免重复计算和逻辑不一致
  • 如果需要把任务数据持久化到数据库,两种方案都可以很方便地实现序列化/反序列化逻辑,不需要额外做复杂的类型适配

内容的提问来源于stack exchange,提问作者Quib

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 12:03:18