2 Commits
Author SHA1 Message Date
Drew MochakandManlyMarco 7cb1246fcc Survive stripped UnityEngine.Application members during chainloader init (#1391)
Two related failures on aggressively stripped Unity Mono builds:

1. InitializeLoggers reads Application.unityVersion, which the managed
   code stripper can remove. The version is only used for an
   informational log line, but a MissingMethodException there aborts the
   rest of chainloader initialisation. Read it defensively instead.

2. UnityChainloader.Initialize caught every exception, logged it as
   Fatal, and returned normally. StaticStart then called Execute() on a
   chainloader that was never initialised, so BepInEx logged
   "Chainloader startup complete" while every plugin silently never ran.
   Rethrow so a failed init cannot be mistaken for a successful one.

Verified on Beacon Pines (Unity 2021.3.45f1, Mono, x64), which strips
both Application.unityVersion and the log-callback members.

Co-authored-by: ManlyMarco <39247311+ManlyMarco@users.noreply.github.com>
2026-09-01 06:58:43 +02:00
Drew Mochak 6d82b2e5fc Don't kill the chainloader when Unity log callbacks are stripped (#1389)
UnityLogSource's static constructor falls back to
Application.RegisterLogCallback when Application.logMessageReceived is
absent. Unity's managed code stripper can remove both, in which case
GetMethod returns null and the unguarded Invoke throws a
NullReferenceException out of the static constructor.

That exception propagates through chainloader initialisation, so the
chainloader never starts and no plugins load. The failure is close to
undiagnosable: LogOutput.log ends at "Preloader finished" with no error,
and the exception only appears on stdout.

Unity log forwarding is optional, so warn and continue instead of taking
the whole loader down.

Seen on Beacon Pines (Unity 2021.3.45f1, Mono), whose
UnityEngine.Application has neither member.
2026-09-01 06:56:05 +02:00