Search Unity

Problems compiling DLLs from MonoDevelop

Discussion in 'Scripting' started by guavaman, Aug 24, 2012.

  1. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Ahh, I see. That makes sense. It's just like changing any other normal class in your code as the MB handles the serialization. Since MB uses the field name and doesn't actually store the data type, there's no problem with namespaces.

    Code (csharp):
    1. --- !u!114 387100048
    2. MonoBehaviour:
    3.   m_ObjectHideFlags: 0
    4.   m_PrefabParentObject: {fileID: 0}
    5.   m_PrefabInternal: {fileID: 0}
    6.   m_GameObject: {fileID: 387100046}
    7.   m_Enabled: 1
    8.   m_EditorHideFlags: 0
    9.   m_Script: {fileID: -510640, guid: fca4563f0aecec144bc47b2d7906c962, type: 1}
    10.   m_Name:
    11.   specialData:
    12.     x: This is wonderful data!
    13.   stringArray:
    14.   - array stuff 1
    15.   - array stuff 2
    16.   - array stuff 3
    17.   - array stuff 4
    This is the output from the .scene file for the GameObject with a MonoBehaviour applied to it which has the serialized class assigned to it. The line specialData is the serialized data from the class object. Notice there is no fileID or guid required to link it back to its target. The serialized data is just stored in the MonoBehaviour directly under the name of the field. MonoBehaviour determines what fields it has by getting them like any other class reference. Thankfully, there's nothing to break here.

    If you decide to go playing with the MonoBehaviour fileId and guid reference and change it to something else, the serialized data will still be there (at least until the next save) even if your new MB class has no fields or non-matching fields. It just matches them up by field name. So whatever fields find a matching name and type, it will use that serialized data. Though type is not explicitly stated, just inferred through the formatting, and there is only 1 object-reference type field (the one with fileId and guid). Serialized class objects just end up as nested trees of data under the field name.
     
    Last edited: Sep 1, 2012
  2. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Just an update...

    I decided to abandon the compiling with Unity's internal compiler because it brought with it too clunky a workflow. And because I'm using ILMerge now as a workaround to the base class problem, it can output a .NET 2.0 dll anyway from the merged 4.0 dlls MonoDevelop outputs. So I've got a better workflow without resorting to a bunch of external programs, post-build commands, and batch files.

    Also, I finished converting my project to use the DLLs instead of the loose scripts and my compile times are now down to 2-3 seconds compared to 15+ before. Excellent! I've outlined the whole conversion process here.

    Next step: Convert everything (or at least some stuff) to C# and ditch MonoDevelop. :)
     
  3. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I have had data loss again, but this time on ScriptableObject assets...

    I may also have noticed a pattern, the data is lost for ScriptableObject's and MonoBehaviours whom have ExecuteInEditMode attribute attached. Maybe a coincidence...
     
  4. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    I have decided to avoid using ExecuteInEditMode for assets. Probably just use for procedural mesh generation (so that it can be seen in editor). I am lucky in that my BrushDatabase can automatically load brushes upon scanning them.
     
  5. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Ugh, sorry to hear that. I was thinking if you enabled text-based asset serialization and recorded all your fileIds you could check the scene/prefab file and see if that fileId changed to find out if that's the source of the problem. If you caught it fast enough (before saving the object again and possibly wiping out the serialized data) you could find/replace the old id with the new id to repair it. It sounds terrible to have to be constantly watching to see if some random object lost its data though. I haven't had time to continue working on the game code since I moved to DLLs so I haven't tested thoroughly (been working on converting the project to C#). When I get a chance to test, I will post here if I have any problems.
     
  6. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    This is only happening in my sandbox environment for testing my extension, but I would hate this to happen in a real application upon installing update. The problem seems to occur either when DLLs are replaced, or when scripts are compiled...

    For some reason it seems that an internal failure (that is not reported, console is clean) is occurring which is aborting the internal deserialisation, and then Unity happily serializes the default values. This is speculation of course, but it seems highly plausible.

    Unfortunately I thought that this problem was solved... Now that I am using scriptable object assets it doesn't gracefully add a broken MonoBehaviour, instead it completely obliterates the asset!
     
  7. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    @numberkruncher: You mentioned having this prob with .dlls compiled from Visual Studio. Was this from there or MD?
     
  8. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    This was from Visual Studio, but it must surely happen with MonoDevelop also given that on Windows it uses the same compiler. I have switched to 3.5 framework with 2.0 runtime for better compatibility with Unity.

    This problem has not happened literally since I last posted here saying it seems to be better. I am hoping that perhaps avoiding that attribute will solve the issue. I didn't spot that previously, but to be honest I hadn't even considered it...
     
  9. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    With Visual Studio it is easier and faster to do incremental builds for trial-and-error scenarios. This was not something that was very comfortable with MonoDevelop (because it is slow and crashes a lot). So perhaps I its all about odds and compiling more frequently just increases them.

    I would switch back to MonoDevelop for a while to see if it happens, but tbh I cannot bare the IDE.
     
  10. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Oh yeah, I forgot you had determined that. So it's very likely this would happen with both.

    Does it delete the asset from disk at the time of import of the new DLL? It shouldn't as it should not even touch the .scene or .prefab file unless you save the scene again. The serialized data format is extremely simple. The only links it maintains are fileID and GUID. Everything else is just raw data. I don't see how it could be anything but one or both of those values getting changed. I will do some tests with scriptableobject myself to see if the serialized data structure is any different than Monobehaviour.

    Are you updating your DLL with Unity open? Also, is the asset an in-scene-only asset or a prefab on disk?

    MonoDevelop is disgusting. I've spent the last week converting my project to C# mainly to get away from that horrid piece of garbage. Even if I have to spend 2 weeks doing this it's all worth it if I never have to see that program again.
     
    Last edited: Sep 13, 2012
  11. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    In this case the damage occurred to .asset files with ScriptableObject classes.

    The issue seems to occur when Unity reloads the DLL and recompiles the scripts in the asset folder. Baring in mind that I do not close Unity to update the DLLs (that would be painful!)

    My use of the word obliterate was probably excessive, the .asset file remains but the data is reset to the default values. These are assets that are used by editor scripts, so when the DLLs are updated the assets get reloaded for use in the editor.

    Oh yeah! lol

    I doubt the issue would occur if the DLLs were updated when Unity was closed. But this is not a realistic solution because when the DLLs are updated via the asset store, Unity will of course be running!

    .asset file on disk

    Yeah it is pretty awful. It seems okay for really simple scripts but when it comes to proper coding it does suck.
     
  12. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Edit: Just read your above post. This is probably irrelevant. I wasn't aware of the .asset file usage.

    Ok, ScriptableObject is a bit different than dealing with monobehaviours. A couple of things I noticed:

    1) There are 2 separate links in the .unity scene file for an SO:
    fileId (internal) which links the MonoBehaviour containing the SO to another "MonoBehaviour" entry in the file which contains the serialized data.
    fileId + GUID which links the SerializedObject ("MonoBehaviour") to its original script file / DLL.
    The SerializedObject seems to be saved in the file as a MonoBehaviour class (which is why I put it in quotes).

    2) SO always stores data in the .unity scene file, never in a prefab. (Or at least I cannot get the prefab to save the SO data. Maybe if you create the SO directly on the prefab...)

    I modified all the fields properly AFAIK using SerializedObject and SerializedProperty. Just doing some general playing around with a gameobject/prefab I was able to lose serialized data a number of times. One thing I noticed during testing was that if I ever got the "cleaning up leaked data" message at any point, the next time I loaded the scene the SO data would be gone even if I re-created the SO data before saving. I'm probably doing something wrong, but I've used SerializedObject/Property before to successfully manipulate data on scene objects and prefabs without this error.

    Also, several times I was able to get the internal fileId pointing to the serialized data to change which also seemed to break it after a save + load even though the SO data was displayed correctly before the save.
     
    Last edited: Sep 13, 2012
  13. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    I see. Have you tried looking at the .asset file in a text editor after if fails? I just made one and its extremely simple just like a .unity or .prefab file. The ScriptableObject is just stored as "MonoBehaviour" again with a fileId + GUID pointing to the script/DLL that contains its class plus the data itself. I would be surprised if the data was actually wiped from the .asset file upon load. I would think that would only happen at the time of updating the asset on disk. Perhaps its just not loading the data right for some reason?... But you did mention this happening to a script that updates in the editor. Is your script updating the .asset file on disk frequently? If it does, that might explain why the .asset gets wiped.

    Hmm, actually if it has to reload the assets when you update the DLL it probably would happen even if the editor was closed because the next time you open it after changing the DLLs it would just reimport at that time and probably do the same thing.
     
  14. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
    That's right, ScriptableObjects can only be stored in scene or a separate .asset file (which can be referenced of course by a MonoBehaviour).

    Not had that one before. I had similar with temporary textures (before I learnt about hideFlags).

    I know that once you make changes to an asset that you are supposed to use EditorUtility.SetDirty to ensure that changes are persisted. I am not sure how this applies with ScriptableProperty/ScriptableObject because that is a special case.

    I didn't but if it happens again I will remember to.

    That's what I am thinking. It seems that the data from the .asset file is not loaded and then those changes are being immediately persisted (perhaps triggered by the reloading of assemblies). But no errors are being logged at all...

    In the scenarios where data has been lost no changes were made to the .asset files. The assets were loaded for use (they represent brushes) but they are not actually used before or after the replacing of the DLLs (in this most recent case). I was working on something entirely separate.

    The issue has only occurred when hot-changing the DLLs, though that is not to rule that possibility out.
     
  15. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    C# DLL users might want to take a look at this post. I got some baffling results when doing some performace tests with DLLs vs script files.
     
  16. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
  17. numberkruncher

    numberkruncher

    Joined:
    Feb 18, 2012
    Posts:
    953
  18. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    5,632
    Thanks for the heads up. Unfortunately, I can't get it working. I was using the same namespaces in my previous tests. I'm gussing the difference might be that I'm trying to permanently store the MonoBehaviour on an object in scene/prefab and the poster (Bunny83) may not be, or else hasn't tested that far ahead. I never had the problem he did where it couldn't locate the class because I was always using the same namespace for both (undefined). I reported it to Unity as a bug. I didn't hear back from the bug team, but the person at support@ I was corresponding with seemed to acknowledge it as a bug. I let him know about my ILMerge workaround as well.
     
    Last edited: Sep 28, 2012
  19. Lambda Knight

    Lambda Knight

    Joined:
    Mar 8, 2011
    Posts:
    23
    slumtrimpet likes this.