Load a sprite created at runtime

Discussion and help for Easy Save 3
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Load a sprite created at runtime

Post by robotSmith »

Hello, I have two questions:
- I would like to know how can I load sprites that were created at runtime.
- Any reason why when "Loading", sometimes some ScriptableObject variables were wiped out. Specifically Sprite and Material when being part of a struct. They were assigned pre-play, and they are not being modified at runtime (I have tried replicating it in an fully isolated project and I have not being able to).

Here is more background on the first part:
I have a script that creates a Texture2D and a Sprite at runtime using CreateSprite() and gets assigned to a serialized class. This class is part of a dictionary, and then I save the dictionary in ES3. When I turn off the editor, and I load the dictionary, the sprite is null and is defaulted to the basic one. I'm not getting any errors.

TIA!
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Load a sprite created at runtime

Post by Joel »

Hi there,

You can save and load Sprites and Texture2Ds just like any other data (see the Getting Started guide for more details). Note that you will need to save both, as saving the Sprite will only save it's Texture2D by reference rather than value.

Regarding your second issue, unfortunately it wouldn't be possible for me to tell without seeing a new project which replicates it. However, this usually means that an instance to the Sprite or Material saved cannot be found (i.e. this might be generated or modified at runtime).

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Load a sprite created at runtime

Post by robotSmith »

Hi Joel,

Thank you for the prompt answer.

About the first question:
I have read the ability to save Sprites and Textures, however, I'm not directly saving the Sprite and Texture, I'm saving the dictionary that holds the object that holds the Sprite (which holds the texture).
ES3.Save("DictionaryC", holderDictionary);
holderDictionary = ES3.Load("DictionaryC", new Dictionary<string, HolderOfImagesLite>());

Is this the wrong way of doing it?
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Load a sprite created at runtime

Post by robotSmith »

Okay, I tried a couple of things.
  • - Saving and load shows the sprite (via breakpoint) if I have not exited the game (I'm using editor mode still).
    - As soon as I stop the Play mode, and start the game again, the sprite will be null (but no error)
    - I simplified the testing to narrow down the options and now I'm not doing this in the Dictionary, but I'm just trying it in the sprite itself. I save the Sprite from the SpriteRenderer.sprite after the sprite has been populated. Same result.
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Load a sprite created at runtime

Post by Joel »

Hi there,

If it works until you leave the scene then this means that there is no reference to the Sprite that you're saving in the scene prior to runtime. In this case you would need to save the Sprite separately so that it is stored by value, and load it before trying to load it by reference (i.e. as a field in a ScriptableObject).

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Load a sprite created at runtime

Post by robotSmith »

That's correct. The sprite does not exist before runtime, it's created dynamically when the game is running. The texture is created first and then the sprite.

I tried this:
Sprite sprite = CameraMerger.Instance.MergeSprites(spriteArray);
ES3.Save<Sprite>("MergedImage", sprite);

(stop the Play mode) then
Load
ES3.Load<Sprite>("MergedImage");

Still not working :? .
p.s: I tried the Load too before stopping Play mode and it does Load the sprite correctly
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Load a sprite created at runtime

Post by Joel »

Hi there,

Please could you create a new, basic project which replicates this and private message it to me?

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Load a sprite created at runtime

Post by robotSmith »

Sent :)
User avatar
Joel
Moodkie Staff
Posts: 4826
Joined: Wed Nov 07, 2012 10:32 pm

Re: Load a sprite created at runtime

Post by Joel »

Thanks for sending that over, there are a few errors in your code unrelated to Easy Save.

Firstly, you're saving the texture of the Sprite attached to your SpriteRenderer. However, this is not the same Sprite as the one you're saving, which has a different texture.

Secondly, you aren't loading this texture before loading your Sprite, so it won't exist.

Once I resolved these it worked fine for me, albeit the pivot being in the wrong place. It turns out Unity uses pixel-based pivot in some places, and normalised pivot in others which is some cases can cause issues. If you private message me your invoice number I'll send over an update which accounts for this.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
robotSmith
Posts: 39
Joined: Thu Apr 01, 2021 4:53 pm

Re: Load a sprite created at runtime

Post by robotSmith »

Thanks for the quick turnaround Joel!

Ref: texture. You are correct, I had it as the one from the SpriteRenderer, but in the current "workflow" (which is only for testing) I'm changing the SpriteRenderer.sprite first, and then I press save, which saves the Texture (I'm assuming) from the correct Sprite. However, maybe this still not work? Do I need to save the original and not the reference?

Ref: loading. You did suggest this before, but maybe I'm not understanding it. For now I understand Load as loading and assigning to a variable, but I'm not assigning the texture to the Sprite here as I cannot do that, and you also mentioned that the Texture should load first.

Code: Select all

    public void Save()
    {
        Sprite sprite = CameraMerger.Instance.MergeSprites(spriteMaterials, new Vector2Int(32, 32));
        ES3.Save<Sprite>("MergedImage", sprite);
        ES3.Save<Texture2D>("MergedTexture", sprite.texture);
    }
     
    public void Load()
    {
        Texture2D texture = ES3.Load<Texture2D>("MergedTexture");
        Sprite sprite = ES3.Load<Sprite>("MergedImage");
        spriteRenderer.sprite = sprite;        
    }
Post Reply