Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Help  How to Save / Load Obi Actors in 5.0
#11
(26-10-2020, 10:34 AM)Elegar Wrote: Hi Jose!
What you are talking about is quite different thing.. I guess I didn’t explain well what I want.

I need this for level design. I don't need to save blueprints on user's end like savegame data, I want them to be included in build. Actually creating blueprints from Editor would work for me: I can run the game, make a knot in runtime, pause the game and then move back to scene mode.
For example, in Unity you can save prefabs right from runtime (if you run in Editor). I want to make the same trick with blueprints, is it possible?

Hi Elegar,

Sorry! I misunderstood what you wanted. Blueprints are just assets, they're already serialized to disk by default. You just need to store particle positions/velocities in the blueprint. For this you can call actor.SaveStateToBlueprint(blueprint), passing the blueprint you want to store the data. Just make sure the blueprint has enough capacity to store all particles, easiest way to do this is instantiating the blueprint used in the first place to create the rope. See this related thread:
http://obi.virtualmethodstudio.com/forum...p?tid=2201

Note that if the rope has changed length or been torn at runtime, these changes cannot be saved in a blueprint.
Reply
#12
(26-10-2020, 10:53 AM)josemendez Wrote: Hi Elegar,

Sorry! I misunderstood what you wanted. Blueprints are just assets, they're already serialized to disk by default. You just need to store particle positions/velocities in the blueprint. For this you can call actor.SaveStateToBlueprint(blueprint), passing the blueprint you want to store the data. Just make sure the blueprint has enough capacity to store all particles, easiest way to do this is instantiating the blueprint used in the first place to create the rope. See this related thread:
http://obi.virtualmethodstudio.com/forum...p?tid=2201

Note that if the rope has changed length or been torn at runtime, these changes cannot be saved in a blueprint.
Hello again Jose
Thanks for such a quick answer! I almost done what I wanted, but still small issue doesn't allow me to be completely happySonrisa
I've read that another thread and it was extremely useful (almost my case). But when I commented out "GenerateImmediate();" from ObiRopeBlueprintBase.cs Unity stopped to save changed blueprints to disk... 

I had a following scenario before removing "GenerateImmediate();": press Run to launch simulation - twist the ropes - press button which calls my Save() function - stop simulation - click "save project" to write changed blueprints to disk. Worked like charm, blueprints files were changed and particle positions were saved inside. But when I launched simulation again or restarted Unity or reopened the scene, ropes returned to their very initial state. At this point I understood why you adviced to remove  "GenerateImmediate();"

Well, I removed it. Everything seems to be fine. I was able to twist the ropes, save them, relaunch simulation. But I noticed that blueprints files are unchanged since that moment. So all these changes lived only in Unity's memory and disappeared when I restarted Unity. But the whole point is to save them permanently... Any advices?

Here is my short script attached to the Rope, may be it can be useful:
Code:
using UnityEngine;
using Obi;

public class RopeSaveLoad : MonoBehaviour
{
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.I))  Save();
    }

    public void Save()
    {
        GetComponent<ObiRope>().SaveStateToBlueprint(GetComponent<ObiRope>().blueprint);
    }
}
Reply
#13
in Unity, you need to call AssetDatabase.SaveAssets() to save any changed assets to disk:
https://docs.unity3d.com/ScriptReference...ssets.html

If you don't, any changes you've done to assets will be lost when you restart Unity.
Reply
#14
(27-10-2020, 09:26 AM)josemendez Wrote: in Unity, you need to call AssetDatabase.SaveAssets() to save any changed assets to disk:
https://docs.unity3d.com/ScriptReference...ssets.html

If you don't, any changes you've done to assets will be lost when you restart Unity.


Nope, It doesn't work. I already tried. Calling SaveAssets changes nothing. Also, as I already wrote, I clicked "File -> SaveProject" which does the same.

Precisely speaking, it doesn't save after I commented out "GenerateImmediate();". And I don't understand why. Before removing that line saving worked but rope reset after validate.
Reply
#15
(27-10-2020, 10:51 AM)Elegar Wrote: Nope, It doesn't work. I already tried. Calling SaveAssets changes nothing. Also, as I already wrote, I clicked "File -> SaveProject" which does the same.

Precisely speaking, it doesn't save after I commented out "GenerateImmediate();". And I don't understand why. Before removing that line saving worked but rope reset after validate.

Have you tried flagging the asset as dirty using EditorUtility.SetDirty(blueprint); before calling SaveAssets? This is automatically called right after GenerateImmediate() (since it regenerates all blueprint data, so it's always known to need saving after this operation) but not called in any other case, such as manual editing of blueprint data or saving to the blueprint at runtime, as we don't know if/when the user has modified the asset.

Anytime you modify an asset, you should flag it as dirty (so that the asset database knows something has changed, and needs writing to disk), then call SaveAssets(). This will cause Unity to iterate over all assets that have been flagged dirty, save them to disk, then clear the dirty flag.

See: https://docs.unity3d.com/ScriptReference...Dirty.html
Reply
#16
(27-10-2020, 12:04 PM)josemendez Wrote: Have you tried flagging the asset as dirty using EditorUtility.SetDirty(blueprint); before calling SaveAssets? This is automatically called right after GenerateImmediate() (since it regenerates all blueprint data, so it's always known to need saving after this operation) but not called in any other case, such as manual editing of blueprint data or saving to the blueprint at runtime, as we don't know if/when the user has modified the asset.

Anytime you modify an asset, you should flag it as dirty (so that the asset database knows something has changed, and needs writing to disk), then call SaveAssets(). This will cause Unity to iterate over all assets that have been flagged dirty, save them to disk, then clear the dirty flag.

See: https://docs.unity3d.com/ScriptReference...Dirty.html
Finally! Yeah, that's exactly what I missed! Thank you hundered times, Jose!

So for those who will look for how to save twisted rope here's working script:
Code:
using UnityEngine;
using Obi;

public class RopeSaveLoad : MonoBehaviour
{
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.I))  Save();
    }

public void Save()
    {
        ObiRope actor = GetComponent<ObiRope>();
        actor.SaveStateToBlueprint(actor.blueprint);
        EditorUtility.SetDirty(actor.blueprint);
        AssetDatabase.SaveAssets();
    }
}
Reply
#17
(27-10-2020, 12:43 PM)Elegar Wrote: Finally! Yeah, that's exactly what I missed! Thank you hundered times, Jose!

So for those who will look for how to save twisted rope here's working script:
Code:
using UnityEngine;
using Obi;

public class RopeSaveLoad : MonoBehaviour
{
    public void Update()
    {
        if (Input.GetKeyDown(KeyCode.I))  Save();
    }

public void Save()
    {
        ObiRope actor = GetComponent<ObiRope>();
        actor.SaveStateToBlueprint(actor.blueprint);
        EditorUtility.SetDirty(actor.blueprint);
        AssetDatabase.SaveAssets();
    }
}

You're welcome! One final note though (you might know this already, but doesn't hurt to complete the info for future readers): I understand this script is editor-only, as you want to ship the game with all blueprints pre-made. If this script is not in a /Editor folder (like it should if it's an editor script), it will be included in any builds you make, and will result in compilation errors if using stuff from the UnityEditor namespace (as it's unavailable outside the editor). In that case you want to exclude any editor-only code by wrapping it in #if UNITY_EDITOR/#endif preprocessor directives. Like so:

Code:
ObiRope actor = GetComponent<ObiRope>();
actor.SaveStateToBlueprint(actor.blueprint);
#if UNITY_EDITOR
        EditorUtility.SetDirty(actor.blueprint);
        AssetDatabase.SaveAssets();
#endif

This will exclude the two editor-only lines in case you're building the script to be shipped with the standalone build, and the blueprint will only be saved to memory.
Reply
#18
(27-10-2020, 12:53 PM)josemendez Wrote: You're welcome! One final note though (you might know this already, but doesn't hurt to complete the info for future readers): I understand this script is editor-only, as you want to ship the game with all blueprints pre-made. If this script is not in a /Editor folder (like it should if it's an editor script), it will be included in any builds you make, and will result in compilation errors if using stuff from the UnityEditor namespace (as it's unavailable outside the editor). In that case you want to exclude any editor-only code by wrapping it in #if UNITY_EDITOR/#endif preprocessor directives. Like so:

Code:
ObiRope actor = GetComponent<ObiRope>();
actor.SaveStateToBlueprint(actor.blueprint);
#if UNITY_EDITOR
        EditorUtility.SetDirty(actor.blueprint);
        AssetDatabase.SaveAssets();
#endif

This will exclude the two editor-only lines in case you're building the script to be shipped with the standalone build, and the blueprint will only be saved to memory.
I get this error when I exit after saving. what is the reason?


Attached Files Thumbnail(s)
   
Reply
#19
(23-11-2021, 01:22 PM)greyhawk Wrote: I get this error when I exit after saving. what is the reason?

You're using an asset instead of an instance. Unity is warning you that this will permanently destroy data stored on disk, so it disallows it. Just instantiate the blueprint before assigning it.
Reply
#20
Hi!

So what i'm trying to do is actually pretty similar to what Elegar was trying. Running the game on editor i want to be able to move the rope and making a new path for it. After that, save the new path in a new blueprint and use it for a new start of a scene or in edit mode use the "Edit Path". I made a code that almost met my needs, but unfortunately the new blueprint is not "syncrhonized" with the new path, the rope follows the path, but i can't use "Edit Path" on it. I will let some prints to demonstrate my problem and the piece of code that i used. I actually dont't know if is possible to do what a want, but will be glad with any answer even if is just a tip to improve the code.

   
   


Code:
    public bool SaveNewBluePrint()
    {
        ObiActorBlueprint presetBluePrint = ActorBlueprint(rope);

        string path;
        string newPath;

        path = AssetDatabase.GetAssetPath(presetBluePrint);

        newPath = CreateNewPath(path, presetBluePrint.name, newBluePrintName, ropeOrRod);

        if (!AssetDatabase.CopyAsset(path, newPath))
            return false;

        if (ropeOrRod)
            newBluePrint = (ObiRopeBlueprint)AssetDatabase.LoadAssetAtPath(newPath, typeof(ObiRopeBlueprint));

        else
            newBluePrint = (ObiRodBlueprint)AssetDatabase.LoadAssetAtPath(newPath, typeof(ObiRodBlueprint));

      
       rope.SaveStateToBlueprint(newBluePrint);
       AssetDatabase.SaveAssets();

     
        return true;
    }
Reply