CharacterGenerator.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using Sirenix.OdinInspector;
  5. using System;
  6. using System.Linq;
  7. using UnityEngine.Assertions;
  8. using NodeCanvas.Framework;
  9. using KairoEngine.Core;
  10. using KairoEngine.Inventory;
  11. namespace KairoEngine.CharacterSystem
  12. {
  13. public class CharacterGenerator : MonoBehaviour
  14. {
  15. public static CharacterGenerator instance;
  16. public GameObject characterTemplatePrefab;
  17. [AssetList(Path = "/Data/Characters/ModelData/", AutoPopulate = true)]
  18. public List<ModelData> modelList;
  19. [AssetList(Path = "/Data/Characters/Attachments/", AutoPopulate = true)]
  20. public List<GameObject> attachmentList;
  21. void OnEnable()
  22. {
  23. GenericEvents.StartListening("GenerateCharacter", Create);
  24. }
  25. void OnDisable()
  26. {
  27. GenericEvents.StopListening("GenerateCharacter", Create);
  28. }
  29. void Awake()
  30. {
  31. if(instance == null) instance = this;
  32. else Destroy(this.gameObject);
  33. }
  34. public void Create(ScriptableObject scriptableObject)
  35. {
  36. CharacterData characterData = (CharacterData)scriptableObject;
  37. Create(characterData);
  38. }
  39. public static CharacterController Create(CharacterData data, Vector3 position, Quaternion rotation)
  40. {
  41. data.hasSpawned = true;
  42. data.position = position;
  43. data.rotation = rotation;
  44. return Create(data);
  45. }
  46. public static CharacterController Create(CharacterData data)
  47. {
  48. // Instantiate Template Character Prefab
  49. GameObject characterObj = GameObject.Instantiate(instance.characterTemplatePrefab, data.position, data.rotation);
  50. characterObj.name = "Character_" + data.characterName;
  51. CharacterController characterController = characterObj.GetComponentInChildren<CharacterController>();
  52. // Set Body Model
  53. ModelData modelData = FindModel(data.bodyModel);
  54. if(modelData == null)
  55. {
  56. Debug.LogError("No modelData found with name " + data.bodyModel, data);
  57. return null;
  58. }
  59. Material material = GetMaterialInModelData(modelData, data.bodyMaterial);
  60. SkinRigger skinRigger = characterObj.GetComponentInChildren<SkinRigger>();
  61. if(skinRigger == null) Debug.LogError("Missing SkinRigger component", characterObj);
  62. else skinRigger.Setup(modelData, material);
  63. // Set Head Attachment
  64. if(data.headAttachment != "")
  65. {
  66. GameObject headAttachmentPrefab = FindAttachment(data.headAttachment);
  67. if(headAttachmentPrefab != null) GameObject.Instantiate(headAttachmentPrefab, characterController.head.transform);
  68. }
  69. // Set Face Attachment
  70. if(data.faceAttachment != "")
  71. {
  72. GameObject faceAttachmentPrefab = FindAttachment(data.faceAttachment);
  73. if(faceAttachmentPrefab != null) GameObject.Instantiate(faceAttachmentPrefab, characterController.head.transform);
  74. }
  75. // Set Name
  76. characterController.characterName = data.name;
  77. characterController.id = data.id;
  78. // Set Faction
  79. characterController.faction = data.faction;
  80. // Set details
  81. characterController.race = data.race;
  82. characterController.gender = data.gender;
  83. characterController.age = data.age;
  84. // Set Visuals
  85. characterController.bodyModelName = data.bodyModel;
  86. characterController.bodyMaterialName = data.bodyMaterial;
  87. characterController.headAttachmentName = data.headAttachment;
  88. characterController.faceAttachmentName = data.faceAttachment;
  89. // Set Hitpoints and armor
  90. characterController.damageController.SetHP(data.hitpoints);
  91. characterController.damageController.SetMaxHP(data.maxHitpoints);
  92. characterController.damageController.SetArmor(data.armor);
  93. // Set inventory items
  94. ItemContainer itemContainer = characterController.GetComponent<ItemContainer>();
  95. for (int b = 0; b < data.itemList.Count; b++)
  96. {
  97. if(data.itemList[b].item.category == ItemType.firearm)
  98. {
  99. var originalFirearmRef = data.itemList[b] as ItemFirearmRef;
  100. if (originalFirearmRef == null)
  101. {
  102. ItemBaseFirearm itemBaseFirearm = (ItemBaseFirearm)data.itemList[b].item;
  103. ItemBaseAmmo itemBaseAmmo = (ItemBaseAmmo)itemBaseFirearm.ammoType;
  104. int ammo = itemBaseFirearm.ammoCapacity;
  105. ItemFirearmRef firearmRef = new ItemFirearmRef(itemBaseFirearm, data.itemList[b].quantity, itemBaseAmmo, ammo);
  106. itemContainer.AddItem(firearmRef);
  107. }
  108. else
  109. {
  110. ItemFirearmRef newFirearm = new ItemFirearmRef(data.itemList[b].item, data.itemList[b].quantity, originalFirearmRef.ammoType,
  111. originalFirearmRef.ammo, originalFirearmRef.accuracyModifier, originalFirearmRef.lastUsed);
  112. itemContainer.AddItem(newFirearm);
  113. }
  114. }
  115. else
  116. {
  117. ItemRef newItem = new ItemRef(data.itemList[b].item, data.itemList[b].quantity, data.itemList[b].lastUsed);
  118. itemContainer.AddItem(newItem);
  119. }
  120. }
  121. // Set Sensors
  122. if(characterController.visionSensor != null) characterController.visionSensor.enabled = data.vision;
  123. if(characterController.hearingSensor != null) characterController.hearingSensor.enabled = data.hearing;
  124. // Set death stance
  125. if(data.isDead)
  126. {
  127. characterController.Die();
  128. SetBones(data.bones, characterController);
  129. }
  130. // Set Dialogue
  131. Blackboard blackboard = characterController.GetComponent<Blackboard>();
  132. if(blackboard !=null && data.dialogueTree != null) blackboard.SetVariableValue("dialogueTree", data.dialogueTree);
  133. return characterController;
  134. }
  135. public static ModelData FindModel(string title)
  136. {
  137. for (int i = 0; i < instance.modelList.Count; i++)
  138. {
  139. if(instance.modelList[i] != null)
  140. {
  141. if(instance.modelList[i].name == title) return instance.modelList[i];
  142. }
  143. }
  144. return null;
  145. }
  146. public static Material GetMaterialInModelData(ModelData modelData, string materialName)
  147. {
  148. if(modelData != null)
  149. {
  150. for (int i = 0; i < modelData.materials.Count; i++)
  151. {
  152. if(modelData.materials[i].name == materialName) return modelData.materials[i];
  153. }
  154. }
  155. return null;
  156. }
  157. public static GameObject FindAttachment(string title)
  158. {
  159. for (int i = 0; i < instance.attachmentList.Count; i++)
  160. {
  161. if(instance.attachmentList[i].name == title) return instance.attachmentList[i];
  162. }
  163. return null;
  164. }
  165. public static void SetBones(List<DataBone> bones, CharacterController character)
  166. {
  167. int boneCount = 0;
  168. character.animator.enabled = false;
  169. Destroy(character.puppetMaster.gameObject);
  170. Transform[] transforms = character.transform.root.GetComponentsInChildren<Transform>();
  171. for (int i = 0; i < bones.Count; i++)
  172. {
  173. for (int a = 0; a < transforms.Length; a++)
  174. {
  175. if(bones[i].name == transforms[a].gameObject.name)
  176. {
  177. transforms[a].position = bones[i].position;
  178. transforms[a].rotation = bones[i].rotation;
  179. boneCount += 1;
  180. }
  181. }
  182. }
  183. Debug.Log($"Set up {boneCount}/{bones.Count} bones for {character.unique_name}");
  184. }
  185. public static void UpdateBoneOrder(SkinnedMeshRenderer meshRenderer)
  186. {
  187. Transform[] children = meshRenderer.rootBone.GetComponentsInChildren<Transform>();
  188. Transform[] bones = new Transform[meshRenderer.bones.Length];
  189. for (int boneOrder = 0; boneOrder < meshRenderer.bones.Length; boneOrder++)
  190. {
  191. bones[boneOrder] = Array.Find<Transform>(children, c => c.name == meshRenderer.bones[boneOrder].name);
  192. }
  193. meshRenderer.bones = bones;
  194. }
  195. public static void UpdateBoneOrder2(SkinnedMeshRenderer rend)
  196. {
  197. //list of bones
  198. List<Transform> tList = rend.bones.ToList();
  199. //sort alphabetically
  200. tList.Sort(CompareTransform);
  201. //record bone index mappings (richardf advice)
  202. //build a Dictionary<int, int> that records the old bone index => new bone index mappings,
  203. //then run through every vertex and just do boneIndexN = dict[boneIndexN] for each weight on each vertex.
  204. Dictionary<int, int> remap = new Dictionary<int, int>();
  205. for (int i = 0; i < rend.bones.Length; i++)
  206. {
  207. remap[i] = tList.IndexOf(rend.bones[i]);
  208. }
  209. //remap bone weight indexes
  210. BoneWeight[] bw = rend.sharedMesh.boneWeights;
  211. for (int i = 0; i < bw.Length; i++)
  212. {
  213. bw[i].boneIndex0 = remap[bw[i].boneIndex0];
  214. bw[i].boneIndex1 = remap[bw[i].boneIndex1];
  215. bw[i].boneIndex2 = remap[bw[i].boneIndex2];
  216. bw[i].boneIndex3 = remap[bw[i].boneIndex3];
  217. }
  218. //remap bindposes
  219. Matrix4x4[] bp = new Matrix4x4[rend.sharedMesh.bindposes.Length];
  220. for (int i = 0; i < bp.Length; i++)
  221. {
  222. var r = remap[i];
  223. if(bp.Length > r && rend.sharedMesh.bindposes.Length > i)
  224. {
  225. bp[r] = rend.sharedMesh.bindposes[i];
  226. }
  227. }
  228. //assign new data
  229. rend.bones = tList.ToArray();
  230. rend.sharedMesh.boneWeights = bw;
  231. rend.sharedMesh.bindposes = bp;
  232. }
  233. private static int CompareTransform(Transform A, Transform B)
  234. {
  235. return A.name.CompareTo(B.name);
  236. }
  237. }
  238. }