Quick answer: Discord rate-limits Rich Presence updates to once every 15 seconds. Batch the latest state and call UpdateActivity at that cadence. Call RunCallbacks every frame.

Your game updates Rich Presence on level change. The first level’s presence shows correctly; subsequent levels never update Discord, even though your code calls UpdateActivity each time. The updates are being silently rate-limited.

The 15-Second Rate Limit

Discord caps Rich Presence updates per client to one every 15 seconds. Calls within the window are silently dropped — no error returned. Without throttling on your side, rapid presence changes mostly disappear.

The Fix: Coalesce Updates

float _lastUpdateTime = -100;
DiscordActivity _pendingActivity;
bool _hasPending = false;

void SetActivity(DiscordActivity act) {
    _pendingActivity = act;
    _hasPending = true;
}

void Tick(float dt) {
    core->RunCallbacks();
    if (_hasPending && (currentTime - _lastUpdateTime) >= 15.0f) {
        core->ActivityManager().UpdateActivity(_pendingActivity, [](auto result) {});
        _lastUpdateTime = currentTime;
        _hasPending = false;
    }
}

The latest pending activity is sent at most once every 15 seconds. Rapid state changes coalesce; the most recent one wins.

RunCallbacks Per Frame

RunCallbacks drives the Discord SDK’s internal event loop. Without it, callbacks queue but never fire. Call it from your game’s main loop:

void Game::Tick() {
    DiscordClient::Instance()->Tick(dt);
    // rest of game tick
}

Discord Not Running

If Discord isn’t running when the game starts, Core::Create returns NULL. Handle gracefully:

if (Core::Create(CLIENT_ID, DiscordCreateFlags_NoRequireDiscord, &core) != DiscordResult_Ok) {
    UE_LOG(LogTemp, Warning, TEXT("Discord not running, Rich Presence disabled"));
    core = nullptr;
}

The NoRequireDiscord flag prevents Discord from auto-launching. Your game continues without presence; if the player launches Discord later, retry init periodically.

Verifying

Open Discord. Launch your game. Verify status shows your initial presence. Change levels every 5 seconds; presence should update roughly every 15 seconds with the latest level info. Discord’s Activity log (in your profile) shows the most recent updates.

“Discord rate-limits; coalesce updates. RunCallbacks every frame or callbacks never fire. Handle Discord-not-running gracefully.”

Rich Presence is best when it reflects meaningful state changes — not every UI tweak. 15-second cadence matches that intent naturally.