The overlay uses shadowed text for better visibility:
private void DrawShadowedLabel(Rect position, string text){ if (textStyle == null) return; // Shadow Color originalColor = textStyle.normal.textColor; textStyle.normal.textColor = Color.black; GUI.Label(new Rect(position.x + 2, position.y + 2, position.width, position.height), text, textStyle); // Main text textStyle.normal.textColor = originalColor; GUI.Label(position, text, textStyle);}
Shadow offset
The shadow is rendered 2 pixels right and 2 pixels down from the main text, creating a subtle depth effect that improves readability over any background.
The OverlayManager class handles overlay lifecycle:
public static class OverlayManager{ public static GameObject overlayObject; public static void CreateOverlay() { if (overlayObject != null) { overlayObject.SetActive(true); // Show if hidden return; } ClassInjector.RegisterTypeInIl2Cpp<ChestOverlay>(); overlayObject = new GameObject("ChestOverlay"); UnityEngine.Object.DontDestroyOnLoad(overlayObject); overlayObject.AddComponent<ChestOverlay>(); Plugin.log.LogInfo("[OverlayManager] Created overlay GUI"); }
Creates the overlay GameObject and registers the ChestOverlay component with IL2CPP. If the overlay already exists, it simply reactivates it instead of creating a duplicate.
HideOverlay()
public static void HideOverlay(){ if (overlayObject != null) { overlayObject.SetActive(false); Plugin.log.LogInfo("[OverlayManager] Overlay hidden."); }}
Hides the overlay without destroying it, allowing it to be shown again later without recreation.
DestroyOverlay()
public static void DestroyOverlay(){ if (overlayObject != null) { UnityEngine.Object.DestroyImmediate(overlayObject); overlayObject = null; }}
Permanently destroys the overlay GameObject and clears the reference.
Both OnDisable() and OnDestroy() call SafeCleanup() to ensure trackers are reset and the overlay is properly hidden regardless of how the component is disabled.