Sprites references null on Load

Discussion and help for Easy Save 3
Post Reply
Kokorozashi
Posts: 7
Joined: Tue Jun 25, 2019 12:20 am

Sprites references null on Load

Post by Kokorozashi »

Updated to 2019.4.1f1 and latest Easy Save 3 and now Sprites are being deserialized as null objects.
Looking in the save file JSON I see
"Graphic" : {
"_ES3Ref" : "3523149218884764385"
},
as the stored value. Maybe that isn't correct?
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Sprites references null on Load

Post by Joel »

Hi there,

This will most likely be because a reference to that Sprite doesn't exist in the manager. Are you getting any warnings when you load?

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Kokorozashi
Posts: 7
Joined: Tue Jun 25, 2019 12:20 am

Re: Sprites references null on Load

Post by Kokorozashi »

Joel wrote: Thu Jun 25, 2020 7:31 am Hi there,

This will most likely be because a reference to that Sprite doesn't exist in the manager. Are you getting any warnings when you load?

All the best,
Joel
That's the issue. Unfortunately it wasn't an issue before the Unity & ES3 update. At the moment, I don't know if it was only caused by updating ES3. I'm currently testing on 2020.1.1f1 with the latest ES3 3.3.1. What I can tell you though is if you have this data structure, then the ES3ReferenceMgr will save incorrect ES3 refs for the sprites:
> Scene
>> GameObject : [MonoBehaviour A]
>> Easy Save 3 Manager

Where:

Code: Select all

public class A : MonoBehaviour {
	public Template t;
        public List<ACard> cardInstances;
        public void Save() {
            ES3.Save("cards", cardInstances);
        }

        public void Load() {
            cardInstances = ES3.Load<List<ACard>>("cards");
        }

        public void GenerateNewHand() {
            cardInstances = new List<ACard>();
            
            foreach (var card in t.l.Cards) {
                
                cardInstances.Add(UnityEngine.Object.Instantiate(card));
            }

        }

}
[CreateAssetMenu(menuName="Test/Template"]
public class Template : ScriptableObject {
  [SerializeField] public Library l;
}
[CreateAssetMenu(menuName="Test/Library"]
public class Library : ScriptableObject {
  [SerializeField] public List<ACard> Cards;
}
public abstract class ACard : ScriptableObject {
  [SerializeField] public Sprite s;
}
[CreateAssetMenu(menuName="Test/SomeCard"]
public class SomeCard : ACard {
}
Pardon any pseudocode errors! Hook up some buttons to the Generate, Load and Save methods. ES3 Runtime settings "Serialize Unity Object fields: By Ref".
1) Create a Template asset, a Library asset, a Card and build the references within the Editor, assigning them all the way back to the Scene MonoBehavior script's Template t reference.
2) Run play mode
3) Generate
4) Save
5) Stop play mode
6) Run play mode
7) Load
8) Observe broken sprite references

NOTE: My current hack to get around this issue is to add a reference to the original ScriptableObject asset within the ScriptableObject instances, then re-assign Sprites after ES3.Load by looping over each SO Instance and copying from the SO Instance's reference. The SO instances need to be saved ByVal or ByRefAndVal:

Code: Select all

[Serializable]
class SO : ScriptableObject {
	[SerializeField]
	private Sprite sprite; 
	[SerializeField]
	private SO original;
	public Sprite Sprite { 
		get { 
			if (sprite == null && original != null) { 
				return original.sprite; 
			} 
			return sprite; 
		} 
		set { 
			sprite = value;
		} 
	}
	public SO GenerateInstance() {
		var inst = Instantiate(this);
		inst.original = this;
		return inst;
	}
  
  }
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Sprites references null on Load

Post by Joel »

Hi there,

Thanks for sending that over, really appreciate it.

Because you are creating instances of your ScriptableObjects, a reference to these will not exist when you reload your scene. This has always been the case, so I'm not sure why this was working before you updated.

In this case you would need to load them by reference and value to ensure that they're loaded correctly.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Kokorozashi
Posts: 7
Joined: Tue Jun 25, 2019 12:20 am

Re: Sprites references null on Load

Post by Kokorozashi »

Do the sprites just get random ref values every run because they aren't referenced by MonoBehaviors in a scene? I have a MonoBehaviour that references the ScriptableObject chain that ultimately has a reference to the Sprite. I would just expect ES3 to be able to traverse that hierarchy to get the Sprite ref so it could be loaded and saved properly by ES3. Unity is weird about that stuff though..
User avatar
Joel
Moodkie Staff
Posts: 4846
Joined: Wed Nov 07, 2012 10:32 pm

Re: Sprites references null on Load

Post by Joel »

Hi there,

They don't get different reference IDs every run because they're not referenced per se. It's that you're creating a new instance each time, which means it's a different instance on every run, so it will have a different instance ID.

You can try assigning your own reference ID using ES3ReferenceMgr.Current.Add(instance, 1234), ensuring you use the same ID each time.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Kokorozashi
Posts: 7
Joined: Tue Jun 25, 2019 12:20 am

Re: Sprites references null on Load

Post by Kokorozashi »

Joel wrote: Sun Aug 16, 2020 9:27 am Hi there,

They don't get different reference IDs every run because they're not referenced per se. It's that you're creating a new instance each time, which means it's a different instance on every run, so it will have a different instance ID.

You can try assigning your own reference ID using ES3ReferenceMgr.Current.Add(instance, 1234), ensuring you use the same ID each time.

All the best,
Joel
ES3ReferenceMgr.Current.Add
Perfect! You've read my mind. I knew I wanted to automate the Right Click > Easy Save 3 > Add Reference(s) to Manager tedium! Thanks.
Post Reply