Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Custom Characters(Child Objects) and Multiplayer Sync

Discussion in 'Netcode for GameObjects' started by FSKiller, Oct 26, 2021.

  1. FSKiller

    FSKiller

    Joined:
    Oct 11, 2021
    Posts:
    2
    Hi,

    We are currently working on a small game, our Player Prefab has all the possible combinations of hair,color, face, etc.

    We are trying to sync the selected options beetween players.

    i've spent at least 12 hours diggin around for info but no luck, i dont have this sort of issue when it comes to syncing audio from players tho...
    our preferences get stored in a local GameObject:
    Code (CSharp):
    1. public class CharacterPrefs : MonoBehaviour
    2. {
    3.     public int  Race;
    4.     public int Sex;
    5.     public int HairIndex;
    6.     public int FaceIndex;
    7.     public int EyebrowsIndex;
    8.     public int BeardIndex;
    9.     public Color  HairColor;
    10.  
    11.     public string PlayerName;
    12.     // Start is called before the first frame update
    13.     void Start()
    14.     {
    15.        DontDestroyOnLoad(gameObject);
    16.     }
    17. }
    After this the Player spawns and the selected options should be applied, when the next player spawns the code tries to set my player with choices from player B and vice versa.

    i've tried this:
    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Netcode;
    3. using RPG.Character;
    4. using System;
    5. public class SetSelectedChar : NetworkBehaviour
    6. {
    7.     public NetworkVariable<int> EyebrowsIndex = new NetworkVariable<int>();
    8.     public NetworkVariable<int> BeardIndex = new NetworkVariable<int>();
    9.     public NetworkVariable<int> Sex = new NetworkVariable<int>();
    10.     public NetworkVariable<int> HairIndex = new NetworkVariable<int>();
    11.     public NetworkVariable<Color> HairColor = new NetworkVariable<Color>();
    12.     public NetworkVariable<int> FaceIndex = new NetworkVariable<int>();
    13.     public NetworkVariable<int> Race = new NetworkVariable<int>();
    14.  
    15.     public int ebIndex;
    16.     public int fhIndex;
    17.     public int hIndex;
    18.     public Color hColor;
    19.     public int fIndex;
    20.     public int gender;
    21.     public int race;
    22.     public bool isUpdated = false;
    23.  
    24.     public ulong cID;
    25.  
    26.  
    27.     void Start()
    28.     {
    29.         cID = NetworkManager.Singleton.LocalClientId;
    30.         Debug.Log("Client ID: " + cID);
    31.         if (!IsLocalPlayer) return;
    32.         //NetworkManager.Singleton.SpawnManager.GetLocalPlayerObject().GetComponent<NetworkObject>().OwnerClientId;
    33.         GameObject CharSystem = GameObject.FindGameObjectWithTag("CharacterSystem");
    34.         ebIndex = CharSystem.GetComponent<CharacterPrefs>().EyebrowsIndex;
    35.         fhIndex = CharSystem.GetComponent<CharacterPrefs>().BeardIndex;
    36.         hIndex = CharSystem.GetComponent<CharacterPrefs>().HairIndex;
    37.         hColor = CharSystem.GetComponent<CharacterPrefs>().HairColor;
    38.         fIndex = CharSystem.GetComponent<CharacterPrefs>().FaceIndex;
    39.         race = CharSystem.GetComponent<CharacterPrefs>().Race;
    40.         gender = CharSystem.GetComponent<CharacterPrefs>().Sex;
    41.         PrepVarsServerRpc(cID, ebIndex, fhIndex, hIndex, hColor, fIndex, race, gender);
    42.     }
    43.     void Update()
    44.     {
    45.         if (IsServer) return;
    46.         if (!IsLocalPlayer) return;
    47.         if (ebIndex != EyebrowsIndex.Value || fhIndex != BeardIndex.Value || hIndex != HairIndex.Value || hColor != HairColor.Value || fIndex != FaceIndex.Value || gender != Sex.Value || race != Race.Value)
    48.         {
    49.             PrepVarsServerRpc(cID, ebIndex, fhIndex, hIndex, hColor, fIndex, race, gender);
    50.         }
    51.         updatechars();
    52.         //if (!IsLocalPlayer) return;
    53.         //Debug.Log("UPDATE");
    54.         //CharServerRpc(ebIndex, fhIndex, hIndex, hColor, fIndex, race, gender);
    55.     }
    56.  
    57.     private void updatechars()
    58.     {
    59.         CharServerRpc();
    60.     }
    61.     [ServerRpc]
    62.     void CharServerRpc()
    63.     {
    64.         CharClientRpc(cID, ebIndex, fhIndex, hIndex, hColor, fIndex, race, gender);
    65.     }
    66.  
    67.     [ServerRpc]
    68.     private void PrepVarsServerRpc(ulong ClientID, int _EyebrowsIndex, int _BeardIndex, int _HairIndex, Color _HairColor, int _FaceIndex, int _Race, int _Sex)
    69.     {
    70.         EyebrowsIndex.Value = _EyebrowsIndex;
    71.         BeardIndex.Value = _BeardIndex;
    72.         HairIndex.Value = _HairIndex;
    73.         HairColor.Value = _HairColor;
    74.         FaceIndex.Value = _FaceIndex;
    75.         Race.Value = _Race;
    76.         Sex.Value = _Sex;
    77.         Debug.Log("Received Update Char From Client: " + ClientID);
    78.     }
    79.     [ClientRpc]
    80.     public void CharClientRpc(ulong clientID, int eb, int bd, int h, Color hc, int fa, int ra, int se)
    81.     {
    82.         GameObject go = gameObject;
    83.         Debug.Log("Remote Vars: " + eb + " " + bd + " " + h + " " + hc + " " + fa + " " + ra + " " + se);
    84.         Debug.Log("Updating: "+cli);
    85.         go.GetComponent<CharacterCreator>().SetEyebrows(eb, "");
    86.         go.GetComponent<CharacterCreator>().SetHair(h, "");
    87.         go.GetComponent<CharacterCreator>().SetHairColor("", hc);
    88.         go.GetComponent<CharacterCreator>().SetHead(fa, "");
    89.         switch (se)
    90.         {
    91.             case 0:
    92.                 go.GetComponent<CharacterCreator>().SetGender("Gender (Male)", Color.black);
    93.                 break;
    94.             case 1:
    95.                 go.GetComponent<CharacterCreator>().SetGender("Gender (Female)", Color.black);
    96.                 break;
    97.         }
    98.         go.GetComponent<CharacterCreator>().SetFacialHair(bd, "");
    99.         //Debug.Log("Race Val =" + Race.Value);
    100.         switch (ra)
    101.         {
    102.             case 0:
    103.                 go.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    104.                 //Debug.Log("Switch 1");
    105.                 break;
    106.             case 1:
    107.                 go.GetComponent<CharacterCreator>().SetRace("Race 2", Color.black);
    108.                 //Debug.Log("Switch 2");
    109.                 break;
    110.             case 2:
    111.                 go.GetComponent<CharacterCreator>().SetRace("Race 3", Color.black);
    112.                 //Debug.Log("Switch 3");
    113.                 break;
    114.             case 3:
    115.                 go.GetComponent<CharacterCreator>().SetRace("Race 4", Color.black);
    116.                 //Debug.Log("Switch 4");
    117.                 break;
    118.             default:
    119.                 go.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    120.                 //Debug.Log("Switch 1");
    121.                 break;
    122.         }
    123.     }
    124. }
    125.  
    126.  
    127.  
    128.  
    129. //Debug.Log("Received Update Char From Server");
    130. //gameObject.GetComponent<CharacterCreator>().SetEyebrows(EyebrowsIndex.Value, "");
    131. //gameObject.GetComponent<CharacterCreator>().SetHair(HairIndex.Value, "");
    132. //gameObject.GetComponent<CharacterCreator>().SetHairColor("", HairColor.Value);
    133. //gameObject.GetComponent<CharacterCreator>().SetHead(FaceIndex.Value, "");
    134. //switch (Sex.Value)
    135. //{
    136. //    case 0:
    137. //        gameObject.GetComponent<CharacterCreator>().SetGender("Gender (Male)", Color.black);
    138. //        break;
    139. //    case 1:
    140. //        gameObject.GetComponent<CharacterCreator>().SetGender("Gender (Female)", Color.black);
    141. //        break;
    142. //}
    143. //gameObject.GetComponent<CharacterCreator>().SetFacialHair(BeardIndex.Value, "");
    144. ////Debug.Log("Race Val =" + Race.Value);
    145. //switch (Race.Value)
    146. //{
    147. //    case 0:
    148. //        gameObject.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    149. //        //Debug.Log("Switch 1");
    150. //        break;
    151. //    case 1:
    152. //        gameObject.GetComponent<CharacterCreator>().SetRace("Race 2", Color.black);
    153. //        //Debug.Log("Switch 2");
    154. //        break;
    155. //    case 2:
    156. //        gameObject.GetComponent<CharacterCreator>().SetRace("Race 3", Color.black);
    157. //        //Debug.Log("Switch 3");
    158. //        break;
    159. //    case 3:
    160. //        gameObject.GetComponent<CharacterCreator>().SetRace("Race 4", Color.black);
    161. //        //Debug.Log("Switch 4");
    162. //        break;
    163. //    default:
    164. //        gameObject.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    165. //        //Debug.Log("Switch 1");
    166. //        break;
    167. //}
    168.  
    and this:
    Code (CSharp):
    1. using UnityEngine;
    2. using Unity.Netcode;
    3. using RPG.Character;
    4. using System;
    5. public class SetSelectedChar : NetworkBehaviour
    6. {
    7.     public int EyeBrows;
    8.     public int Beard;
    9.     public int Hair;
    10.     public Color HairColor;
    11.     public int Face;
    12.     public int Gender;
    13.     public int Race;
    14.  
    15.     void Start()
    16.     {
    17.         if (IsServer) enabled = false;
    18.         if (!IsLocalPlayer) return;
    19.         GameObject CharSystem = GameObject.FindGameObjectWithTag("CharacterSystem");
    20.         EyeBrows = CharSystem.GetComponent<CharacterPrefs>().EyebrowsIndex;
    21.         Beard = CharSystem.GetComponent<CharacterPrefs>().BeardIndex;
    22.         Hair = CharSystem.GetComponent<CharacterPrefs>().HairIndex;
    23.         HairColor = CharSystem.GetComponent<CharacterPrefs>().HairColor;
    24.         Face = CharSystem.GetComponent<CharacterPrefs>().FaceIndex;
    25.         Race = CharSystem.GetComponent<CharacterPrefs>().Race;
    26.         Gender = CharSystem.GetComponent<CharacterPrefs>().Sex;
    27.     }
    28.     void Update()
    29.     {
    30.         if (!IsLocalPlayer) return;
    31.         CharServerRpc();
    32.     }
    33.  
    34.     [ServerRpc]
    35.     private void CharServerRpc()
    36.     {
    37.         CharClientRpc();
    38.     }
    39.     [ClientRpc]
    40.     private void CharClientRpc()
    41.     {
    42.         if (!IsLocalPlayer)
    43.         {
    44.             Debug.Log("Updating : " + gameObject.GetComponent<NetworkObject>().OwnerClientId);
    45.             gameObject.GetComponent<CharacterCreator>().SetEyebrows(EyeBrows, "");
    46.             gameObject.GetComponent<CharacterCreator>().SetHair(Hair, "");
    47.             gameObject.GetComponent<CharacterCreator>().SetHairColor("", HairColor);
    48.             gameObject.GetComponent<CharacterCreator>().SetHead(Face, "");
    49.             switch (Gender)
    50.             {
    51.                 case 0:
    52.                     gameObject.GetComponent<CharacterCreator>().SetGender("Gender (Male)", Color.black);
    53.                     break;
    54.                 case 1:
    55.                     gameObject.GetComponent<CharacterCreator>().SetGender("Gender (Female)", Color.black);
    56.                     break;
    57.             }
    58.             gameObject.GetComponent<CharacterCreator>().SetFacialHair(Beard, "");
    59.             switch (Race)
    60.             {
    61.                 case 0:
    62.                     gameObject.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    63.                     //Debug.Log("Switch 1");
    64.                     break;
    65.                 case 1:
    66.                     gameObject.GetComponent<CharacterCreator>().SetRace("Race 2", Color.black);
    67.                     //Debug.Log("Switch 2");
    68.                     break;
    69.                 case 2:
    70.                     gameObject.GetComponent<CharacterCreator>().SetRace("Race 3", Color.black);
    71.                     //Debug.Log("Switch 3");
    72.                     break;
    73.                 case 3:
    74.                     gameObject.GetComponent<CharacterCreator>().SetRace("Race 4", Color.black);
    75.                     //Debug.Log("Switch 4");
    76.                     break;
    77.                 default:
    78.                     gameObject.GetComponent<CharacterCreator>().SetRace("Race 1", Color.black);
    79.                     //Debug.Log("Switch 1");
    80.                     break;
    81.             }
    82.         }
    83.     }
    84. }
    85.  
    Nothing seems to work...
    Getting kinda desperate NGL.... Pls send help, i think i'm going crazy

    BTW this my CharacterCreator.cs:

    Code (CSharp):
    1. using System;
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. namespace RPG.Character
    7. {
    8.     public class CharacterCreator : MonoBehaviour
    9.     {
    10.         [Header("Material")]
    11.         public Material mat;
    12.  
    13.         [Header("Skin Colors")]
    14.         public Color whiteSkin = new Color(1f, 0.8000001f, 0.682353f);
    15.         public Color brownSkin = new Color(0.8196079f, 0.6352941f, 0.4588236f);
    16.         public Color blackSkin = new Color(0.5647059f, 0.4078432f, 0.3137255f);
    17.         public Color elfSkin = new Color(0.9607844f, 0.7843138f, 0.7294118f);
    18.  
    19.         [Header("Scar Colors")]
    20.         public Color whiteScar = new Color(0.9294118f, 0.6862745f, 0.5921569f);
    21.         public Color brownScar = new Color(0.6980392f, 0.5450981f, 0.4f);
    22.         public Color blackScar = new Color(0.4235294f, 0.3176471f, 0.282353f);
    23.         public Color elfScar = new Color(0.8745099f, 0.6588235f, 0.6313726f);
    24.  
    25.         [Header("Stubble Colors")]
    26.         public Color whiteStubble = new Color(0.8039216f, 0.7019608f, 0.6313726f);
    27.         public Color brownStubble = new Color(0.6588235f, 0.572549f, 0.4627451f);
    28.         public Color blackStubble = new Color(0.3882353f, 0.2901961f, 0.2470588f);
    29.         public Color elfStubble = new Color(0.8627452f, 0.7294118f, 0.6862745f);
    30.  
    31.         [Header("Body Art Colors")]
    32.         public Color[] bodyArt = { new Color(0.0509804f, 0.6745098f, 0.9843138f), new Color(0.7215686f, 0.2666667f, 0.2666667f) };
    33.  
    34.         // character object lists
    35.         // male list
    36.         [HideInInspector]
    37.         public CharacterObjectGroups male;
    38.  
    39.         // female list
    40.         [HideInInspector]
    41.         public CharacterObjectGroups female;
    42.  
    43.         // universal list
    44.         [HideInInspector]
    45.         public CharacterObjectListsAllGender allGender;
    46.  
    47.         private Gender gender = Gender.Male;
    48.  
    49.         //holds the acttive bits, should be useful for saving
    50.         private int[] equipped;
    51.         private int maxParts = 0;
    52.  
    53.         //dictionary to keep all posible items for fast reference
    54.         private List<GameObject>[,] allObjects;
    55.  
    56.         private bool isLoaded = false;
    57.  
    58.         #region Init and Helpers
    59.         // Start is called before the first frame update
    60.         void Start()
    61.         {
    62.             if (false == isLoaded)
    63.             {
    64.                 InitBody();
    65.             }
    66.  
    67.             EnableCharacter();
    68.         }
    69.  
    70.         private void InitBody()
    71.         {
    72.             //set up the vectors
    73.             maxParts = Enum.GetValues(typeof(BodyParts)).Length;
    74.             equipped = new int[maxParts];
    75.  
    76.             //silly C# sintax
    77.             allObjects = new List<GameObject>[2, maxParts];
    78.  
    79.             // rebuild all lists
    80.             BuildLists();
    81.             //set to -1 which means nothing equipped
    82.             for (int i = 0; i < maxParts; i++)
    83.             {
    84.                 equipped[i] = -1;
    85.             }
    86.             //default startup as male
    87.             equipped[(int)BodyParts.HeadAllElements] = 0;
    88.             equipped[(int)BodyParts.Eyebrow] = 0;
    89.             equipped[(int)BodyParts.Torso] = 0;
    90.             equipped[(int)BodyParts.Arm_Upper_Right] = 0;
    91.             equipped[(int)BodyParts.Arm_Upper_Left] = 0;
    92.             equipped[(int)BodyParts.Arm_Lower_Right] = 0;
    93.             equipped[(int)BodyParts.Arm_Lower_Left] = 0;
    94.             equipped[(int)BodyParts.Hand_Right] = 0;
    95.             equipped[(int)BodyParts.Hand_Left] = 0;
    96.             equipped[(int)BodyParts.Hips] = 0;
    97.             equipped[(int)BodyParts.Leg_Right] = 0;
    98.             equipped[(int)BodyParts.Leg_Left] = 0;
    99.  
    100.             SetRace("Race 1", Color.white);
    101.             SetHairColor("dummy", new Color(0.3098039f, 0.254902f, 0.1764706f));
    102.  
    103.         }
    104.  
    105.         private void EnableCharacter()
    106.         {
    107.             //activate the look
    108.             for (int i = 0; i < maxParts; i++)
    109.             {
    110.                 ActivateItem(i, equipped[i]);
    111.             }
    112.         }
    113.         private void DisableCharacter()
    114.         {
    115.             //activate the look
    116.             for (int i = 0; i < maxParts; i++)
    117.             {
    118.                 DeactivateItem(i, equipped[i]);
    119.             }
    120.         }
    121.  
    122.         private void DeactivateItem(int itemType, int itemIndex)
    123.         {
    124.             //if we had a previous item
    125.             if (equipped[itemType] != -1 && equipped[itemType] < allObjects[(int)gender, itemType].Count)
    126.             {
    127.                 allObjects[(int)gender, itemType][equipped[itemType]].SetActive(false);
    128.             }
    129.         }
    130.  
    131.         // enable game object and add it to the enabled objects list
    132.         void ActivateItem(int itemType, int itemIndex)
    133.         {
    134.             if (itemIndex >= allObjects[(int)gender, itemType].Count)
    135.             {
    136.                 itemIndex = -1;
    137.             }
    138.             //if we had a previous item
    139.             if (equipped[itemType] != -1)
    140.             {
    141.                 if (equipped[itemType] < allObjects[(int)gender, itemType].Count)
    142.                 {
    143.                     allObjects[(int)gender, itemType][equipped[itemType]].SetActive(false);
    144.                 }
    145.                 if (itemIndex != -1)
    146.                 {
    147.                     equipped[itemType] = itemIndex;
    148.                     allObjects[(int)gender, itemType][equipped[itemType]].SetActive(true);
    149.                 }
    150.  
    151.             }
    152.             else
    153.             {
    154.                 if (itemIndex != -1)
    155.                 {
    156.                     equipped[itemType] = itemIndex;
    157.                     allObjects[(int)gender, itemType][equipped[itemType]].SetActive(true);
    158.                 }
    159.             }
    160.  
    161.  
    162.         }
    163.  
    164.         Color ConvertColor(int r, int g, int b)
    165.         {
    166.             return new Color(r / 255.0f, g / 255.0f, b / 255.0f, 1);
    167.         }
    168.         #endregion
    169.  
    170.         #region UI Setters
    171.         public void SetHead(int index, string name)
    172.         {
    173.             if (index < allObjects[(int)gender, (int)BodyParts.HeadAllElements].Count)
    174.             {
    175.                 ActivateItem((int)BodyParts.HeadAllElements, index);
    176.             }
    177.         }
    178.  
    179.         public void SetEyebrows(int index, string name)
    180.         {
    181.             if (index < allObjects[(int)gender, (int)BodyParts.Eyebrow].Count)
    182.             {
    183.                 ActivateItem((int)BodyParts.Eyebrow, index);
    184.             }
    185.         }
    186.  
    187.         public void SetHair(int index, string name)
    188.         {
    189.             //handle no hair option
    190.             index--;
    191.             if (index < allObjects[(int)gender, (int)BodyParts.All_Hair].Count)
    192.             {
    193.                 ActivateItem((int)BodyParts.All_Hair, index);
    194.             }
    195.         }
    196.  
    197.         public void SetFacialHair(int index, string name)
    198.         {
    199.             if (gender == Gender.Female)
    200.                 return;
    201.             //handle no hair option
    202.             index--;
    203.             if (index < allObjects[(int)gender, (int)BodyParts.FacialHair].Count)
    204.             {
    205.                 ActivateItem((int)BodyParts.FacialHair, index);
    206.             }
    207.         }
    208.  
    209.         public void SetRace(string name, Color color)
    210.         {
    211.             Color skinColor = Color.black;
    212.             Color scarColor = Color.black;
    213.             Color stubbleColor = Color.black;
    214.  
    215.             ActivateItem((int)BodyParts.Elf_Ear, -1);
    216.             equipped[(int)BodyParts.Elf_Ear] = -1;
    217.             switch (name)
    218.             {
    219.                 case "Race 1": //Human
    220.                     skinColor = whiteSkin;
    221.                     scarColor = whiteScar;
    222.                     stubbleColor = whiteStubble;
    223.                     break;
    224.                 case "Race 2":
    225.                     skinColor = brownSkin;
    226.                     scarColor = brownScar;
    227.                     stubbleColor = brownStubble;
    228.                     break;
    229.                 case "Race 3":
    230.                     skinColor = blackSkin;
    231.                     scarColor = blackScar;
    232.                     stubbleColor = blackStubble;
    233.                     break;
    234.                 case "Race 4":
    235.                     skinColor = elfSkin;
    236.                     scarColor = elfScar;
    237.                     stubbleColor = elfStubble;
    238.                     equipped[(int)BodyParts.Elf_Ear] = 1;
    239.                     ActivateItem((int)BodyParts.Elf_Ear, 1);
    240.                     //activate elf ears
    241.                     break;
    242.  
    243.             }
    244.             //set the skin color
    245.             mat.SetColor("_Color_Skin", skinColor);
    246.  
    247.             // set stubble color
    248.             mat.SetColor("_Color_Stubble", stubbleColor);
    249.  
    250.             // set scar color
    251.             mat.SetColor("_Color_Scar", scarColor);
    252.         }
    253.  
    254.         public void SetHairColor(string name, Color color)
    255.         {
    256.             mat.SetColor("_Color_Hair", color);
    257.         }
    258.  
    259.         public void SetGender(string name, Color color)
    260.         {
    261.             Gender newGender;
    262.             //string comparison yes!
    263.             if (name.CompareTo("Gender (Male)") == 0)
    264.             {
    265.                 newGender = Gender.Male;
    266.             }
    267.             else
    268.             {
    269.                 newGender = Gender.Female;
    270.             }
    271.             if (newGender != gender)
    272.             {
    273.                 DisableCharacter();
    274.                 gender = newGender;
    275.                 EnableCharacter();
    276.             }
    277.         }
    278.         #endregion
    279.  
    280.         #region Builders
    281.         // build all item lists for use in randomization
    282.         private void BuildLists()
    283.         {
    284.             //build out male lists
    285.             BuildList(male.headAllElements, "Male_Head_All_Elements");
    286.             BuildList(male.headNoElements, "Male_Head_No_Elements");
    287.             BuildList(male.eyebrow, "Male_01_Eyebrows");
    288.             BuildList(male.facialHair, "Male_02_FacialHair");
    289.             BuildList(male.torso, "Male_03_Torso");
    290.             BuildList(male.arm_Upper_Right, "Male_04_Arm_Upper_Right");
    291.             BuildList(male.arm_Upper_Left, "Male_05_Arm_Upper_Left");
    292.             BuildList(male.arm_Lower_Right, "Male_06_Arm_Lower_Right");
    293.             BuildList(male.arm_Lower_Left, "Male_07_Arm_Lower_Left");
    294.             BuildList(male.hand_Right, "Male_08_Hand_Right");
    295.             BuildList(male.hand_Left, "Male_09_Hand_Left");
    296.             BuildList(male.hips, "Male_10_Hips");
    297.             BuildList(male.leg_Right, "Male_11_Leg_Right");
    298.             BuildList(male.leg_Left, "Male_12_Leg_Left");
    299.  
    300.             //add them to the male list
    301.             allObjects[0, (int)BodyParts.HeadAllElements] = male.headAllElements;
    302.             allObjects[0, (int)BodyParts.HeadNoElements] = male.headNoElements;
    303.             allObjects[0, (int)BodyParts.Eyebrow] = male.eyebrow;
    304.             allObjects[0, (int)BodyParts.FacialHair] = male.facialHair;
    305.             allObjects[0, (int)BodyParts.Torso] = male.torso;
    306.             allObjects[0, (int)BodyParts.Arm_Upper_Right] = male.arm_Upper_Right;
    307.             allObjects[0, (int)BodyParts.Arm_Upper_Left] = male.arm_Upper_Left;
    308.             allObjects[0, (int)BodyParts.Arm_Lower_Right] = male.arm_Lower_Right;
    309.             allObjects[0, (int)BodyParts.Arm_Lower_Left] = male.arm_Lower_Left;
    310.             allObjects[0, (int)BodyParts.Hand_Right] = male.hand_Right;
    311.             allObjects[0, (int)BodyParts.Hand_Left] = male.hand_Left;
    312.             allObjects[0, (int)BodyParts.Hips] = male.hips;
    313.             allObjects[0, (int)BodyParts.Leg_Right] = male.leg_Right;
    314.             allObjects[0, (int)BodyParts.Leg_Left] = male.leg_Left;
    315.  
    316.             //build out female lists
    317.             BuildList(female.headAllElements, "Female_Head_All_Elements");
    318.             BuildList(female.headNoElements, "Female_Head_No_Elements");
    319.             BuildList(female.eyebrow, "Female_01_Eyebrows");
    320.             BuildList(female.facialHair, "Female_02_FacialHair");
    321.             BuildList(female.torso, "Female_03_Torso");
    322.             BuildList(female.arm_Upper_Right, "Female_04_Arm_Upper_Right");
    323.             BuildList(female.arm_Upper_Left, "Female_05_Arm_Upper_Left");
    324.             BuildList(female.arm_Lower_Right, "Female_06_Arm_Lower_Right");
    325.             BuildList(female.arm_Lower_Left, "Female_07_Arm_Lower_Left");
    326.             BuildList(female.hand_Right, "Female_08_Hand_Right");
    327.             BuildList(female.hand_Left, "Female_09_Hand_Left");
    328.             BuildList(female.hips, "Female_10_Hips");
    329.             BuildList(female.leg_Right, "Female_11_Leg_Right");
    330.             BuildList(female.leg_Left, "Female_12_Leg_Left");
    331.  
    332.             //add them to the female list
    333.             allObjects[1, (int)BodyParts.HeadAllElements] = female.headAllElements;
    334.             allObjects[1, (int)BodyParts.HeadNoElements] = female.headNoElements;
    335.             allObjects[1, (int)BodyParts.Eyebrow] = female.eyebrow;
    336.             allObjects[1, (int)BodyParts.FacialHair] = female.facialHair;
    337.             allObjects[1, (int)BodyParts.Torso] = female.torso;
    338.             allObjects[1, (int)BodyParts.Arm_Upper_Right] = female.arm_Upper_Right;
    339.             allObjects[1, (int)BodyParts.Arm_Upper_Left] = female.arm_Upper_Left;
    340.             allObjects[1, (int)BodyParts.Arm_Lower_Right] = female.arm_Lower_Right;
    341.             allObjects[1, (int)BodyParts.Arm_Lower_Left] = female.arm_Lower_Left;
    342.             allObjects[1, (int)BodyParts.Hand_Right] = female.hand_Right;
    343.             allObjects[1, (int)BodyParts.Hand_Left] = female.hand_Left;
    344.             allObjects[1, (int)BodyParts.Hips] = female.hips;
    345.             allObjects[1, (int)BodyParts.Leg_Right] = female.leg_Right;
    346.             allObjects[1, (int)BodyParts.Leg_Left] = female.leg_Left;
    347.  
    348.             // build out all gender lists
    349.             BuildList(allGender.all_Hair, "All_01_Hair");
    350.             BuildList(allGender.all_Head_Attachment, "All_02_Head_Attachment");
    351.             BuildList(allGender.headCoverings_Base_Hair, "HeadCoverings_Base_Hair");
    352.             BuildList(allGender.headCoverings_No_FacialHair, "HeadCoverings_No_FacialHair");
    353.             BuildList(allGender.headCoverings_No_Hair, "HeadCoverings_No_Hair");
    354.             BuildList(allGender.chest_Attachment, "All_03_Chest_Attachment");
    355.             BuildList(allGender.back_Attachment, "All_04_Back_Attachment");
    356.             BuildList(allGender.shoulder_Attachment_Right, "All_05_Shoulder_Attachment_Right");
    357.             BuildList(allGender.shoulder_Attachment_Left, "All_06_Shoulder_Attachment_Left");
    358.             BuildList(allGender.elbow_Attachment_Right, "All_07_Elbow_Attachment_Right");
    359.             BuildList(allGender.elbow_Attachment_Left, "All_08_Elbow_Attachment_Left");
    360.             BuildList(allGender.hips_Attachment, "All_09_Hips_Attachment");
    361.             BuildList(allGender.knee_Attachement_Right, "All_10_Knee_Attachement_Right");
    362.             BuildList(allGender.knee_Attachement_Left, "All_11_Knee_Attachement_Left");
    363.             BuildList(allGender.elf_Ear, "Elf_Ear");
    364.  
    365.             //add common parts to both lists
    366.             allObjects[0, (int)BodyParts.All_Hair] = allGender.all_Hair;
    367.             allObjects[0, (int)BodyParts.All_Head_Attachment] = allGender.all_Head_Attachment;
    368.             allObjects[0, (int)BodyParts.HeadCoverings_Base_Hair] = allGender.headCoverings_Base_Hair;
    369.             allObjects[0, (int)BodyParts.HeadCoverings_No_FacialHair] = allGender.headCoverings_No_FacialHair;
    370.             allObjects[0, (int)BodyParts.HeadCoverings_No_Hair] = allGender.headCoverings_No_Hair;
    371.             allObjects[0, (int)BodyParts.Chest_Attachment] = allGender.chest_Attachment;
    372.             allObjects[0, (int)BodyParts.Back_Attachment] = allGender.back_Attachment;
    373.             allObjects[0, (int)BodyParts.Shoulder_Attachment_Right] = allGender.shoulder_Attachment_Right;
    374.             allObjects[0, (int)BodyParts.Shoulder_Attachment_Left] = allGender.shoulder_Attachment_Left;
    375.             allObjects[0, (int)BodyParts.Elbow_Attachment_Right] = allGender.elbow_Attachment_Right;
    376.             allObjects[0, (int)BodyParts.Elbow_Attachment_Left] = allGender.elbow_Attachment_Left;
    377.             allObjects[0, (int)BodyParts.Hips_Attachment] = allGender.hips_Attachment;
    378.             allObjects[0, (int)BodyParts.Knee_Attachement_Right] = allGender.knee_Attachement_Right;
    379.             allObjects[0, (int)BodyParts.Knee_Attachement_Left] = allGender.knee_Attachement_Left;
    380.             allObjects[0, (int)BodyParts.Elf_Ear] = allGender.elf_Ear;
    381.  
    382.             //add common parts to both lists
    383.             allObjects[1, (int)BodyParts.All_Hair] = allGender.all_Hair;
    384.             allObjects[1, (int)BodyParts.All_Head_Attachment] = allGender.all_Head_Attachment;
    385.             allObjects[1, (int)BodyParts.HeadCoverings_Base_Hair] = allGender.headCoverings_Base_Hair;
    386.             allObjects[1, (int)BodyParts.HeadCoverings_No_FacialHair] = allGender.headCoverings_No_FacialHair;
    387.             allObjects[1, (int)BodyParts.HeadCoverings_No_Hair] = allGender.headCoverings_No_Hair;
    388.             allObjects[1, (int)BodyParts.Chest_Attachment] = allGender.chest_Attachment;
    389.             allObjects[1, (int)BodyParts.Back_Attachment] = allGender.back_Attachment;
    390.             allObjects[1, (int)BodyParts.Shoulder_Attachment_Right] = allGender.shoulder_Attachment_Right;
    391.             allObjects[1, (int)BodyParts.Shoulder_Attachment_Left] = allGender.shoulder_Attachment_Left;
    392.             allObjects[1, (int)BodyParts.Elbow_Attachment_Right] = allGender.elbow_Attachment_Right;
    393.             allObjects[1, (int)BodyParts.Elbow_Attachment_Left] = allGender.elbow_Attachment_Left;
    394.             allObjects[1, (int)BodyParts.Hips_Attachment] = allGender.hips_Attachment;
    395.             allObjects[1, (int)BodyParts.Knee_Attachement_Right] = allGender.knee_Attachement_Right;
    396.             allObjects[1, (int)BodyParts.Knee_Attachement_Left] = allGender.knee_Attachement_Left;
    397.             allObjects[1, (int)BodyParts.Elf_Ear] = allGender.elf_Ear;
    398.  
    399.         }
    400.  
    401.         // called from the BuildLists method
    402.         void BuildList(List<GameObject> targetList, string characterPart)
    403.         {
    404.             Transform[] rootTransform = gameObject.GetComponentsInChildren<Transform>();
    405.  
    406.             // declare target root transform
    407.             Transform targetRoot = null;
    408.  
    409.             // find character parts parent object in the scene
    410.             foreach (Transform t in rootTransform)
    411.             {
    412.                 if (t.gameObject.name == characterPart)
    413.                 {
    414.                     targetRoot = t;
    415.                     break;
    416.                 }
    417.             }
    418.  
    419.             // clears targeted list of all objects
    420.             targetList.Clear();
    421.  
    422.             // cycle through all child objects of the parent object
    423.             for (int i = 0; i < targetRoot.childCount; i++)
    424.             {
    425.                 // get child gameobject index i
    426.                 GameObject go = targetRoot.GetChild(i).gameObject;
    427.  
    428.                 // disable child object
    429.                 go.SetActive(false);
    430.  
    431.                 // add object to the targeted object list
    432.                 targetList.Add(go);
    433.  
    434.                 // collect the material for the random character, only if null in the inspector;
    435.                 if (!mat)
    436.                 {
    437.                     if (go.GetComponent<SkinnedMeshRenderer>())
    438.                         mat = go.GetComponent<SkinnedMeshRenderer>().material;
    439.                 }
    440.                 else
    441.                 {
    442.                     if (go.GetComponent<SkinnedMeshRenderer>())
    443.                     {
    444.                         go.GetComponent<SkinnedMeshRenderer>().material = mat;
    445.                     }
    446.                 }
    447.             }
    448.         }
    449.         #endregion
    450.  
    451.         #region Save and Load
    452.         //this save your data
    453.         public object CaptureState()
    454.         {
    455.             Dictionary<string, object> data = new Dictionary<string, object>();
    456.  
    457.             data["gender"] = gender;
    458.             data["head"] = equipped[(int)BodyParts.HeadAllElements];
    459.             data["eyebrows"] = equipped[(int)BodyParts.Eyebrow];
    460.             data["hair"] = equipped[(int)BodyParts.All_Hair];
    461.             data["facialhair"] = equipped[(int)BodyParts.FacialHair];
    462.             return data;
    463.         }
    464.  
    465.         public void RestoreState(object state)
    466.         {
    467.  
    468.             isLoaded = true;
    469.  
    470.             Dictionary<string, object> data = (Dictionary<string, object>)state;
    471.             int gd = (int)data["gender"];
    472.  
    473.             InitBody();
    474.  
    475.             EnableCharacter();
    476.  
    477.             //this part is stupid but lazy developers
    478.             if ((Gender)gd == Gender.Male)
    479.             {
    480.                 SetGender("Gender (Male)", Color.black);
    481.             }
    482.             else
    483.             {
    484.                 SetGender("Gender (Female)", Color.black);
    485.             }
    486.  
    487.             int index = (int)data["head"];
    488.             ActivateItem((int)BodyParts.HeadAllElements, index);
    489.             index = (int)data["eyebrows"];
    490.             ActivateItem((int)BodyParts.Eyebrow, index);
    491.             index = (int)data["hair"];
    492.             ActivateItem((int)BodyParts.All_Hair, index);
    493.             index = (int)data["facialhair"];
    494.             ActivateItem((int)BodyParts.FacialHair, index);
    495.         }
    496.         #endregion
    497.     }
    498. }