Forum rules - please read before posting.

Optimizing compile time

edited November 2017 in Technical Q&A
Hi Guys,

Any tips on optimizing compile times for AC projects? I have a lot of custom code and would love to prevent AC from having to recompile with every change. I generally follow the "move 3rd party assets into /Plugins/ folder" - but AC doesn't seem to like this in my initial trials.

Anyone else found ways to improve compile time of AC?

Thanks,
Sebastian
«1

Comments

  • AC won't like being moved because has a few hard-coded references to it's intended directory, but in hindsight that's not really best-practice.  I'll amend things so that only one string references it, so that you can amend it if necessary.
  • That would be very helpful... thanks very much.
  • Sure - it'll be in the next release.  I'm reluctant to expose it as a public variable, but you'll be able to amend it at the top of the Resource.cs file.
  • Hi Chris - finally got around to trying this again. Ended up with this:

    TypeLoadException: Could not load type 'AC.OptionsData'.
    System.Reflection.Assembly.GetType (System.String name, Boolean throwOnError, Boolean ignoreCase) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:398)
  • In what context?  What was the code you wrote that resulted in that, and is there more to the message than that?
  • Apologies, but I've found that there is also another reference that must be changed.  To move AC to a custom directory, do the following:

    1) Create the new folder and move AC to it
    2) In Resource.cs, modify the "mainFolderPath" variable to point to the new directory
    3) In ActionsManager.cs, modify the "folderPath" variable to point to the new Actions directory
    4) In your Actions Manager UI, clear or re-assign your custom Actions folder
    5) Restart Unity
  • Hi Chris,

    Unfortunately still seeing the same behavior - though I'm wondering if this is a difference between a moved folder within the main project assembly, and pushing into one of the "special" assemblies. I tried 3 things while following your instructions:

    1. Moved into /Plugins/
    2. Moved into /Standard Assets/

    3. Finally, I tried leaving it in place and implementing one of the new assembly definition files in Unity 2017.3.

    All 3 time resulted in the following:
  • TypeLoadException: Could not load type 'AC.OptionsData'.
    System.Reflection.Assembly.GetType (System.String name, Boolean throwOnError, Boolean ignoreCase) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:398)
    System.Reflection.Assembly.GetType (System.String name, Boolean throwOnError) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Reflection/Assembly.cs:381)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.GetDeserializationType (Int64 assemblyId, System.String className) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:833)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadTypeMetadata (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:637)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectInstance (System.IO.BinaryReader reader, Boolean isRuntimeObject, Boolean hasTypeInfo, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:269)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:195)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObject (BinaryElement element, System.IO.BinaryReader reader, System.Int64& objectId, System.Object& value, System.Runtime.Serialization.SerializationInfo& info) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:223)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (BinaryElement element, System.IO.BinaryReader reader) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:130)
    System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/ObjectReader.cs:104)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:179)
    System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) (at /Users/builduser/buildslave/mono/build/mcs/class/corlib/System.Runtime.Serialization.Formatters.Binary/BinaryFormatter.cs:136)
    AC.FileFormatHandler_Binary.DeserializeObject[OptionsData] (System.String dataString) (at Assets/Standard Assets/AdventureCreator/Scripts/Save system/FileFormat/FileFormatHandler_Binary.cs:51)
    AC.Serializer.DeserializeObject[OptionsData] (System.String dataString) (at Assets/Standard Assets/AdventureCreator/Scripts/Save system/Serializer.cs:244)
    AC.Serializer.DeserializeOptionsData (System.String dataString) (at Assets/Standard Assets/AdventureCreator/Scripts/Save system/Serializer.cs:432)
    AC.Options.LoadPrefsFromID (Int32 profileID, Boolean showLog, Boolean doSave) (at Assets/Standard Assets/AdventureCreator/Scripts/Options/Options.cs:184)
    AC.Options.LoadPrefs () (at Assets/Standard Assets/AdventureCreator/Scripts/Options/Options.cs:137)
    AC.Options.OnStart () (at Assets/Standard Assets/AdventureCreator/Scripts/Options/Options.cs:45)
    AC.StateHandler.InitPersistentEngine () (at Assets/Standard Assets/AdventureCreator/Scripts/Game engine/StateHandler.cs:92)
    AC.StateHandler.OnAwake () (at Assets/Standard Assets/AdventureCreator/Scripts/Game engine/StateHandler.cs:72)
    AC.KickStarter.SetPersistentEngine () (at Assets/Standard Assets/AdventureCreator/Scripts/Game engine/KickStarter.cs:130)
    AC.KickStarter.OnAwake () (at Assets/Standard Assets/AdventureCreator/Scripts/Game engine/KickStarter.cs:979)
    AC.MultiSceneChecker.Awake () (at Assets/Standard Assets/AdventureCreator/Scripts/Game engine/MultiSceneChecker.cs:46)
  • I take it this was all working before you moved the folder?  What if you move it to a generic folder name, e.g. "FolderTest"? instead of something that Unity has a special meaning for?

    The issue looks to be related to deserializing the Options data in Binary, so I'm not sure how moving the folder can have such an effect.  Does the AC Game Editor etc all load correctly (i.e. the issue is only once the game is run)?
  • Yes it's all working properly in the default folder.

    I did the same tests I mentioned above in addition to the generic folder name you suggested using a fresh project and the 3D demo... it does indeed have to do with the special folder assemblies. Moving into a "FolderTest" and updating the location as you specified does without any serialization issues (but of course no improvement to compilation time either).

    Clicking through the AC editor windows does indeed create a bunch of errors when inside the special folders as well.

    I've read and re-read the Unity docs regarding the compilation order and special folder handling and can't figure out why this would cause issues - but am admittedly no expert.
  • I'll see if I can recreate it, then.  It might be that there's too much "secret stuff" going in the background by Unity wrt these special folder types, but I'll give it a look.
  • Thanks, I appreciate your help. This is probably a complete non-issue when working within the AC system and doing mostly in-editor visual game scripting, but I've hacked your lovely system to bits and am using it in all kinds of strange ways (though I promise the behaviour is the same with the fresh demo). Once I started tracking how much compilation time I was waiting for every week I started on this mission.

    It's funny, doing so much specialty-programming in my day job and here in my Unity hobby, I sometimes get the sense I actually know a thing or two... and then run into one of these issues that makes me feel like a complete beginner programmer again. Oh well!
  • edited December 2017
    Well, I got the same error as yourself - namely it doesn't like binary serialization for some reason once you move it all to the Plugins folder.

    Fortunately, XML saving seems to work just fine - so it's just a matter of enforcing it:

    void OnEnable ()
    {
        SaveSystem.FileFormatHandler = new FileFormatHandler_Xml ();
    }


    (See the "Custom save formats and handling" chapter of the Manual for more on this)

    Put that in a new C# Monobehaviour script and place it in your scene before running the game / Editor window.  Works for me from then on.  Of course, you might not want save files to save in XML format - but I guess you could just move everything back when you're ready to publish.
  • Fantastic... thank you very much. Working here perfectly using custom folders or assembly definition files.
  • I suggest that you change the main scripts folder structure (excluding the demos) to be
    Runtime
    Editor
    and an assembly definition file in each of them with respective settings.
    Since I usually modify the assets I use I move them to custom package folder. So it would be great if it can be moved to a custom package folder as it is without breaking.

  • I managed to get it working by this assembly definition file settings in custom packages folder
    https://pasteboard.co/JHCPlxE.png
    https://pasteboard.co/JHCPDYL.png

    The demos are still in the assets folder and it seems I can play them fine.

    However resources had to be fixed like this

        public static bool IsInPackage {
            get {
                var mainFolder = MainFolderFullPath.Replace('\\', '/');
                var assetsParentFolder = System.IO.Directory.GetParent(Application.dataPath).FullName.Replace('\\', '/');
    
                return mainFolder.StartsWith(assetsParentFolder);
            }
        }
    
        // Path to root AC folder
        public static string MainFolderPath
        {
            get
            {
                return MainFolderPathRelativeToAssets;
            }
        }
    
        public static string MainFolderPathAssetsRegardlessOfPackage {
            get {
                return "Assets/" + mainFolderPath;
            }
        }
    
        public static string MainFolderFullPath {
            get {
                var path = new System.Diagnostics.StackTrace(true).GetFrame(0).GetFileName();
    
                for (int i = 0; i < 4; i++)
                {
                    path = System.IO.Directory.GetParent(path).FullName;
                }
    
                return path;
            }
        }
    
        // Path to root AC folder, relative to the Assets directory
        public static string MainFolderPathRelativeToAssets
        {
            get
            {
                var path = MainFolderFullPath;
    
                if (IsInPackage)
                {
                    path = path.Substring(path.LastIndexOf("Packages"));
                }
                else
                {
                    path = path.Substring(path.LastIndexOf("Assets"));
                }
    
                return path;
            }
        }
    

    and in GetOrCreateSettings I did the following

        internal static ACEditorPrefs GetOrCreateSettings ()
        {
            ACEditorPrefs settings = null;
    
            string fullPath;
            if (Resource.IsInPackage)
            {
                fullPath = Resource.MainFolderPathAssetsRegardlessOfPackage + settingsPath;
            }
            else
            {
                fullPath = Resource.MainFolderPath + settingsPath;
            }
    
            settings = AssetDatabase.LoadAssetAtPath<ACEditorPrefs>(fullPath);
    
            if(settings == null) {
                var editorPrefs = AssetDatabase.FindAssets("t:ACEditorPrefs");
                if(editorPrefs.Length > 0)
                {
                    settings = AssetDatabase.LoadAssetAtPath<ACEditorPrefs>(AssetDatabase.GUIDToAssetPath(editorPrefs[0]));
                }
            }
    
            if (settings == null)
            {
                bool isValid = AssetDatabase.IsValidFolder (Resource.MainFolderPathAssetsRegardlessOfPackage + "/Editor");
                if (!isValid)
                {
                    System.IO.Directory.CreateDirectory(System.IO.Directory.GetParent(fullPath).FullName);
                    isValid = AssetDatabase.IsValidFolder (Resource.MainFolderPathAssetsRegardlessOfPackage + "/Editor");
                }
    

    Now it works fine in the package and I think it should work fine too in the assets folder.

  • A small correction I had to do. packageID is now hard coded. I hope there's a way to get the package id from script.

        public static string MainFolderPathRelativeToAssets
        {
            get
            {
                var path = MainFolderFullPath;
    
                if (IsInPackage)
                {
                    path = path.Substring(path.LastIndexOf("Packages"));
                    var firstIndex = path.IndexOf("/", 0);
                    var secondIndex = path.IndexOf("/", firstIndex+1);
                    path = path.Substring(secondIndex+1);
    
                    path = "Packages/"+packageID+"/" + path;
                }
                else
                {
                    path = path.Substring(path.LastIndexOf("Assets"));
                }
    
                return path;
            }
        }
    
  • ActionManager.cs little fix. You get the idea, I am still working on it, but it's totally doable.
    public string FolderPath
    {
    get
    {
    return Resource.MainFolderPathRelativeToAssets + "/Scripts/Runtime/Actions";
    }
    }

  • Thank you for the suggestions, @stranger.

    I'm wary of making any official change that involves referencing assets while changing locations, as Unity doesn't respect changed locations when re-importing pre-existing assets. Though, your steps are helpful to those looking to make such changes manually.

  • @ChrisIceBox
    Thank you for your comment. You are right. It would be best if unity have plugin and editor extensions from asset store to be installed as a package so that they are not part of the main repository.
    It would be useful if the same plugin is used in multiple projects and have internal modification used by the studio.
    I am not sure if this change is coming soon to the asset store though.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.