For the complete documentation index, see llms.txt. This page is also available as Markdown.

效果

效果会暂时接管实体,以实现冲刺、攻击、进食动画、过场动画或死亡/重生序列等复杂行为。

效果可用于玩家、NPC 或任何实体。它们在以下情况尤其有用:

  • 由代码控制的移动(冲刺/击退/翻滚)

  • 在短暂序列期间“锁定”玩家输入(进食、复活、过场动画)

  • 具有时限的状态窗口(无敌、减速、眩晕)

  • 与临时状态关联的 UI(重生倒计时)

主动与被动

All Out 支持两种效果:

  • 主动效果:每个实体一次只能有一个。设置新的主动效果会中断当前的主动效果。

  • 被动效果:可同时附加多个(可叠加的增益/减益/状态效果)。

主动效果也会被插入实体的效果列表,因此会显示在 effect_iterator 中,与被动效果一样。

快速入门(一个简单的定时效果)

创建一个继承自 Effect_Base的类,然后将其附加到实体。

Apple_Pop_Effect :: class : Effect_Base {
    sprite: Sprite_Renderer;
    start_scale: v2;
    start_pos: v2;

    effect_start :: method() {
        sprite = entity.get_component(Sprite_Renderer);
        start_scale = entity.local_scale;
        start_pos = entity.local_position;
        set_duration(0.4); // 0.4 秒后自动移除
    }

    effect_update :: method(dt: float) {
        t := get_elapsed_time() / 0.4;

        // 先放大,然后缩小至消失
        scale_curve: float;
        if t < 0.3 {
            scale_curve = lerp(1.0, 1.3, Ease.out_back(t / 0.3));
        } else {
            scale_curve = lerp(1.3, 0.0, Ease.in_back((t - 0.3) / 0.7));
        }

        entity.set_local_scale(start_scale * scale_curve);

        // 稍微向上漂浮
        rise := Ease.out_quad(t) * 0.5;
        entity.set_local_position({start_pos.x, start_pos.y + rise});

        // 在接近结尾时淡出
        if sprite != null {
            alpha := 1.0 - Ease.in_quad(max(0.0, (t - 0.5) / 0.5));
            sprite.color.w = alpha;
        }
    }

    effect_end :: method(interrupt: bool) {
        // 完成时(或被中断时)进行清理
        entity.destroy();
    }
}

将其作为主动效果附加:

效果生命周期

效果基于回调。只需实现你需要的部分:

  • effect_start():效果附加时调用一次

  • effect_update(dt):每帧调用

  • effect_late_update(dt):在每帧的 effect_update

  • effect_end(interrupt):效果移除时调用

主动效果(独占控制)

使用 set_active_effect 用于应当互斥的效果(冲刺、攻击前摇、死亡序列)。

如果该实体已有主动效果,则会以 interrupt = true.

被动效果(可叠加增益 / 状态)

使用 add_passive_effect 用于可以叠加的效果(减速、中毒、护盾、无敌窗口)。

API 参考

Effect_Base

应用 / 移除效果

检查 / 遍历效果

freeze_playerdisable_movement_inputs

  • player_specific.freeze_player = true:完全锁定玩家位置。

  • player_specific.disable_movement_inputs = true:忽略输入,但你的效果仍可移动玩家(冲刺/翻滚)。

两者仅在以下条件下生效: player != null (即效果位于拥有 Player 组件的实体上)。

玩家表情动作

玩家表情动作使用内置的主动效果。开始另一个表情动作会中断当前表情动作,而任何其他主动效果都会阻止新的表情动作开始。移动会中断表情动作并恢复主动画层,但 Emote/T_Pose除外,它允许移动。

当游戏玩法应暂时阻止表情轮盘启动表情动作时,请使用阻止原因:

原因会按条目计数,因此匹配的添加/移除调用很重要。 remove_emote_block_reason 移除一个匹配条目,并返回是否找到该条目。你也可以直接查询或控制内置效果:

try_trigger_emote 返回 false 在动画未装备、表情动作被阻止,或其他类型的主动效果占用玩家时。普通表情轮盘使用相同的路径。

效果示例

冲刺 / 翻滚(主动效果)

无敌窗口(被动效果)

使用被动效果表示无敌状态,并在应用伤害的任何位置检查它。

数秒内变为 2 倍大小(被动效果)

死亡 / 重生序列(带本地 UI 的主动效果)

过场动画锁定(主动效果)

平滑的自定义视觉效果

模拟以固定速率运行,而渲染可以运行得更快。从组件回调中绘制会自动锚定到该组件的实体。对于其他情况:

  • 将另一个实体的世界空间绘制包装在 UI.begin_world_space_ui(entity)UI.end_world_space_ui().

  • 对于不属于实体的移动位置,请保留一个持久的 Position_Interpolation_Helper。传入来自 update(position)UI.push_interpolation_offset的偏移量,然后在绘制后将其弹出。

  • 使用持久的 Float_Interpolation_Helper 包含 UI.quad_fill 来处理变化的条形值。

  • 调用 entity.mark_teleported() 在位置发生不连续变化后。

将插值辅助器保存在持久的组件或 UI 状态中。在绘制方法内创建的辅助器没有可供插值的前一帧。

最佳实践

  • 使用 set_active_effect 当效果在短暂序列中“拥有”实体时(冲刺/攻击/死亡/过场动画)。

  • 使用 add_passive_effect 用于可叠加状态(增益/减益/状态)。

  • 使用 set_duration(...) 用于定时效果,而不是手动计时器。

  • 始终在以下位置恢复所有已修改的状态: effect_end (摩擦力、缩放、动画触发器等)。

  • 在共享的预测路径中运行游戏效果。

  • 从玩家的以下位置绘制与效果相关的 UI: ao_late_update 并使用以下内容进行保护 is_local_or_server().

最后更新于