Skip to content

Fix Unity 6000.5 compile errors, deprecation warnings, and NLog initialization - #1984

Open
mikhail-dcl wants to merge 4 commits into
alttester:developmentfrom
mikhail-dcl:1983-unity-6000-5-getinstanceid-obsolete
Open

Fix Unity 6000.5 compile errors, deprecation warnings, and NLog initialization#1984
mikhail-dcl wants to merge 4 commits into
alttester:developmentfrom
mikhail-dcl:1983-unity-6000-5-getinstanceid-obsolete

Conversation

@mikhail-dcl

@mikhail-dcl mikhail-dcl commented Aug 25, 2026

Copy link
Copy Markdown

Fixes #1983.

This PR covers two independent Unity 6000.5 problems. The first is the compile errors from the GetInstanceID deprecation, described immediately below. The second is a runtime TypeLoadException that leaves the SDK unusable even once it compiles; it is described in the final section, NLog initialization on Unity 6000.5.

Problem

Unity 6000.4 deprecated Object.GetInstanceID() in favour of Object.GetEntityId(). Unity 6000.5 raised that deprecation to an error, so the SDK's 19 GetInstanceID() call sites across 6 files emit CS0619 and AltTester.AltTesterUnitySDK.dll does not build.

Renaming the call is not sufficient:

  • EntityId's implicit conversion to int is also deprecated as an error, so int id = obj.GetEntityId(); does not compile.
  • #pragma warning disable CS0619 does not suppress an obsolete-as-error, so there is no consumer-side workaround.
  • EntityId.GetRawData() is deprecated in favour of EntityId.ToULong(EntityId), which is the supported accessor.

Changes

Compile errors. New Runtime/Commands/Utils/AltObjectId.cs; all 19 call sites route through it:

public static int GetAltInstanceId(this UnityEngine.Object obj)
{
#if UNITY_6000_4_OR_NEWER
    return unchecked((int)UnityEngine.EntityId.ToULong(obj.GetEntityId()));
#else
    return obj.GetInstanceID();
#endif
}

The narrowing keeps the id 32-bit, matching AltObject.id, transformId and transformParentId. Widening it is a wire-format change across the C#, Java, Python and Robot bindings, and is out of scope.

Deprecation warnings. Clears the 5 CS0618 warnings Unity 6000.5 adds, using the NamedBuildTarget pattern already present in AltBuilder.cs:

  • AltRunner.csFindObjectsOfType<UIDocument>()FindObjectsByType<UIDocument>(), plus an explicit sort (see Ordering).
  • AltGetAllCamerasCommand.cs — adds a UNITY_6000_4_OR_NEWER tier using the no-argument FindObjectsByType<Camera>(); the FindObjectsSortMode overload is now deprecated too.
  • AltTesterEditorWindow.csGetScriptingDefineSymbolsForGroup(BuildTargetGroup)GetScriptingDefineSymbols(NamedBuildTarget).
  • CreateAltPrefab.cs — the GetScriptingDefineSymbolsForGroup result was assigned to a local never read anywhere in the file; the dead assignment is removed.

Version gate

EntityId.ToULong and the no-argument FindObjectsByType<T>() overload both first appear in 6000.4. Compiled against each editor's own reference assemblies with -warnaserror:

Unity unchecked((int)EntityId.ToULong(o.GetEntityId())) FindObjectsByType<T>()
6000.3.1f1 CS0117 — EntityId has no ToULong CS1501 — no such overload
6000.4.0f1 clean clean
6000.5.9f1 clean clean

Gating at UNITY_6000_5_OR_NEWER would leave a CS0618 warning on 6000.4. Versions below 6000.4 keep the existing code paths, so the "unity": "2021.3" floor in package.json is unaffected.

Validation

Unity 6000.5.9f1, batch mode, this repository: AltTester.AltTesterUnitySDK.dll and AltTester.AltTesterUnitySDK.Editor.dll recompile with 0 errors and 0 warnings. Before: 19 errors, 5 warnings.

Also compiled in a separate ~21k-asset project on 6000.5.9f1 with the package linked via file: — no AltTester diagnostics.

Returned ids compared against GetInstanceID reached by reflection:

GameObject (scene)     legacy=-18932  shim=-18932
Transform              legacy=-18934  shim=-18934
Camera component       legacy=-18936  shim=-18936
Material (runtime)     legacy=-18938  shim=-18938
Texture2D (runtime)    legacy=-18940  shim=-18940
Shader (loaded asset)  legacy=52      shim=52

Both id signs are covered, exercising the unchecked narrowing.

Ordering

Of the two call sites moving to FindObjectsByType, one is order-sensitive.

AltGetAllCamerasCommand only enumerates its result (two from ... select projections, no indexing) and has passed FindObjectsSortMode.None since Unity 6 support was added. Order was already unspecified; nothing observable changes.

AltRunner.GetScreenPosition used an ungated FindObjectsOfType<UIDocument>() on all Unity versions and reads uIDocuments[0] twice. FindObjectsOfType orders by instance id; FindObjectsByType does not. The previous ordering is restored explicitly:

System.Array.Sort(uIDocuments, (first, second) => first.GetAltInstanceId().CompareTo(second.GetAltInstanceId()));

Measured on 6000.5.9f1:

  • FindObjectsOfType<T>() orders ascending by instance id, so [0] is the minimum.
  • FindObjectsByType<T>() is unordered: five objects created in sequence returned -1508, -1532, -1520, -1526, -1514, against -1532, -1526, -1520, -1514, -1508 from FindObjectsOfType.
  • After the sort, the sequence is element-for-element identical to FindObjectsOfType and [0] is the same object reference.

System.Array.Sort with a non-capturing lambda adds no allocation and needs no new using. Instance ids are unique, so sort stability is immaterial.

Pre-existing and untouched: the same method indexes [0] without a length check and throws when a scene contains no UIDocument.


NLog initialization on Unity 6000.5

Problem

Unity 6000.5 resolves NLog's assembly location to the host executable path. NLog's scan for optional NLog.*.dll extension assemblies then calls Directory.GetFiles on a file rather than a directory and throws while building ConfigurationItemFactory.Default:

IOException: The parameter is incorrect : 'C:\...\Editor\Unity.exe'
  at System.IO.Directory.GetFiles
  at NLog.Config.ConfigurationItemFactory.GetNLogExtensionFiles
  at NLog.Config.ConfigurationItemFactory.BuildDefaultFactory
  at NLog.Config.ConfigurationItemFactory.get_Default
  at NLog.Layouts.Layout.op_Implicit
  at NLog.Targets.TargetWithLayout..ctor
  at AltTester.AltTesterSDK.Driver.Logging.UnityTarget..ctor

Constructing any layout or target resolves that factory implicitly, so the exception escapes whichever static constructor first reaches a log manager and permanently poisons that type. Both entry points are fatal:

  • EditorAltBuilder..cctor -> EditorLogManager.Instance, reached from AltTesterImportErrorChecker.DeleteAltTesterPrefabIfExists on an EditorApplication delay call. This fires on editor load, so the SDK is broken before anything is run.
  • PlayerAltRunner..cctor -> ServerLogManager.Instance.

Because the failure happens inside a type initializer, the resulting TypeInitializationException is not recoverable for the lifetime of the domain.

Scope

All three log factories construct NLog targets and are equally affected, in three separate assemblies:

log manager assembly
DriverLogManager AltTester.AltTesterUnitySDK.Driver
ServerLogManager AltTester.AltTesterUnitySDK
EditorLogManager AltTester.AltTesterUnitySDK.Editor

Changes

One guard, on DriverLogManager — the lowest of the three assemblies, which the other two already reference — so there is a single implementation rather than three copies:

public static void EnsureConfigurationItemFactory()
{
#if UNITY_6000_5_OR_NEWER
    if (configurationItemFactoryInitialized)
        return;

    configurationItemFactoryInitialized = true;
    ConfigurationItemFactory.Default = new ConfigurationItemFactory(typeof(LogManager).Assembly);
#endif
}

Each buildLogFactory() calls it as its first statement. Three properties matter:

  • The #if is inside the method, so call sites carry no conditional compilation and the method is a no-op on other Unity versions and outside Unity entirely, where UNITY_6000_5_OR_NEWER is never defined.
  • The first-call flag makes it idempotent. Three independent Lazy<LogFactory> instances can each call it; only the first assigns, so no factory discards registrations made by an earlier one.
  • Seeding happens before the #if UNITY_EDITOR || ALTTESTER split in each factory, so the ConsoleTarget and FileTarget paths used by non-instrumented builds are covered as well. A static constructor on UnityTarget would have been a smaller change but would miss those, since that type only compiles under the editor/ALTTESTER branch.

Nothing is lost by skipping the scan: the SDK bundles only NLog.dll (Runtime/3rdParty/nlog.4.7.9) and ships no NLog.*.dll extension assemblies for it to find.

Validation

Unity 6000.5.9f1. All three assemblies — AltTester.AltTesterUnitySDK.Driver.dll, AltTester.AltTesterUnitySDK.dll and AltTester.AltTesterUnitySDK.Editor.dll — recompile with 0 errors, and the log is free of IOException, GetNLogExtensionFiles and TypeInitializationException.

Confirmed in a ~21k-asset project on 6000.5.9f1 with the package linked from this branch: before the change, launching the editor reported the AltBuilder TypeInitializationException above on every load; after it, the editor loads clean.

The editor path is verified directly. The player path (AltRunner -> ServerLogManager) shares the same guard and the same factory, but was not exercised in a player build.

mikhail-dcl and others added 4 commits August 25, 2026 13:43
Unity 6000.5 resolves NLog's assembly location to the host executable
path, so NLog's scan for optional NLog.*.dll extension assemblies calls
Directory.GetFiles on a file and throws while building
ConfigurationItemFactory.Default:

  IOException: The parameter is incorrect :
  'C:\...\Editor\Unity.exe'
    at NLog.Config.ConfigurationItemFactory.GetNLogExtensionFiles
    at NLog.Config.ConfigurationItemFactory.BuildDefaultFactory
    at NLog.Layouts.Layout.op_Implicit
    at NLog.Targets.TargetWithLayout..ctor

Creating any layout or target resolves that factory implicitly, so the
exception escapes the static constructors that reach the log managers and
permanently poisons those types. It surfaces from AltRunner in the player
and from AltBuilder in the editor, the latter during an editor delay call
in AltTesterImportErrorChecker, which makes the SDK unusable on 6000.5.

All three log factories are affected -- DriverLogManager, ServerLogManager
and EditorLogManager -- so the guard lives once on DriverLogManager, the
lowest assembly the other two already reference, and each buildLogFactory
calls it first. Seeding happens before the UNITY_EDITOR || ALTTESTER split
so the ConsoleTarget and FileTarget paths are covered too.

The SDK ships no NLog extension assemblies, so registering NLog's built-in
items directly loses nothing. Guarded by UNITY_6000_5_OR_NEWER and a first
-call flag, so it is a no-op on other Unity versions, outside Unity, and on
every call after the first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@mikhail-dcl mikhail-dcl changed the title Fix Unity 6000.5 compile errors and deprecation warnings Fix Unity 6000.5 compile errors, deprecation warnings, and NLog initialization Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Unity 6000.5: SDK does not compile — Object.GetInstanceID() is obsolete (CS0619)

1 participant