Skip to main content

1.2.6 — Respawn-safe character references

What changed

Live character getters (runtime)

_PulseGetChar(), _PulseGetHRP(), _PulseGetHumanoid(), and _PulseGetAlive() no longer cache the character at CharacterAdded time. They now read LocalPlayer.Character directly on every call.

Before (1.2.5): The runtime held _char, _hrp, _humanoid locals updated via a deferred CharacterAdded connection. Between CharacterRemoving and the deferred refresh there was a window where these still pointed to the destroyed character — and any component that called them during that window received a stale (or destroyed) instance.

After (1.2.6): Every call reads the live LocalPlayer.Character property. The result is always correct: nil while no character exists, the new character instance immediately after spawn. No deferred refresh, no race window.

This means most components require no special respawn handling at all. If you read character refs inside a on Heartbeat or on RenderStepped callback, they automatically reflect the current character on the next tick after respawn.

_LocalPlayer available in all component IIFEs (compiler)

Since 1.2.5, each .rblua component is compiled into its own isolated function scope (IIFE) for the 200-local budget fix. The compiler exported func to _G.__rb_func for IIFEs to import, but forgot _LocalPlayer.

Effect: Inside every IIFE component, _LocalPlayer was nil. This silently broke:

  • Any direct use of _LocalPlayer (e.g. _LocalPlayer.Character, _LocalPlayer:GetAttribute(...))
  • on CharacterAdded {} and on Respawn {} blocks — they generate _LocalPlayer.CharacterAdded:Connect(...) which errored, so the connection was never registered. Respawn handlers silently did nothing.
  • on CharacterRemoving {} — same.

Fix: The compiler now also exports _G.__rb_lp = _LocalPlayer before the first IIFE, and each IIFE imports local _LocalPlayer = _G.__rb_lp alongside func. All _LocalPlayer usage and all respawn connections now work correctly.

Impact

  • Components using _PulseGetChar() / _PulseGetHRP() / _PulseGetHumanoid() in callbacks: automatically correct after respawn — no source changes required.
  • Components with on CharacterAdded {} or on Respawn {}: these connections are now actually registered and fire correctly on every spawn.
  • Components using _LocalPlayer directly (e.g. _LocalPlayer.Character in a loop): now work in all builds.

No source changes required

All fixes are in the framework (runtime + compiler). No .rblua component files need to change.

Respawn pattern reference

For components that need to re-run logic on each spawn, use:

-- Preferred: no character parameter needed
on Respawn {
_cachedThing = nil -- clear stale cache
task.wait(1) -- wait for game state to settle
-- re-initialize
}

-- When you need the new character instance
on CharacterAdded {
-- _ is the new character model
-- 'character', 'hrp', 'humanoid' locals are already live — no update needed
}

For everything else (reading character refs in callbacks), no explicit respawn handling is needed — the live getters handle it transparently.