Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

Weaver - Get rid of your magic strings

Discussion in 'Assets and Asset Store' started by Kybernetik, Dec 3, 2018.

  1. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,012
    Hey, I'm using weaver light only for the Animator constants generation and I have a question. Since you directly save the ints and not run StringToHash at runtime, are you sure StringToHash returns the same stuff in all platforms supported by Unity?

    I guess what I'm saying is: I feel a bit uneasy with the Hash not being calculated at run-time and I can't find any specific information. Have any of your users had any problems with this?
     
    Last edited: Jul 18, 2021
  2. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I've never considered that they might be using a hash algorithm which gives different results depending on the platform. I haven't had any problems between Windows and Android.

    The algorithm they use isn't documented, but pressing F12 on the Animator.StringToHash method shows that it has a
    [NativeMethod(Name = "ScriptingStringToCRC32", IsThreadSafe = true)]
    attribute which means they should be using the CRC32 algorithm (unless they changed the algorithm without renaming the method) which I believe should give the same results on all platforms, though I'm not an expert on that.

    If you discover a discrepency, it would be easy enough for me to make it generate the script using static readonly fields that call StringToHash in their field initializers, but that would be less efficient and the generated HashToString method wouldn't be able to use a switch statement because it needs constants for the cases.
     
    AcidArrow likes this.
  3. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Good news everyone: Weaver v6.2 is now available on the Asset Store.

    It's a pretty small update, but it has a few new things:
    • Dropped support for Unity 2018.4. Tested versions are now 2019.4 (LTS), 2020.3 (LTS), and 2021.1 (Latest Stable). Weaver v6.1 is still available for Unity 2018.4 though.
    • Changed all Project Constants to be disabled by default.
    • Moved the Weaver Window menu function to Window/General/Weaver.
    • The Tag Constants system I posted a while ago.
    • A fix for the shader issue @Bezoro mentioned.
    • A fix for the issue @BoteRock was having. Referencing components using asset injection should work properly now.
    • Added the FixProjectDefinition script from my previous post.
     
    Bezoro likes this.
  4. mklasson

    mklasson

    Joined:
    Oct 30, 2018
    Posts:
    28
    Hi,

    I'm having some problems trying to use Weaver with asmdefs. AFAIK when I'm trying to access the generated procedural assets from within a folder with an asmdef I need to either move the default Procedural Assets folder somewhere I can already access, or make another referenced asmdef for the Procedural Assets folder.

    The problem is that doing either of those things causes Weaver to then regenerate the procedural asset files again whenever I save, even with no changes. It seems to no longer be able to understand what's already there, even if I move the folder to somewhere inside Plugins/Weaver.

    I'm guessing this has to do with it being Weaver Lite and the Lite assembly not having a reference to the assembly the PA is now in?

    https://forum.unity.com/threads/referenging-package-dlls-in-external-projects.609601/#post-4080826 seems to suggest it's not really even fixable if I understand the problem correctly: "In addition, we don't currently support pre-compiled assemblies (DLL files built outside Unity, and imported from your Assets or in packages) referencing assemblies built with assembly definitions."

    I suppose the easiest and best fix is to just buy Pro, but figured I'd at least hear your thoughts on the problem. I'm currently not really using Weaver, but I kinda want it in all my projects just for the conceptual cleanliness of its constants should I happen to need them :)

    Edit: Disabling "Auto Generate On Save" is an easy bandaid.
     
    Last edited: Oct 25, 2021
    andreiagmu likes this.
  5. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Importing the attached files over the top of your existing ones should allow you to put the procedural scripts in an assembly definition.

    The issue was just that it was written before assembly definitions were a thing so it only had to look directly in Unity's main C# assembly instead of searching through every assembly.

    If you upgrade to Weaver Pro, just replace the FindExistingType method in the CachedTypeInfo class with this:
    Code (CSharp):
    1.         public static CachedTypeInfo FindExistingType(string name, string fullName, ref bool shouldRebuild)
    2.         {
    3.             Type partialNameMatch = null;
    4.             StringBuilder partialMatchError = null;
    5.  
    6.             for (int iAssembly = 0; iAssembly < ReflectionUtilities.Assemblies.All.Count; iAssembly++)
    7.             {
    8.                 var assembly = ReflectionUtilities.Assemblies.All[iAssembly];
    9.                 var types = ReflectionUtilities.Assemblies.GetTypes(assembly);
    10.                 for (int iType = 0; iType < types.Length; iType++)
    11.                 {
    12.                     var type = types[iType];
    13.                     if (type.FullName == fullName)
    14.                     {
    15.                         return Get(type);
    16.                     }
    17.                     else if (type.Name == name)
    18.                     {
    19.                         if (partialNameMatch == null)
    20.                         {
    21.                             partialNameMatch = type;
    22.                         }
    23.                         else
    24.                         {
    25.                             if (partialMatchError == null)
    26.                             {
    27.                                 partialMatchError = WeaverUtilities.GetStringBuilder();
    28.                                 partialMatchError
    29.                                     .Append("Multiple types with the name '")
    30.                                     .Append(name)
    31.                                     .Append("' were found in the following assemblies:")
    32.                                     .AppendLineConst()
    33.                                     .Append("- Type: '")
    34.                                     .Append(partialNameMatch.FullName)
    35.                                     .Append("' in Assembly: '")
    36.                                     .Append(partialNameMatch.Assembly.FullName)
    37.                                     .Append('\'');
    38.                             }
    39.  
    40.                             partialMatchError
    41.                                 .AppendLineConst()
    42.                                 .Append("- Type: '")
    43.                                 .Append(type.FullName)
    44.                                 .Append("' in Assembly: '")
    45.                                 .Append(type.Assembly.FullName)
    46.                                 .Append('\'');
    47.                         }
    48.                     }
    49.                 }
    50.             }
    51.  
    52.             if (partialNameMatch != null)
    53.             {
    54.                 if (partialMatchError != null)
    55.                 {
    56.                     UnityEngine.Debug.LogWarning(partialMatchError.ReleaseToString());
    57.                     return null;
    58.                 }
    59.  
    60.                 shouldRebuild = true;
    61.                 return Get(partialNameMatch);
    62.             }
    63.  
    64.             return null;
    65.         }
     

    Attached Files:

    andreiagmu likes this.
  6. mklasson

    mklasson

    Joined:
    Oct 30, 2018
    Posts:
    28
    Works like a charm. Thank you!
     
  7. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    Hello, I have an issue.
    When I Try to generate a Constants Like Tags.cs or LasyerMask.cs
    It trigger this error "Static classes cannot have instance constructors"
    I just only comment the error. Seems to work fine after that. But it this a normal ?
     
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Can you attach one of the generated files so I can see what it looks like?
     
  9. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    Yeah I'm Using Unity 2021.1.28f1

    I want to generate Tags constants I delete the already generated file and create a new one this is the output file.
    Code (CSharp):
    1. // This file was procedurally generated by Weaver. Any modifications will be overwritten.
    2.  
    3. #pragma warning disable // All.
    4.  
    5. namespace Weaver
    6. {
    7.     /// <summary>This class was procedurally generated by Weaver.</summary>
    8.     public static class Tags
    9.     {
    10.         public const string Untagged = "Untagged";
    11.  
    12.         public const string Respawn = "Respawn";
    13.  
    14.         public const string Finish = "Finish";
    15.  
    16.         public const string EditorOnly = "EditorOnly";
    17.  
    18.         public const string MainCamera = "MainCamera";
    19.  
    20.         public const string Player = "Player";
    21.  
    22.         public const string GameController = "GameController";
    23.  
    24.         public const string LevelBounds = "LevelBounds";
    25.  
    26.         public const string Music = "Music";
    27.  
    28.         public const string Background = "Background";
    29.  
    30.         public const string NoMask = "NoMask";
    31.  
    32.         public const string Pickable = "Pickable";
    33.  
    34.         public const string PlayerOverworld = "Player-Overworld";
    35.  
    36.         #region Obsolete Members
    37. #if UNITY_EDITOR
    38.  
    39.         [System.Obsolete("Remove any references to it.")]
    40.         private Tags() { throw new System.NotImplementedException("UnityConstants.Tags..ctor is obsolete. Remove any references to it."); }
    41.  
    42. #endif
    43.         #endregion
    44.     }
    45. }
    46.  
    The Constructor in the "editor script" is the error.
    With a Comment it will ok.
     
  10. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I haven't been able to replicate the issue and can't see any reason for that script to generate a constructor.

    Can you please try the following:
    1. Open the ConstructorBuilder.cs script.
    2. Find the two Get methods in
      #region Pooling
      .
    3. Put
      UnityEngine.Debug.Log(declaringType);
      in both of them.
    4. Remove the constructors from all generated scripts and make sure you have no compile errors.
    5. Delete and regenerate the Tags script.
    6. If it generates a constructor it should trigger one of those Log calls, so just post the full stack trace and hopefully I'll be able to figure out what's causing it.
     
  11. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    Sorry but it's hard to trigger the error. I wasn't able to replicate the issue from a previous post.

    But unfortunately I found another issue.
    I think this issue makes everything more difficult to work.
    When I use weaver I know this create a Scriptable Object called
    "Weaver Settings.asset"

    I have issues when using different computers.
    If you download the project in another computer.

    For some reason weaver create a new Scriptable Object.

    The new file that is created is like:
    "Weaver Settings 1.asset"
    Weaver window loads the new file.

    when I press play in editor the injector have missing references.
    But If I delete that new generated file and press play everything works nice.

    I was able to replicate the issue in the same machine.
    I have to clean up the all the generated scripts by unity.

    Delete these folders and files.
    -Library
    -Logs
    -obj
    And all the .csproj files that are generated.
    Basically this is just delete all the ignores files from the project
    like the ".gitignore" or "ignore.conf"
    (this is like downloading the project for the first time)


    I'm Using Unity 2021.2.15f1 on Windows 10
     
    andreiagmu likes this.
  12. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    The issue seems to be that Weaver is getting initialized before Unity is actually ready to load Scriptable Objects. The Asset Database is loaded enough for it to see that the settings file exists but not enough to actually find it by type so when Weaver asks if one exists Unity says no and Weaver creates a new one. It should be a solvable problem, but won't be a quick fix so I'll have to put it on my to do list for after the Animancer update I'm currently working on.
     
    andreiagmu likes this.
  13. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    I check again with a new project using only Weaver with examples, Never fails.
    I think this is more like an issue with Unity Editor.

    A Temporal solution is to go Here
    "Startup.cs"
    and remove "[InitializeOnLoadMethod]"
    I was tired of rebuild the scriptable object.
     
    Last edited: Mar 22, 2022
  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    That should work as long as you aren't expecting injected fields to work in Edit Mode.
     
  15. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    @OscarLeif Have you tried using Weaver in Unity 2021.3 LTS? I'm trying to recreate the issue to figure out how to fix it properly but it doesn't seem to be happening at all so it might have just been a Unity bug in earlier 2021 versions.
     
  16. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    I check again. with an empty project.
    -Unity 2021.3.5f1. (2021.3.5.8f1, lastest LTS have a critical bug in the with nested canvas)
    -Unity 2020.3.20f1

    I didn't find the issue where the plugin generates a new scriptable object.
    So I try again with a big project.
    Only using 2021.3.5f1.
    The error appear again.

    I made the same steps to make this happen.

    -Clean all the temporary files, ".csproj" files.
    -Library folder
    -Log folder.
    -Temp folder.

    So an Empty project never fails.
    I will check if a more small project could trigger the same issue..

    Because I really depend on Weaver.
    I probably found a way to avoid the new creation of the scriptable file Object.

    This solution Avoids the creation of the new "Weaver Settings.asset"
    But the only issue here it Weaver have issues. Reading the file.
    I have to close and open Unity and everything is done again.

    I try to make project when this fails.

    Edit: for some reason I cannot trigger the error in other project.
    Maybe there's something wrong in my project that makes Weaver don't work as expected.

    Code (CSharp):
    1. internal static bool EnsureInstanceIsSaved()
    2.         {
    3.             if (_Instance == null ||
    4.                 _Instance.IsSaved ||
    5.                 EditorApplication.isCompiling)
    6.                 return false;
    7.  
    8.             _Instance.IsSaved = true;
    9.  
    10.             if (AssetDatabase.Contains(_Instance))
    11.                 return false;
    12.  
    13.             var path = DefaultPath;
    14.  
    15.             if (File.Exists(path))
    16.             {
    17.                 _Instance = AssetDatabase.LoadAssetAtPath<WeaverSettings>(path);
    18.                 Debug.Log("The File Exist");
    19.                 EditorApplication.delayCall += DelayCall.ByNumberOfEditorFrames(10, () =>
    20.                 {
    21.                     if (Editor.Window.WeaverWindow.Instance)
    22.                         Editor.Window.WeaverWindow.Instance.Close();
    23.                     string folderPath = "Assets/Plugins/Weaver";
    24.                     AssetDatabase.ImportAsset(folderPath, ImportAssetOptions.ImportRecursive | ImportAssetOptions.DontDownloadFromCacheServer);
    25.                     Debug.Log("Try Play a Scene");
    26.                 });
    27.                 return true;
    28.             }
    29.  
    30.             Directory.CreateDirectory(Path.GetDirectoryName(path));
    31.  
    32.             _Instance.hideFlags = HideFlags.None;
    33.             path = AssetDatabase.GenerateUniqueAssetPath(path);
    34.             AssetDatabase.CreateAsset(_Instance, path);
    35.             Debug.Log($"Created {Name} at {path}", _Instance);
    36.  
    37.             return true;
    38.         }
     
    Last edited: Aug 20, 2022
  17. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    How large is your project? I just tried it in a 4gb project which took ages to reimport but Weaver had no issues when it was done.

    If I can't figure out a proper fix, I probably will have to fall back to using a default path like you suggest. I wanted to leave it generic so you could move Weaver and the settings asset anywhere in your project, but that's obviously not worth it if it's going to cause issues like this.
     
  18. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    I finally found the issue.
    I never thought at first another asset could make weaver fail.
    If you use "Weaver" with "Monkey command" the issue happens.
    So when I include Monkey Command and Simply "Reimport All" it will generate every time a new "Weaver Settings.asset" file.

    So I could simply avoid including (ignore) Monkey in my repository, and Import it later.
    Monkey is an editor Tool.
    I will check what monkey does.
     
    Last edited: Aug 20, 2022
  19. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Someone found the solution for me. Turns out this behaviour is actually intentional, but in true Unity fashion it's only documented for [InitializeOnLoad] but not [InitializeOnLoadMethod]. Using OnPostProcessAllAssets seems to work (Weaver was actually already using that method, but it seems that if you don't add the optional didDomainReload parameter it won't get called immediately after scripts are reloaded so I had no idea it could even be used for that.

    I have a few other issues to look into, but it shouldn't be too long before I release an update.
     
    andreiagmu likes this.
  20. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Hey everyone, Weaver v6.3 is now up on the Asset Store.
     
  21. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    The AssetInstance attribute doesn't seem to like when you disable domain reloading.

    I have an object I call TickableManager. A singleton MonoBehaviour that receives Unities Update, Late Update and FixedUpdate calls and passes them along to objects that need them.

    With the following code, the system works only on the very first time you enter Play Mode. (With Domain Reload disabled)
    Code (CSharp):
    1. [AssetInstance] [UsedImplicitly]
    2. public static readonly TickableManager Instance;
    Changing it to the following, fixed the issue.
    Code (CSharp):
    1. [field: AssetInstance] [UsedImplicitly]
    2. public static TickableManager Instance { get; private set; }
    3.  
    4. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    5. private static void Init() { Instance = null; }
    6.  
     
  22. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I think you just ran into the issue with readonly fields described here. I just did a quick test with a property (without the Init method) and it worked as expected.

    Also, you don't need the
    field:
    because injection attributes can be placed directly on properties.
     
    Bezoro likes this.
  23. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    172
    Hi, I use Weaver for its Project Constants feature. Those auto-generated consts are very useful!
    I didn't have any issues with it while working on a solo project.

    But I'm also using Weaver in a project with more devs working in different task branches, and they may add/change stuff in the project (animations, tags, scenes, etc.) that eventually changes the generated consts files.
    This implies quite frequent VCS conflicts with the auto-generated consts (as was happening in this project).

    To avoid VCS conflicts, I tried ignoring the auto-generated consts scripts and their .meta files in my repo (I removed them from the repo), and keeping the "Weaver Settings.asset" file, for common settings stuff.
    Of course, I had to regenerate my consts files, and this updated their references in "Weaver Settings.asset". (that's ok)
    So, I pushed that updated version of Weaver Settings to the repo.

    One of the other devs also had to regenerate the consts files locally on his machine. (that was expected)
    But the generated .meta files didn't have the same guids as before, even when they are being generated in the same folder as before.
    This implies that when someone first regenerates those consts, their .meta guids will always change, and this updates their references in "Weaver Settings.asset" file, thereby causing more conflicts.

    What's the recommended approach for using Weaver in a VCS repository, where multiple people may end up changing project consts in their branches?
    Should I ignore the auto-generated files to avoid conflicts, or keep all the files and resolve their conflicts (or simply regenerate them after merging) when needed?

    ---
    After more thought, I could try ignoring the consts' .cs files, but keep their .meta files in the repo.
    In theory, this would keep the guids consistent between devs.

    But I'm not sure if, before the dev has a chance to regenerate the consts (consider an initial point where the dev doesn't have the consts' .cs files yet on their machine), Unity would try to delete those .meta files because their associated .cs files are missing.
    So, maybe this workaround wouldn't work after all.
     
    Last edited: Apr 15, 2023
  24. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Yeah, Unity would delete the metadatas with no matching file before Weaver can do anything.

    I'm not sure what version control system you're using, but in Git you can tell it to include a file and ignore changes so you could commit an empty (or barebones) .cs and its .meta then each user would regenerate their own .cs without effecting its GUID or the version control.
     
    andreiagmu likes this.
  25. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    172
    Thanks for the advice! :)
    I guess this would solve it perfectly for git. One of my teammates had even mentioned the
    Code (CSharp):
    1. git update-index --assume-unchanged FILE_NAME
    command, for cases like this.

    In our project's case, we use Plastic SCM (Unity VCS). I'd just need to know what's the equivalent for that git command.

    In the past, because of a similar case, I tried adding files to Plastic's "cloaked/hidden changes" lists, but that didn't work (the files' changes kept appearing in Plastic's pending changes view).
    But I'll try it out again, maybe some bug was fixed in Plastic since then.

    Thanks again for the tip!
     
  26. andreiagmu

    andreiagmu

    Joined:
    Feb 20, 2014
    Posts:
    172
    Ok, for Plastic SCM (Unity VCS), adding the generated constants' .cs and .meta files to
    hidden_changes.conf
    (and removing the files from
    ignore.conf
    ) did the trick! :)
     
  27. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    Hey, Weaver is super useful and has become an auto-include in all my projects but I've been having an annoying issue.

    Every time I clone the repo Weaver doesn't remember where the settings file is and generates a brand new one. (Weaver is in the repo)
    It also loses reference to all my Asset Instances.
    Am I missing something?

    Unity: 2021.3.26f1
    Weaver Pro: 6.3
     
    Last edited: May 28, 2023
    andreiagmu likes this.
  28. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I don't have time to properly look into it at the moment, but it sounds similar to this old issue which should have been fixed. There's a #if in the
    Startup
    script which is supposed to fix that using a different initialization method but I wouldn't be surprised if they've broken it again. So you could try commenting out the OnPostprocessAllAssets and OnLoadInEditor methods for now and I'll take a look sometime soon.
     
    andreiagmu likes this.
  29. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    I would like to make a feature request if possible.
    The ability to define a priority for the instantiation of AssetInstances.

    I just encountered a situation where I have some AssetInstances that rely on another being ready and initialized before they can do their thing.
    I'm thinking of a way similar to how the DefaultExecutionOrder attribute works, where you pass in an int.
     
  30. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I'll add it to my to do list for the next version.

    For now, [OnInjectionComplete] attributes might be your best bet for a workaround since they run after everything is injected. Just use [AssetReference]s then instantiate them yourself in [OnInjectionComplete].
     
    Bezoro likes this.
  31. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    @Bezoro Are you able to replicate the initialization issue in an empty project with a few simple scripts that have some injected stuff? I tried a bunch of different things but haven't managed to get it to fail.

    Also, which folders are in your repo and where is the Weaver Settings asset located?
     
  32. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    Assets, Packages and ProjectSettings are the folders in the repo.
    Weaver wasn't moved around or anything, its in the Assets/Plugins folder with the exact structure as it came when imported (except for the Examples and BuildDetailsScriptBuilder.cs, which were deleted).

    I just tested by deleting the contents in the Library folder.
    Upon opening the project and recalculating everything Weaver created a brand new Weaver Settings 1 and began using that.
    After deleting it it went back to using my old one, but it had lost all references to AssetInstances and most Procedural Assets consts (it only kept InjectorScriptBuilder), it kept the reference to the custom output directory though (Assets/Weaver Procedurals).

    Something I just found out, if I click the G button to generate any of the Procedural Assets consts, after compiling it it gets all references again.

    I'll try to reproduce it on an empty project. It may be something to do with another asset, I use dozens of tools from the asset store.
     
    Last edited: Jun 6, 2023
    andreiagmu likes this.
  33. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    Yep, seems like its not a problem with Weaver.
    I can replicate it without fail in my project, but not on a brand new one.
    There may be another asset that is causing the issue.
    You can disregard this.
     
  34. OscarLeif

    OscarLeif

    Joined:
    Jul 17, 2016
    Posts:
    68
    I think this happens when Multiple Scripts are called on the Unity Editor Startup.
    Something happens with the Editor Asset Database. So if you delete all the Assets that interact with the startup. Weaver should work fine.
     
    andreiagmu and Bezoro like this.
  35. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    I have another feature request that I would like to make, if possible.

    Currently, when loading assets using the Addressables system, we have to rely on strings when we don't have an asset reference readily available to load from. It would be incredibly useful if Weaver could generate constants for the Addressables string keys as well. This way, instead of using an error-prone string key:
    Code (CSharp):
    1. Addressables.LoadAssetAsync<GameObject>("error prone string key");
    We could do:
    Code (CSharp):
    1. Addressables.LoadAssetAsync<GameObject>(Weaver.PlayerCharacter)
    This would be quite helpful.
    Thank you for your time.
     
    andreiagmu likes this.
  36. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I haven't really looked into Addressables at all, but procedural scripts are pretty easy to make if the right APIs exist.

    Is there a way to get all addresses without needing to load every asset in the project and check if they have an address? Because that would be prohibitively slow.

    That might not even be the best approach anyway. I could probably make AddressableAsset<T> as a subclass of the lazy loaded Asset<T> which would allow it to work on addressables and resources without your code knowing or caring where it comes from, you'd just have an
    [AssetReference] public static Asset<GameObject> PlayerCharacter { get; private set; }
    .

    I vaguely remember reading that Addressables don't have a non-async loading method so injecting a non-lazy loaded reference might not be possible and it might also not be possible for Asset and AddressableAsset to be interchangeable since it wouldn't be able to load its addressable immediately on demand and you'd want to check if it's loaded yet and stuff like that.

    It's definitely worth investigating when I get time to do some more work on Weaver, but that might not be any time soon as I've just started working on a major update for Animancer.
     
    Bezoro likes this.
  37. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    The following piece of code prints all addresses for all assets marked as Addressable:
    Code (CSharp):
    1. foreach (var group in UnityEditor.AddressableAssets.AddressableAssetSettingsDefaultObject.Settings.groups)
    2. {
    3.     foreach (var entry in group.entries)
    4.         Debug.Log(entry.address);
    5. }

    You can force the loading of an asset to be synchronous with WaitForCompletion()
    Code (CSharp):
    1. Addressables.LoadAssetAsync<T>("Addressable ID").WaitForCompletion();

    As a user of Animancer this is very exciting.
    Right now with ECS being out of experimental I am playing around with it, does that update address anything related to ECS?
     
    andreiagmu likes this.
  38. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    I just realised that would be totally pointless anyway. If you want to inject a non-lazy loaded reference you'd just use a regular injected field since Addressables wouldn't help at all.
    Unfortunately not since there's basically nothing to work off without a baseline DOTS animation system like the Playables API so I'd be directly competing with Unity and everyone else trying to make a system from scratch rather than filling holes in an already established market. I'm also really not a fan of the DOTS "cripple your development workflow to get performance by default" philosophy so it's unlikely that I'll do anything to help push early adoption even if things end up going that way in the future.

    I'm currently working on a parameter binding system for mixers that works more like parameters in Animator Controllers so your code doesn't need to be so tightly coupled to the structure of your mixer states (which is especially painful if they're nested). I'm also brainstorming ideas for transition sets to let you set up different transitions depending on the state you're coming from, though it might end up being way more complicated than that if I also try to include more Animator Controller like features such as the ability to repeatedly tell it to "Attack" and have it play through each attack animation in a combo without the user's code needing to iterate through an array of transitions themselves.
     
  39. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    I imagined that would be the case.

    Yeah, I am really enjoying the extra performance, but the lack of feature parity with regular GameObjects has been a bit of a headache, in particular skinned meshes with animations. (Currently using GameObjects for the characters visual representation that follows their corresponding entity transform 1 to 1. All the logic happens in ECS land and gets passed to Monobehaviour land to play animations, sounds, particles, etc)

    Regardless, that does sound very useful.
     
    andreiagmu likes this.
  40. Bezoro

    Bezoro

    Joined:
    Mar 16, 2015
    Posts:
    130
    Does Weaver not support something like this?

    Code (CSharp):
    1. [SelectionBase]
    2. [DisallowMultipleComponent]
    3. public abstract class SingletonGameObject<T> : MonoBehaviour
    4. where T : class
    5. {
    6.     [AssetInstance] [UsedImplicitly]
    7.     public static T Instance
    8.     {
    9.        get => _instance;
    10.        private set => _instance = value;
    11.     }
    12.  
    13.     [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    14.     private static void Init() =>
    15.        Instance = null;
    16.  
    17.     private static T _instance;
    18. }
    I ask because this doesn't show up.

    Code (CSharp):
    1. public sealed class PlayerManager : SingletonGameObject<PlayerManager> {}
     
  41. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,487
    Yeah, injection isn't supported in generic types because it would take a lot of extra work to implement compared to regular types and I haven't run into a use case that would justify the effort. Your case could be basically covered by putting
    [AssetInstance] public static PlayerManager Instance { get; private set; }
    in PlayerManager, which isn't much more code than you're using to inherit.
     
    Bezoro likes this.