Problem: When Main.TransitionTo() tried to show an error modal about missing multiplayer UI, it triggered ModalManager's static constructor which tried to instantiate modalUIPrefab. Since the asset bundle was missing, modalUIPrefab was null, causing: System.TypeInitializationException: The type initializer for 'KCM.ModalManager' threw an exception. ---> System.ArgumentException: The Object you want to instantiate is null. at KCM.ModalManager..cctor () [0x00017] This created a catch-22: couldn't show error modal about missing UI because the modal itself needed the missing UI. Root cause: ModalManager static constructor didn't check if modalUIPrefab was null before trying to instantiate it. ShowModal() and HideModal() also assumed modalInst was always initialized. Solutions: ModalManager static constructor (lines 25-30): - Add null check for PrefabManager.modalUIPrefab - If null, log warning and return early - Set instantiated = true to prevent re-initialization - Log success message when initialization works ShowModal() method (lines 55-59): - Check if modalInst is null before using it - If null (couldn't initialize), just log the modal content - Format: "MODAL (not shown - UI missing): Title - Message" - Prevents crash and preserves the error message in logs HideModal() method (lines 81-84): - Add null check before calling SetActive - Safe to call even if modal not initialized Results: ✅ No crash when modal UI is missing ✅ Error messages still logged even if not shown visually ✅ Graceful degradation throughout the mod ✅ ModalManager can be safely called from anywhere ✅ Clear logging shows what modals would have appeared 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
88 lines
2.7 KiB
C#
88 lines
2.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using TMPro;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
|
|
namespace KCM
|
|
{
|
|
public class ModalManager
|
|
{
|
|
static GameObject modalInst;
|
|
static bool instantiated = false;
|
|
|
|
static TMPro.TextMeshProUGUI tmpTitle;
|
|
static TMPro.TextMeshProUGUI tmpDescription;
|
|
static Button acceptButton;
|
|
|
|
static ModalManager()
|
|
{
|
|
if (!instantiated)
|
|
{
|
|
// Check if modal prefab is loaded
|
|
if (PrefabManager.modalUIPrefab == null)
|
|
{
|
|
Main.helper.Log("WARNING: ModalManager cannot initialize - modalUIPrefab is null (asset bundle missing)");
|
|
instantiated = true; // Prevent re-initialization attempts
|
|
return;
|
|
}
|
|
|
|
modalInst = GameObject.Instantiate(PrefabManager.modalUIPrefab, Constants.MainMenuUI_T);
|
|
modalInst.SetActive(false);
|
|
|
|
acceptButton = modalInst.transform.Find("Modal/Container/Button").GetComponent<UnityEngine.UI.Button>();
|
|
|
|
|
|
|
|
tmpTitle = modalInst.transform.Find("Modal/Container/Title").GetComponent<TextMeshProUGUI>();
|
|
tmpDescription = modalInst.transform.Find("Modal/Container/Description").GetComponent<TextMeshProUGUI>();
|
|
|
|
instantiated = true;
|
|
Main.helper.Log("ModalManager initialized successfully");
|
|
}
|
|
else
|
|
{
|
|
throw new Exception("ModalManager is a singleton and may only be instantiated once");
|
|
}
|
|
}
|
|
|
|
public static void ShowModal(string title, string message, string buttonText = "Okay", bool withButton = true, Action action = null)
|
|
{
|
|
// If modal couldn't be initialized (asset bundle missing), just log the message
|
|
if (modalInst == null)
|
|
{
|
|
Main.helper.Log($"MODAL (not shown - UI missing): {title} - {message}");
|
|
return;
|
|
}
|
|
|
|
tmpTitle.text = title;
|
|
tmpDescription.text = message;
|
|
|
|
acceptButton.gameObject.SetActive(withButton);
|
|
|
|
acceptButton.gameObject.GetComponentInChildren<TextMeshProUGUI>().text = buttonText;
|
|
|
|
acceptButton.onClick.RemoveAllListeners();
|
|
|
|
acceptButton.onClick.AddListener(() =>
|
|
{
|
|
modalInst.SetActive(false); // Clicked okay
|
|
action?.Invoke();
|
|
});
|
|
|
|
modalInst.SetActive(true);
|
|
}
|
|
|
|
public static void HideModal()
|
|
{
|
|
if (modalInst != null)
|
|
{
|
|
modalInst.SetActive(false);
|
|
}
|
|
}
|
|
}
|
|
}
|