Search Unity

Feedback @Unity: Please +SaveAssets() when you CTRL+S

Discussion in 'General Discussion' started by MrLucid72, Aug 5, 2019.

  1. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Currently, ScriptableObjects aren't writing to disc when they normally should. Sometimes they do, but not always.

    This is bad for Git users (read: Likely 99% of Unity users), as some things that should be sync'd are not being sync'd.

    Here is a ghetto CTRL+S override workaround until then (to add AssetDatabase.SaveAssets() to the save flow):

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEditor;
    3.  
    4. ...
    5.  
    6. [MenuItem("File/Save All (Xblade) %s", false, 0)] // ctrl+s
    7. public static void SaveAll()
    8. {
    9.     // Save scenes + prefab instances
    10.     EditorApplication.ExecuteMenuItem("File/Save");
    11.  
    12.     // Save dirty ScriptableOjects (.assets)
    13.     AssetDatabase.SaveAssets();
    14.  
    15.     Debug.Log("[EditorSaveAll] Done!");
    16. }
     
    Last edited: Aug 5, 2019
    dbdenny likes this.
  2. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Have you filled a bug report regarding the not saving?
     
  3. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    A lot of the time when I'm working with scriptable objects, prefabs or other project objects I'm not working in an actual scene so ctr+s doesn't make sense to use. As mentioned, this makes GIT commits a pain sometimes.

    More aggressively flushing in memory changes to disk would really be a godsend. A lot of the time I end up having to shut down and restart unity to make sure the changes are being written to disk.
     
  4. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,983
    This, so much this. We have some very scriptable object heavy workflows in our pipeline and as such we often do this dance to get unity to write changes.

    Git + scriptable objects are a pain right now due to way they are handled, and I often find myself questioning why a colleagues commit does not work for me to discover that a scriptable object was not written to disk and pushed through git, despite the fact that they "saved".
     
    Gekigengar and frosted like this.
  5. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Doesn't the save project menu option also save scriptable objects?
     
  6. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    You know what - I never noticed that option. Very useful!
     
    Joe-Censored and AndersMalmgren like this.
  7. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Yes it does.
    Save and Save As are for the Scene, if you have ScriptableObjects then try using Save Project.
     
  8. Tzan

    Tzan

    Joined:
    Apr 5, 2009
    Posts:
    736
    My entire game is in one scene, I was always wondering what Save Project does.
    I dont currently us scriptable objects though.
     
  9. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Its true for prefabs too
     
    Tzan likes this.
  10. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Renaming the menu items would be a really good and easy start here. By just the name "Save" there is no information about what exactly it saves. It's ambiguous naming, and now that we've got prefabs we can edit independently of scenes the context is a little more complicated than it used to be.

    I'd suggest "Save Scene" and "Save Project Metadata" (or whatever would be the technically correct term). Also, I'd suggest that when you're in the Prefab editor the "Save Scene" item should be seamlessly replaced with a "Save Prefab" item mapped to the same key, because why would we want anything else?
     
  11. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    On the Mac, you map the the shortcut to save project in the keyboard prefs (note: the pref pane sees each app as distinct, so if you upgrade / install another version, you will have to assign it as well, it doesn't carry over).
    upload_2019-8-5_17-50-35.png
    upload_2019-8-5_17-51-35.png
    upload_2019-8-5_17-32-37.png
    You can do it on windows too, though you many need a freeware tool to do it.

    Save Project mostly works. There have been a few instances where an SO hasn't "saved" after changes (sometimes when making changes via play mode). But it is pretty rare. Typically if I am doing a big commit that isn't isolated to a few checked out files, I will quit Unity first and then do a reconcile just to be 100% sure.
     
    MadeFromPolygons likes this.
  12. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    Yea... I know there is no good time to revamp things, but it would be nice if they picked some release in the future and have something like a "quality of life" update that mostly addresses the little weirdness that have built up over time that are largely awkward and not mission critical. Scenes and many other things work a bit differently and mean something slightly different than they did a decade or so ago. ;)
     
  13. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Exactly. I get it because I've been using it for something like a decade and innately understand the context of things based on how they have changed over that time.

    To a new(er) user, it says "save" but it arbitrarily only saves certain things and ignores others. It makes no sense from a user perspective unless you already know what it means.

    Looks like this happens transparently. Opening a prefab, changing something, then going File -> Save also blanks out the "Save" button at the top of the prefab's editor window. It'd be good to communicate that more effectively, because I've been using that for months and didn't know it was a thing.
     
    zombiegorilla likes this.
  14. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
    The new nested prefab editor forces a save on close, I think it shouldn't be an an issue with prefabs in newer Unity versions anymore.

    Pretty sure that's a too complicated term for many people and then they're afraid to even try it ;) Unity also saves more than just .meta files on "Save Project", doesn't it?
     
  15. MadeFromPolygons

    MadeFromPolygons

    Joined:
    Oct 5, 2013
    Posts:
    3,983
    Thats actually brilliant will give this a go
     
  16. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Hey. I spoke to some of the teams regarding this. We actually did use to have `Save Scene` and `Save Project`, we changed it in 2018.3 when we added the new Prefab Workflow.

    We have a docs page regarding Saving https://docs.unity3d.com/Manual/Saving.html

    It's not been updated with the Prefab mode changes so I have just updated it, my changes won't be available until the docs team have reviewed them so here is the additional information I have added:

    Save Scene is now just called Save. This is because Save actually does save everything. The only exception is when in Prefab Mode:

    One of the most common reasons why changes to ScriptableObjects and other assets are not saved it because they are not set as dirty. So I also added this to the Save Project section

    A team member did look into changing the Save label when in prefab mode, unfortunately, it's stored in our native side and not simple to dynamically change. Hopefully, we can revisit it in the future.
     
    Joe-Censored, Ryiah, frosted and 3 others like this.
  17. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Please consider some kind of background autosave to project objects. There are certain user actions like: "Apply to prefab", "new scene" etc, that would probably make sense to trigger a project save.

    Because flushing memory changes to disk is so transparent (no option to cancel for example, no 'save changes' prompt on unity exit) - users simply assume the changes are being written as they work.

    In terms of labeling, I wouldn't even use the "Save" nomenclature, since this does not operate like a save feature in most apps. It is a "flush" operation not a "save" operation, "flush project changes" is more accurate than "save project".

    What it's doing is: "Write Buffered Changes to Disk" not "Commit Changes" (which is how save normally functions)
     
  18. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Now that I think about it, this would properly go under "refreshing", wouldn't it? Eg, CTRL+R for manual (although refresh is automated, by default). After all, ScriptableObjs are supposed to "instantly save", so refresh seems more relevant than Save, as some others have pointed out.
     
  19. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    "Refresh" is usually redrawing the screen to reflect changes on disk. This is the opposite. It's literally flushing the buffer to disk.
     
  20. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Flushing is a term that people would be less likely to understand, especially if they are not a programmer.
     
    angrypenguin, Ryiah and Socrates like this.
  21. steego

    steego

    Joined:
    Jul 15, 2010
    Posts:
    969
    I'm bothered by this sometimes as well. Why does there even need to be more than one save? Couldn't there be only one that saves everything?
     
    MrLucid72 likes this.
  22. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    "Write Pending Changes" is another way to phrase it that is a little less technical. It also helps teach the user that there are pending changes in the first place.

    It might sound pedantic, but "Save" operations in general means something different from what's being done here.
     
  23. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    But it does way more than that in Unity -- if you turn auto refresh off, you won't see recompiled code, new directories, any external changes (like adding new files or changing them around), etc.

    CTRL+R and all of this will magically happen.

    Unity scales horribly with large projects (I'm frankly shocked that nothing has been done about this yet -- it's all about that refresh that isn't handled well automatically, but I digress), so I actually experience this first-hand since I keep auto refresh OFF.

    When it's off, since I know when to CTRL+R, I've been experiencing an "New project experience" -- it's incredible. Unity needs a "Smart Refresh". Currently it just refreshes your entire project whenever you make any change, direct or indirect.

    Gah, digressed again: TL;DR: Refresh does quite a lot and has a big part to play in external updates, project tab (path stuff, including meta files) and recompiling C# changes. Whenever all threads are locked and you see that spinny [well, frozen circle, threads being locked and all] circle at the bottom right? Refreshing ~

    > "Did you file a bug report yet?"

    Nay, but apologies, my project is huge. I found it's fruitless if I can't attach my project. So many times I've taken the time to submit "the perfect bug report" of something easily repro'd, then the QA guy would just fade it out if there wasn't a project attached. Made me pretty reluctant to file bug reports since then. I believe this post is as far as my part goes, unless I can send an invoice for further QA from me while I'm already working 50 hrs/wk :p.

    I'm fine with my ghetto script, but I post this thinking about others (I was super lost for a while when my changes weren't always showing up on Git).
     
    Last edited: Aug 6, 2019
  24. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Actually, to add:

    It seems like the ghetto trick of adding AssetDatabase.SaveAssets() still doesn't save everything...!

    Repro'd right here:

    http://recordit.co/VAFwGpJtM1

    So, what the heck will actually save my changes? This is starting to turn into an emergency if changes aren't actually being saved for Git collaboration, even with the hacky way.

    @karl_jones Gonna give you a quick tag after noticing this.

    EDIT 1:
    Even though it's already done in the script, I still tried file>>save, file >> saved project, CTRL+R refresh ... nothing works. What would write this to disk, closing Unity? Experimenting now

    EDIT 2:
    Welp, I just lost ALL of my changes by closing Unity and bringing it back up.

    I'm not .gitignore'ing the files, either -- I've been working with SO's for about a month now and it's *mostly* fine, except sometimes data just randomly poofs. I always thought it was in my head until both this post and the poof with a recording above having proof I had that data filled.

    EDIT 3:
    I just opened up Unity again, tried making a few changes, tried clicking around ... for some reason, NO changes are being detected at all - no matter what I do! I'm on 2019.1.8 ... any fixes for this in a later version? Any workarounds, like additional code I can add to my save flow?
     
    Last edited: Aug 7, 2019
  25. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
    If this is using a custom editor, the editor must use either the SerializedObject API or EditorUtility.SetDirty for modifications, to let Unity know something has changed, so it saves the file.
     
    angrypenguin and karl_jones like this.
  26. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Is this custom? I read in the docs that SerializeField, Header, ToolTip and TextArea are all native:

    I don't have any editor scripts involved.
     
  27. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
    I wouldn't consider this custom. Perhaps the readonly keyword is the issue?
     
  28. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    WHOA!! That was it!! I hope this is a bug - I'm clearly not trying to hide readonly from the buffer to save to disk?? O_O If this was Reddit, I'd give you a medal.
     
    Peter77 likes this.
  29. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
    Glad you found the culprit.

    I believe from a language point of view it works as expected, as you can't change the value from anywhere but the constructor.

    However, Unity should probably implement to hide or disable readonly fields from the Inspector. Perhaps even better to generate a compile error if readonly is used on a SerializedField field, but not sure if that's possible.
     
    Last edited: Aug 8, 2019
  30. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Hmm, ya - or a readonly override like they do with their custom "==" comparison for destroyed objs.

    or an attribute, like [ReadOnly] which would be more clear since it won't mix it with native stuff, saying "read only, except for the buffer" (then show an err if using the native readonly for a serialized field so folks are actually aware of this).

    Even then, when you make a change and you refresh, shouldn't that call the editor constructor again with the new changes?

    Maybe it's cached? So it'll try/catch (with no error...?) to change cached fields upon changes for speed.

    What if they checked if (readonly) then called the constructor (new) again with the updated info? Else, just do what it does now and update cache. And perhaps add an error there, if unable to update for whatever reason - not sure why it's silent.
     
    Last edited: Aug 7, 2019
  31. https://docs.unity3d.com/Manual/script-Serialization.html
    == is an operator, readonly is a keyword in c#, AFAIK it is not override-able. It is not a unity thing, it is a C# thing.

    That's taken by the DOTS already. :D
    https://docs.unity3d.com/ScriptReference/Unity.Collections.ReadOnlyAttribute.html


    .
     
    PizzaPie likes this.
  32. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,620
    karl_jones likes this.
  33. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    Glad to see you solved your problems while I was asleep :D
     
    Peter77 likes this.
  34. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    I was just going to file a bug report for this but it seems I cant recreate the issue.
    Here is my test script

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. [CreateAssetMenu(fileName = "Read only field asset")]
    4. public class ReadonlyField : ScriptableObject
    5. {
    6.     public readonly string publicString = "Hello world 1";
    7.  
    8.     [Header("TEST")][Tooltip("TEST")]
    9.     [SerializeField, TextArea(3, 10)]
    10.     private readonly string serializeFieldString = "Hello world 2";
    11.  
    12.     public int val = 123;
    13. }
    14.  
    Annotation 2019-08-07 103333.png

    I can not see any of the readonly fields in the inspector. I tried 2019.3 and 2017.4. What am I doing wrong?

    Now you can see why we ask for repro projects for bugs ;)
     
    Last edited: Aug 7, 2019
    frosted and Peter77 like this.
  35. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Whats the value of seing a readonly field in the inspector btw? It cant mutate :D
     
  36. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Ah... I originally had the field serialized WITHOUT readonly. Then I realized "Oh! .NET 4.6! I can use readonly". So I set as readonly and the fields didn't poof. Perhaps it wasn't supposed to show in the first place?

    Try serializing without readonly, refresh so you see the field, then add readonly + refresh again. I don't know if that makes a difference, but that's the only thing I did differently. Once I removed readonly, everything worked fine (and before that, I could edit the readonly fields in the editor -- I could see them and interact with them). It wasn't just strings - bools, etc, too.



    Who says you necessarily want to mutate this data (eg, scriptableObjs - data)? It's way friendlier than json (and arguably faster) - we use it to store game class (fighter, wizard, etc)/ability (magic missile, etc) info. We change things around all the time, so scriptableObjs greatly helps.

    There are tons of workarounds to use readonly for the non-mutable data - I didn't know it was causing issues. The issue is that I'm unlikely going to be the only one that notices issues being caused.
     
    Last edited: Aug 7, 2019
  37. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    Readonly means that the value cant be changed after construction (deserialization happens after construction, so unity won't be able to change the value).

    I would suspect that the reason youre able to see the changes there is because Unity has a 'serializedproperty' for editor values that was staging a temporary value that it couldnt actually save.
     
  38. MrLucid72

    MrLucid72

    Joined:
    Jan 12, 2016
    Posts:
    996
    Probably! :) However, the question now is: Where's the error? Saving to a readonly field sounds like something should pop out to say "Hey, now..."
     
  39. karl_jones

    karl_jones

    Unity Technologies

    Joined:
    May 5, 2015
    Posts:
    8,300
    So I changed it to not be readonly, modified the fields and then changed it back to readonly and the fields vanished as expected. Very strange. What version are you using?
     
  40. Overview. Why do you like to see the variables during debug or why do you like to see the other, related data in a spreadsheet during edit? Because humans like to see things in context. Usually readonly data also part of the same context, seeing them at the same place would be beneficial. Although I think the "debug" mode, even if the name a little bit clunky, would be just fine in the case of the unity inspector.
     
    Last edited by a moderator: Aug 7, 2019
  41. AndersMalmgren

    AndersMalmgren

    Joined:
    Aug 31, 2014
    Posts:
    5,358
    Since it can't mutate its the same value as once set either from from constructor (which is not likely since constructors are not really used when dealing with Unity API) or inline from variable declaration. So it's value will always be same. Can't see the value to see it from inspector that's all
     
  42. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Unity's serializer (afaik) uses reflection to write the serialized data, and reflection can (afaik) set readonly fields. So there's nothing saying that it's not doable to support them.

    Serializing readonly stuff is already supported by accident, by serializing the backing field of get-only properties:

    Code (csharp):
    1. //this works in C# 7.x
    2. [field: SerializeField]
    3. public int Foo { get; }
    It would be really valuable if this, and readonly fields, were supported, for expressing "this thing can only be changed from the editor, and is unchangeable after entering play mode" without having to build systems to do just that.
     
  43. angrypenguin

    angrypenguin

    Joined:
    Dec 29, 2011
    Posts:
    15,620
    Because it's common to want to save just one scene while editing multiple, or just a prefab that is being used in a scene, or some project settings without saving the scene or prefab you're modifying...

    The current system works pretty well. I very rarely run into issues with it. It's just the naming/communication that's not ideal. When training new people there's a fair bit of explanation I have to do, which I think could probably be more self-describing if the names were a bit more descriptive.
     
  44. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    IMO, encouraging runtime edits of readonly fields is a language violation and should absolutely not be encouraged.

    To achieve "this thing can only be changed from the editor" you can use a private field with serializefield tag with a public readonly property (if that's needed). This provides the same functionality in editor and is clear and unambiguous when reading the code cold.
     
    angrypenguin and karl_jones like this.
  45. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    That's a different thing. You can still write to that field from the same class. I'm also pretty sure that there's overhead involved when reading from a property compared to reading from a field.

    I don't even want the field to be public most of the time! I just as often want to do:
    Code (csharp):
    1. [SerializeField]
    2. private readonly Material foo;
    To express "this material that I use is a setting that won't be changed by any method in this type".
     
  46. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    I would consider that code to be really bad form.

    Thankfully, we don't have to share a codebase, so we can just agree to disagree on this and happily part ways (if we did share a code base and you didn't quickly reverse course, we would engage in glorious code based battle over that snippit).
     
    angrypenguin and Socrates like this.
  47. zombiegorilla

    zombiegorilla

    Moderator

    Joined:
    May 8, 2012
    Posts:
    9,052
    OMG... I saw that actually happen once several years ago. Two engineers that constantly fought over a semantic difference of opinion (something very trivial). All passive aggressively and all in code/commits. Ugh. We wanted to slap them both.
     
    Ryiah likes this.
  48. frosted

    frosted

    Joined:
    Jan 17, 2014
    Posts:
    4,044
    That's not glorious code battle. That's underhanded codebase sabotage, the refuge of scoundrels and cowards.

    I'm not passive when being aggressive. :p

    (On the serious note, developers disagree on code, it happens. I believe argument is healthy most of the time, but at the end of the day, you figure out how to understand eachother or one of you finds a new job).
     
    Ony, Ryiah and zombiegorilla like this.
  49. This is why making a coding manual is not a waste of time. Both style and basic rules. So when someone tries to submit something which deviates from the standard, it can be pointed out during review and ask them to stick to the rules.

    Edit: it also removes the "personal" elements from the interaction, it's not two opinion against each other anymore, the project rules vs. the "offender's" opinion
     
    Last edited by a moderator: Aug 8, 2019
  50. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    Why?

    I don't want to fight, I'm just genuinely curious why you'd consider it bad form. You're saying that encourages "runtime edits of readonly fields", but I don't see how it does that, as the field is not edited at runtime. It's edited at deserialization time. That's runtime from the engine's point of view, but from user side (ie. the code we write), it's not something we can interact with.

    It doesn't in any way enable me to edit the field at runtime, only at edit time.
     
    frosted likes this.