Initialization Race Condition
Subsystem now defers injection by 0.1s to ensure all actors have completed BeginPlay. Added validation for HasBegunPlay() before component initialization.
Dangerous Raw Pointer Caching
Converted BoundInputComponent from raw pointer to TWeakObjectPtr<UInputComponent> to prevent dangling pointer crashes during possession changes.
Input Double-Binding Risk
Added static flags to prevent repeated failed asset loads and bAlreadyBound checks to prevent duplicate input bindings.
Missing Null Checks
Comprehensive null pointer validation added in HandleLookInput, BuildViewQuaternion, and DetectSurface to prevent crashes.
GEditor Nullptr Risk
SOmniWalkDebugger now validates GEditor, WorldContext, World, PlayerController, and Pawn before access to prevent crashes in standalone builds.
Division by Zero
Added SizeSquared() > 0.01f checks before all vector normalization operations to prevent divide-by-zero crashes.
Delegate Type Mismatch
Changed OnPreGravityChange and OnPostGravityChange from single-cast to DECLARE_DYNAMIC_MULTICAST_DELEGATE. Single-cast delegates are incompatible with BlueprintAssignable, causing silent binding failures in Blueprints.
Dual-Path Replication Conflict
Removed conflicting DOREPLIFETIME registrations that fought with the Client_SyncGravityState RPC path. Gravity state now replicates exclusively via throttled 10Hz Client RPC to avoid desync.
CrossProduct Handedness Error
Fixed FVector::CrossProduct(UpVector, WorldForward) to CrossProduct(WorldForward, UpVector) in movement input fix. Incorrect operand order produced inverted right-vector, causing mirrored strafing on non-standard gravity surfaces.
Client-Side Authority Violation
Non-authority clients in RequestDismount and SetWallSliding now return after sending the Server RPC instead of also setting state locally. Prevents replication desync where client state diverges from server truth.
Stale Dismount Trigger
Moved bDismountRequested = false to unconditional clear after the dismount check block. Previously, the flag could persist across ticks and fire unexpectedly when the character next touched a surface.
Double Surface-Detach Event
Added bWasGrounded = false after StartDismount to prevent the grounded-state transition from firing NotifySurfaceDetached a second time in the same tick.
Zero-Vector Gravity Crash
Added early-exit guard in SetGravityDirection when the input vector cannot be normalized (zero or near-zero), preventing NaN propagation through the movement component.
Wall Normal Overriding Floor Data
Wall detection now only uses wall impact normal when HitCount == 0 (no floor hits). Previously, wall hits could override valid floor data during surface transitions, causing gravity flicker.
Camera Pitch Limits Blocking Gravity Transitions
Changed ViewPitchMin/Max, ViewYawMin/Max, and ViewRollMin/Max to -360/360 in AOmniWalkPlayerCameraManager. Default UE limits clamped the camera during gravity rotations, causing sudden snaps.
Gamepad Look Inversion
Added UInputModifierNegate to Gamepad_RightY mapping in AOmniWalkPlayerController. Without it, gamepad vertical look was inverted relative to mouse input.
Look Action Double-Bind on Re-Possession
Stored LookAction = ExistingLookAction after binding to existing IA_Look. The top-of-function guard checked LookAction but it was never set on the existing-action path, causing duplicate bindings on each possession.