Search Unity

Removing m_ComponentOwner before serializing

Discussion in 'Cinemachine' started by Kerber996, Dec 3, 2019.

  1. Kerber996

    Kerber996

    Joined:
    Nov 9, 2016
    Posts:
    23
    I have been serializing Cinemachine components and unserializing them like so:

    Code (CSharp):
    1. public static string[] GetCMSerializedOrdered(GameObject parent) {
    2.             CinemachineVirtualCameraBase[] bases =
    3.                 parent.GetComponentsInChildren<CinemachineVirtualCameraBase>();
    4.  
    5.             CinemachineFreeLook[] freeLooks =
    6.                 parent.GetComponentsInChildren<CinemachineFreeLook>();
    7.             CinemachineVirtualCamera[] virtualCameras =
    8.                 parent.GetComponentsInChildren<CinemachineVirtualCamera>();
    9.             CinemachinePipeline[] pipelines =
    10.             parent.GetComponentsInChildren<CinemachinePipeline>();
    11.             CinemachineOrbitalTransposer[] transporters =
    12.                 parent.GetComponentsInChildren<CinemachineOrbitalTransposer>();
    13.             CinemachineComposer[] composers =
    14.                 parent.GetComponentsInChildren<CinemachineComposer>();
    15.  
    16.             List<string> components = new List<string>();
    17.  
    18.             foreach (var item in bases) {
    19.                 item.Follow = null;
    20.                 item.LookAt = null;
    21.                 components.Add(JsonUtility.ToJson(item));
    22.             }
    23.  
    24.             foreach (var item in freeLooks) {
    25.                 item.Follow = null;
    26.                 item.LookAt = null;
    27.                 components.Add(JsonUtility.ToJson(item));
    28.             }
    29.  
    30.             foreach (var item in virtualCameras) {
    31.                 item.Follow = null;
    32.                 item.LookAt = null;
    33.                 components.Add(JsonUtility.ToJson(item));
    34.             }
    35.  
    36.             foreach (var item in pipelines) {
    37.                 components.Add(JsonUtility.ToJson(item));
    38.             }
    39.  
    40.             foreach (var item in transporters) {
    41.                 components.Add(JsonUtility.ToJson(item));
    42.             }
    43.  
    44.             foreach (var item in composers) {
    45.                 components.Add(JsonUtility.ToJson(item));
    46.             }
    47.  
    48.             return components.ToArray();
    49. }
    and as you can see i have to set Follow and LookAt as null, because if I unserialize them and they are not null, the reference that they hold will point either to nothing or to some random thing in the scene (which will brake Cinemachine into chaos).

    Now I am facing the same issue with m_ComponentOwner which is serialized to handle copy/paste, but is not public or is there a function for me to null it (except DestroyPipeline, but i guess it would destroy too much, am i wrong?).

    Anyone has a workaround? Can/Should i rebuild the dll's? @Gregoryl
     
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,719
    Serializing in this manner is a pretty risky thing to do, imo. Why don't you just use prefabs or something like that?

    If you must serialize, you can define CINEMACHINE_EXPERIMENTAL_VCAM; then you will find CinemachineNewVirtualCamera and CinemachineNewFreeLook, which have much more straightforward implementations that you might find easier to serialize. Use them instead of CinemachineVirtualCamera and CinemachineFreeLook.
     
  3. Kerber996

    Kerber996

    Joined:
    Nov 9, 2016
    Posts:
    23
    Thanks for the info, will get back with the results :D

    I am using prefabs in a sense that I instantiate one prefab which has a Cinemachine setup, and I apply a serialized version to override the default prefab component values (I am basically serializing them to save their components values on the server, so i can change the values there and then they will update in the app :D)
     
  4. Kerber996

    Kerber996

    Joined:
    Nov 9, 2016
    Posts:
    23
    Yes, the new cinemachines don't have m_ComponentOwner when serialized :D

    However i ended up not using them since i would have to replace a lot of data, but the next big update will use the new cinemachines. I fixed m_ComponentOwner by removing it from JSON when serializing

    Code (CSharp):
    1. public string[] SerializeCinemachineCameraElements<T>(T[] elements) where T : CinemachineVirtualCameraBase {
    2.             List<string> returnList = new List<string>();
    3.  
    4.             foreach (T element in elements) {
    5.                 element.Follow = null;
    6.                 element.LookAt = null;
    7.                 string tempJson = JsonUtility.ToJson(element);
    8.  
    9.                 JObject tempJ = JObject.Parse(tempJson);
    10.                 tempJ.Property("m_ComponentOwner")?.Remove();
    11.  
    12.                 tempJson = tempJ.ToString()
    13.                     .Replace(System.Environment.NewLine, string.Empty);
    14.  
    15.                 returnList.Add(tempJson);
    16.             }
    17.  
    18.             return returnList.ToArray();
    19.         }