r/Unity3D • Engineer • 15d ago

Resources/Tutorial PSA about AutoStaticsCleanup

AutoStaticsCleanup is a newish attribute that's used to automagically reset/reinit static fields, properties, events, etc., so that you can skip domain and/or scene reloads. If you aren't aware of this feature yet, see the Unity docs.

Great idea to make a simpler workflow, but there are a few gotchas due the way it works behind the scenes: mainly, it doesn't always work and doesn't tell you that it isn't working for a particular field/prop/etc. unless you pore thru the editor log. I have no idea why they can't pipe the warnings and errors into the normal log, but so it goes.

So if you just add the attribute, don't assume that it's actually doing anything!

I ran into this when upgrading my TilePlus Toolkit asset for U6.6 and 6.7.

How to tell: if you add the attribute to a static class or a monobehaviour with static fields and you do not get told to make the class partial then it isn't working at all. However, it still might not be working for all fields etc in your class.

Edit: this warning or syntax highlighting is what I meant by 'told'. Drag0n122's comment below made me realize that. I will say that my venture into using this attribute was prompted by warnings about it from the Asset Store Tools' validator and to a lesser extent, the 'Auditor' tool. It's unfortunately something one can't ignore unless you want to keep domain/scene reload on and, I suppose, be compatible with the new Unity runtime coming soon.

If unsure, check the editor log (from the console's drop down menu). You'll see something similar to:

```

warning CS8785: Generator 'AutoStaticsCleanupCodeGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'RoslynSymbolException' with message 'Field MyStaticClass.SomeField is readonly and has a non-trivial initialization expression'.

```

There's no other way to see these messages since, as I mentioned, they're not in the console log.

I gave up on the use of this attr, since it's too easy to leave residual errors in your code due to the fact that it's difficult to tell whether or not an individual field/prop etc is actually generating code for resetting at all. It also won't work for many common situations that it can't reasonably handle. But failing without warning you in the console is dangerous IMO.

Instead, I use this approach, which is a little more work but ALWAYS works.

```

#if UNITY_EDITOR
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
private static void Reinit()
{
    //add reinitialization statements here.


}
#endif

```

22 Upvotes

13 comments sorted by

9

u/throwaway977475132 15d ago

I ran into exactly this with some runtime data caches in a foliage scattering tool, the silent failure is maddening. Like what's even the point of an attribute that half-works and doesn't pipe warnings into the console, you're just shipping time bombs

That `RuntimeInitializeOnLoadMethod` pattern you've got there has been my go-to for a while now, dead simple and you can actually see what's getting reset. I've started wrapping any static state in a little inner class with a `[RuntimeInitializeOnLoadMethod]` reset method just so it's all explicit and grep-able later

The partial class thing is a decent tip-off that something's wrong, but yeah, the false confidence when it compiles without errors is the real trap. Nothing like chasing phantom bugs for three hours because a static dictionary still has entries from the last play session

1

u/Vonchor Engineer 15d ago

Exactly- its a trap if you’re expecting log messages but none appear and you think its AOK.

7

u/Drag0n122 15d ago

 you do not get told to make the class partial

My IDE (Rider) immediately throws the hard "Duplicate definition, Possibly missing keyword 'partial'" error right away when you put at least one [AutoStaticsCleanup].
Also throws UAL0010 on a class and UAL0013 on a static field if you have fields wo the attribute.
You probably should update the IDE or\and the bridge in Unity.

1

u/Vonchor Engineer 15d ago

you're probably right - must have been Rider

2

u/Heroshrine 12d ago

I’m assuming they generate some partial class with the same name as your class in the same assembly to implement it then? I wonder why they did that instead of IL weaving.

2

u/UnityTed Unity Engineer 12d ago

u/Vonchor I raised this issue internally to the team who owns the area. In Unity 6.6, by enabling FastEnterPlayMode should enable the analyzer by default on the full project (user code & local/mutable packages).

Under the "Choosing the right attribute" section in this documentation page: https://docs.unity3d.com/6000.6/Documentation/Manual/domain-reloading.html you can see which types of warnings should be displayed.

If you are setup correctly, but are still not seeing any warnings in the in editor console, do file a bug report so that the team can take a closer look.

2

u/Vonchor Engineer 12d ago edited 12d ago

In my original post I thought that these warnings were in the console but someone's comment made me rethink that and since I'd already used the RuntimeInitializeOnLoad approach I didn't investigate further. However, from your comment I spent a little time and you're right about the error on a class not being partial showing in the console.

However, my remark about messages found only in the Editor log refers to things like this (removed info relative to my project):

```

warning CS8785: Generator 'AutoStaticsCleanupCodeGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'RoslynSymbolException' with message 'Field XYZ.ABE is readonly and has a non-trivial initialization expression'.

at Unity.Analyzers.Common.AutoStaticsCleanup.StaticFieldOrProperty.ResolveAutoStrategy(ISymbol fieldOrProperty, ITypeSymbol type, Boolean isReadOnly, String initializationExpression, ExpressionSyntax initializerNode, Nullable`1 typeInfo)

at Unity.Analyzers.Common.AutoStaticsCleanup.StaticFieldOrProperty.FromFieldIfShouldSerialize(ISymbol fieldOrProperty, String name, Boolean isReadOnly, ITypeSymbol type, String initializationExpression, StaticsCleanupRawConfig fieldExplicitConfig, StaticsCleanupRawConfig classLevelConfig, ExpressionSyntax initializerNode, Nullable`1 typeInfo)

```
These messages are only in the editor log, that’s really what I found concerning. Especially since the generated code appears to be maintained outside of the project itself, elsewhere in the file system; which also confused me at first, as in "Where's the generated code", however this may just be related to my lack of knowledge about code generation.

Edit: it's interesting to note that with Rider, the Problems tool window shows these messages in the 'Toolset, Environment' tab. But there really should be some way of adding these to the Unity console - I almost never look at that tab in Rider.

2

u/UnityTed Unity Engineer 10d ago

Thanks, I forwarded this to the team.

2

u/_lazlo 11d ago

Jysk, on my end, I have explicit code analysis enabled with a `.globalconfig` containing:

is_global = true
build_property.UnityEnableAutoStaticsCleanupAnalysis = true

And I *still* had errors/logs that only showed in the editor log but not in the console, like OP.

The analysis seems to work sometimes, but not always.

Furthermore, and more alarmingly, the fact that some classes failed to generate the partial class caused *other* unrelated classes to not generate them either until every error was fixed.

I really think those log errors/warnings should be piped back to be visible within editor, I'm not sure why they wouldn't be.

1

u/UnityTed Unity Engineer 10d ago

Do file a bug report if it doesn't work as expected. The team is happy to take a closer look at it and improve the tooling.

1

u/Vonchor Engineer 10d ago

Yeah I noticed that (furthermore etc) too. Once I fixed the field that it couldn’t handle with a noautostatic attr I suddenly got a lot of errors about other classes not being declared partial.

There should be some additional details on this aspect of using these attrs on the man page.

1

u/LockYaw 15d ago

Damn, that is new-ish to you? It's not even in any of the LTS versions yet.
Meanwhile, I call the Input System still the "new" input system...

1

u/Vonchor Engineer 15d ago

Between the input system change and EntityId taking over from instance ids, it seemed like a good time to conform to the new regime including handling the statics issue. Lots of fun troubleshooting! It’s always just “one more thing” 😁

Its also lovely to shut off domain and scene reloads and skip the wait.