[A13 and Assets loading]

Started by Fluffy (l2032), April 08, 2016, 03:43:53 AM

Previous topic - Next topic

Fluffy (l2032)

The following is a breakdown from what others and I have found when trying to use textures in .dlls. This is by no means final information, as there's quite a few oddities going on that we don't understand. I'll try and keep this thread updated with new developments.

See also my bug report here.


definitely_not_fluffy [09:30]
ok so here's the breakdown

[09:30]
mods are loaded in a separate thread

[09:31]
which means any 'assets' (textures, sounds, materials, etc) won't load correctly

[09:31]
you get a vague 'couldn't find it' error, which is very misleading

[09:31]
there's theoretically two solutions

[09:32]
the first, and prefered solution is to put a [StaticConstructorOnStartup] attribute above any classes that have static resources defined in them

[09:32]
that ​_should_​ cause them to be loaded in hte main thread, before anything else

[09:32]
this doesn't actually appear to work however

[09:33]
the seond solution is to somehow defer loading of textures until after the main mod loading phase is complete

[09:33]
again, there's two ways

[09:33]
the first is to call LongEventHandler.ExecuteWhenFinished( Action ) in the constructor

[09:34]
if the mod is loaded in the asynchchronous thread, your action is then queued to be executed on the main thread after mod loading is complete

[09:34]
this works for me, but appears not to work for some others

[09:34]
the final solution is to not load textures at all until you need them

[09:34]
e.g. do an if (texture ==null) loadTexture kind of thing in the Draw() method (or something similar).

[09:35]
that's a bit risky, since if it fails, it'll keep failing very noisily

[09:35]
but the approach should work


And a little more background info from Ison through Skullywag on how it's supposed to work:
skullywag [11:59]
added a C# snippet
This happens because from now on mods are loaded in a different thread. This, combined with the fact that it's impossible to use Unity's functions like loading a texture in threads other than the main one, means that you get an error in such cases. Does your new class have any static resources like Texture, Material or Graphic? If so, it means that during loading the game, when an object of this class is loaded, its static constructor is called and the game tries to load a texture in a different thread. With StaticConstructorOnStartup attribute, class' static constructor is called in the main thread before loading everything else.
Add Comment
skullywag [12:00]
he also said this, which might mean something to you guys:
skullywag [12:00]
added a C# snippet
Making those Material fields non-static doesn't work, because they are instantiated from a different thread during loading an instance of Building_WindTurbineStuffed. You can also schedule a task to be executed from the main thread after the loading has finished like this: LongEventHandler.ExecuteWhenFinished(() => DoSomething()); but in your case you should just use static fields and [StaticConstructorOnStartup].
Add Comment
skullywag [12:01]
and heres the bit about the game laoding thingy
skullywag [12:01]
added a C# snippet
It's because static constructor is called only once when a class is first used, so it won't be called again until you restart the game. If a class is first used during gameplay (e.g. you build a wind turbine), then wind turbine's textures are loaded in the main thread so everything's fine, but if it's first used during loading (e.g. you try to load an instance of a wind turbine), then it throws errors because it tries to load a texture from a different thread.
Add Comment
definitely_not_fluffy [12:01]
that is actually an entrance point for bootstrapping right there, isn't it?
[12:02]
if we can set code to be run on main thread, we can get to gameobjects and everything
skullywag [12:02]
mebbe
[12:02]
like i said it might mean more to you guys than me (edited)
definitely_not_fluffy [12:02]
this is really good info to have, thanks!