Nested Custom Datatypes?

Discussion and help for Easy Save 3
Post Reply
Harper
Posts: 3
Joined: Sun Mar 13, 2022 3:15 am

Nested Custom Datatypes?

Post by Harper »

Hi, I am trying to figure out the approach to saving classes that have nested custom data types. For instance, if I want to save a class called "DanceMove"

Code: Select all

public class DanceMove{
	[SerializedField] public string name;
	[SerializedField] public int startBeat;
	[SerializedField] public List<Pose> poses;
}

// poses is a list of a custom data type that contains custom data types. 
public class Pose{
	[SerializedField] public int beat;
	[SerializedField] public bool isSet;
	[SerializedField] public Dictionary<LimbClassifier, TranslationData> limbPositions;
}

// limbPositions is made of a enum as a key and a pos rot dataset
public enum LimbClassifier{
	leftArm,
	rightArm,
	leftFoot,
	rightFoot
}

public class TranslationData{
	public Vector3 Position;
	public Quaternion Rotation;
}
I want to save and load DanceMove so my first try was simply

Code: Select all

ES3.Save("danceMove",theDanceMove);
and

Code: Select all

theDanceMove = ES3.Load<DanceMove>("danceMove");
This works fine for the name but the poses are empty.

I assume that I will need to create another like "saveDanceMoveData" class that first dumps all the nested content of DanceMove into it before saving and then translating it back but that is an undertaking so I just wanted to check here first.

Code: Select all

// Do I have to do something like this? I am assuming so but I just hope there is a simpler way. 
public class DanceMoveSaveData{
	public string danceMoveName;
	public int poseOneBeat;
	public int poseTwoBeat;
	public int poseThreeBeat;
	public int poseFourBeat;
	public TranslationData poseOneLeftArm;
	public TranslationData poseTwoLeftArm;
	public TranslationData poseThreeLeftArm;
	// and so on. with a constructor
	public DanceMoveSaveData(DanceMove move){
		danceMoveName = move.name;
		poseOneBeat = move.poses[0].beat;
		poseOneLeftArm = move.pose[0].limbPositions[LimbClassifier.leftArm];
		// and so on. 
	}
}
User avatar
Joel
Moodkie Staff
Posts: 4849
Joined: Wed Nov 07, 2012 10:32 pm

Re: Nested Custom Datatypes?

Post by Joel »

Hi there,

I’ve just tried your code and it appears to be working fine at my end. Would you be able to create a script which I can drop into a new scene in a new project which replicates your issue?
I assume that I will need to create another like "saveDanceMoveData" class that first dumps all the nested content of DanceMove into it before saving and then translating it back but that is an undertaking so I just wanted to check here first.
You don’t need to do this.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Harper
Posts: 3
Joined: Sun Mar 13, 2022 3:15 am

Re: Nested Custom Datatypes?

Post by Harper »

Interesting. Good to know that it should work and that I won't need to build this manual data class. There must be a difference between my example and my actual code. The code is nothing special so I will just post it here. Maybe you see something that I dont?

DanceMove

Code: Select all

System.Collections.Generic;
using UnityEngine;

namespace BDO.scripts.datatypes
{
    [System.Serializable]
    public class DanceMove
    {
        [SerializeField] public string name;
        [SerializeField]
        public int StartBeat;
        [SerializeField]
        public List<Pose> Poses;

        public DanceMove()
        {
            Poses = new List<Pose>();
        }

        public bool ContainsBeat(int beat)
        {
            return (beat >= StartBeat && beat <= StartBeat + 4);
        }
    }
}
Pose

Code: Select all

using System.Collections.Generic;
using UnityEngine;

namespace BDO.scripts.datatypes
{
    [System.Serializable]
    public class Pose
    {
        [SerializeField]
        public int BeatOffset;
        [SerializeField]
        public bool IsSet;
        [SerializeField]
        public Dictionary<CPClassifier, TranslationData> RigTargetPositions;

	// this is just used to populate the pose, it is just labeled transforms.
        public Pose(RigCollection collection)
        {
            RigTargetPositions = new Dictionary<CPClassifier, TranslationData>();
            RigTargetPositions.Add(CPClassifier.LeftHand,new TranslationData(collection.KVP[CPClassifier.LeftHand].transform.localPosition,collection.KVP[CPClassifier.LeftHand].transform.rotation));
            RigTargetPositions.Add(CPClassifier.RightHand,new TranslationData(collection.KVP[CPClassifier.RightHand].transform.localPosition,collection.KVP[CPClassifier.RightHand].transform.rotation));
            RigTargetPositions.Add(CPClassifier.LeftFoot,new TranslationData(collection.KVP[CPClassifier.LeftFoot].transform.localPosition,collection.KVP[CPClassifier.LeftFoot].transform.rotation));
            RigTargetPositions.Add(CPClassifier.RightFoot,new TranslationData(collection.KVP[CPClassifier.RightFoot].transform.localPosition,collection.KVP[CPClassifier.RightFoot].transform.rotation));
            RigTargetPositions.Add(CPClassifier.Spine,new TranslationData(collection.KVP[CPClassifier.Spine].transform.localPosition,collection.KVP[CPClassifier.Spine].transform.rotation));
            RigTargetPositions.Add(CPClassifier.Lookat,new TranslationData(collection.KVP[CPClassifier.Lookat].transform.localPosition,collection.KVP[CPClassifier.Lookat].transform.rotation));
            RigTargetPositions.Add(CPClassifier.Pelvis,new TranslationData(collection.KVP[CPClassifier.Pelvis].transform.localPosition,collection.KVP[CPClassifier.Pelvis].transform.rotation));
        }
    }
}
CPClassifier

Code: Select all

[System.Serializable]
public enum CPClassifier 
{
    LeftHand,
    RightHand,
    LeftFoot,
    RightFoot,
    Pelvis,
    Spine,
    Lookat
}

TranslationData

Code: Select all

using UnityEngine;
[System.Serializable]
public class TranslationData
{
    [SerializeField]
    public Vector3 Position;
    [SerializeField]
    public Quaternion Rotation;

    public TranslationData( Vector3 position, Quaternion rotation)
    {
        Position = position;
        Rotation = rotation;
    }
}

maybe I am not using the serializefield attribute properly somewhere?
User avatar
Joel
Moodkie Staff
Posts: 4849
Joined: Wed Nov 07, 2012 10:32 pm

Re: Nested Custom Datatypes?

Post by Joel »

Hi there,

Two of your classes do not have parameterless constructors so will not be serialised. Adding parameterless constructors will resolve the issue.

All the best,
Joel
Joel @ Moodkie Interactive
Purchase Easy Save | Contact | Guides | Docs | Getting started
Harper
Posts: 3
Joined: Sun Mar 13, 2022 3:15 am

Re: Nested Custom Datatypes?

Post by Harper »

Oh that worked. Thank you. I never knew that parameterless constructors are required for serilization. Appreciate the Sunday reply. Cheers
Post Reply