CharacterEntity.cs 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.SceneManagement;
  5. using System.IO;
  6. /// <summary>
  7. /// This script is to manage the characters, you can inherit your character control script from it.
  8. /// </summary>
  9. namespace SoftKitty.MasterCharacterCreator
  10. {
  11. public class CharacterEntity : MonoBehaviour
  12. {
  13. #region variables
  14. [HideInInspector]
  15. public string uid = "DemoCharacter";
  16. [HideInInspector]
  17. public CharacterAppearance mCharacterAppearance;
  18. [HideInInspector]
  19. public string EditorRootPath;
  20. [HideInInspector]
  21. public bool LoadFromBlueprint = false;
  22. [HideInInspector]
  23. public string BlueprintPath = "";
  24. [HideInInspector]
  25. public RuntimeAnimatorController MaleController;
  26. [HideInInspector]
  27. public RuntimeAnimatorController FemaleController;
  28. [HideInInspector]
  29. public bool AutoInitializeWithDefaultLooking = false;
  30. [HideInInspector]
  31. public WeaponController [] Weapons;
  32. [HideInInspector]
  33. public int WeaponEquipType = 0;
  34. [HideInInspector]
  35. public WeaponState DefaultWeaponState = WeaponState.Carry;
  36. [HideInInspector]
  37. public CharacterBoneControl mCharacterBoneControl;
  38. private WeaponState CurrentWeaponState = WeaponState.Hide;
  39. protected Animator mAnimator;
  40. public Transform LookAtTarget;
  41. public bool TogglePlaceHolderGizmo = true;
  42. public Mesh PlaceHolderMesh;
  43. public Color PlaceHolderColor= new Color(0F, 0.7F, 1F, 0.5F);
  44. private Coroutine ResetCo;
  45. private Dictionary<WeaponType, WeaponController> EquippedWeapons = new Dictionary<WeaponType, WeaponController>();
  46. #endregion
  47. #region internal methods
  48. IEnumerator ResetAnimator(Avatar _avatar)
  49. {
  50. yield return 1;
  51. mAnimator.avatar = _avatar;
  52. }
  53. public virtual void Start()
  54. {
  55. if (CharacterManager.isCharacterAppearanceExist(this))
  56. {
  57. if (mCharacterBoneControl != null && CharacterManager.GetAppearanceData(this).isSameAs(mCharacterAppearance))
  58. {
  59. mCharacterBoneControl.MyData = mCharacterAppearance;
  60. LoadDefaultWeapon();
  61. }
  62. else
  63. {
  64. Initialize(CharacterManager.GetAppearanceData(this));
  65. }
  66. }
  67. else
  68. {
  69. if (mCharacterBoneControl != null)
  70. {
  71. CharacterManager.UpdateCharacterAppearance(uid, mCharacterAppearance);
  72. mCharacterBoneControl.MyData = mCharacterAppearance;
  73. LoadDefaultWeapon();
  74. }
  75. else if (LoadFromBlueprint && BlueprintPath.Trim() != "")
  76. {
  77. Initialize(CharacterManager.LoadCharacterDataFromResources(BlueprintPath, null));
  78. }
  79. else if (AutoInitializeWithDefaultLooking)
  80. {
  81. ResetCharacter();
  82. }
  83. else
  84. {
  85. mCharacterAppearance = null;
  86. }
  87. }
  88. }
  89. #if UNITY_EDITOR
  90. private void OnDrawGizmos()
  91. {
  92. if (!Application.isPlaying && TogglePlaceHolderGizmo && PlaceHolderMesh!=null && mCharacterBoneControl==null)
  93. {
  94. Color _color = Gizmos.color;
  95. Gizmos.color = PlaceHolderColor;
  96. Gizmos.DrawMesh(PlaceHolderMesh,0,transform.position,transform.rotation,Vector3.one);
  97. Gizmos.color = _color;
  98. }
  99. }
  100. #endif
  101. #endregion
  102. /// <summary>
  103. /// Returns the gender of this character
  104. /// </summary>
  105. public Sex sex
  106. {
  107. get
  108. {
  109. return mCharacterAppearance._Sex;
  110. }
  111. }
  112. /// <summary>
  113. /// Assigns a random unique ID for this character.
  114. /// </summary>
  115. public void RandomUid()
  116. {
  117. List<byte> _bytes = new List<byte>();
  118. for (int i = 0; i < Random.Range(10, 15); i++)
  119. {
  120. _bytes.Add((byte)Random.Range(63, 123));
  121. }
  122. uid = System.Text.Encoding.ASCII.GetString(_bytes.ToArray()).Replace(@"\","").Replace("/","").Replace(".", "").Replace("^","").Replace("`", "").Replace("@","").Replace("(", "").Replace(")", "").Replace("?", "").Replace("[", "").Replace("]", "").Replace("-", "_");
  123. }
  124. #region Save/Load/Initialize
  125. /// <summary>
  126. /// Initializes the character with a "*.bytes" file in your editor folder, please use absolute full path and with extension. Example:"E:/NpcPreset_1.bytes"
  127. /// </summary>
  128. /// <param name="_editorPath"></param>
  129. public void LoadFromEditor(string _editorPath)
  130. {
  131. if (!Application.isEditor || Application.isPlaying) return;
  132. Initialize(CharacterManager.LoadCharacterDataFromFile(null, Application.dataPath + "/SoftKitty/MasterCharacterCreator/Resources/" + _editorPath + ".bytes"));
  133. }
  134. /// <summary>
  135. /// Initializes the character with a "*.bytes" file in your resources folder, please use relative path without extension from resources folder. Example: "MasterCharacterCreator/CustomBlueprints/Characters/NpcPreset_1"
  136. /// </summary>
  137. /// <param name="_resourcePath"></param>
  138. public void LoadFromResourceFile(string _resourcePath)
  139. {
  140. Initialize(CharacterManager.LoadCharacterDataFromResources(_resourcePath, null));
  141. }
  142. /// <summary>
  143. /// Initializes the character with a "*.bytes" file from disk, please use absolute full path and with extension. Example:"E:/NpcPreset_1.bytes"
  144. /// </summary>
  145. /// <param name="_absolutePath"></param>
  146. public void LoadFromByteFileFromDisk(string _absolutePath)
  147. {
  148. Initialize(CharacterManager.LoadCharacterDataFromFile(mCharacterAppearance,_absolutePath));
  149. }
  150. /// <summary>
  151. /// Initializes the character with a "*.png" file from disk, please use absolute full path and with extension.Example:"E:/NpcPreset_1.png"
  152. /// </summary>
  153. /// <param name="_absolutePath"></param>
  154. public void LoadFromPngFileFromDisk(string _absolutePath)
  155. {
  156. CharacterManager.LoadCharacterDataWithPhoto(ref mCharacterAppearance, _absolutePath);
  157. Initialize(mCharacterAppearance);
  158. }
  159. /// <summary>
  160. /// Initializes the character with the bytes array loaded from your own save system.
  161. /// </summary>
  162. /// <param name="_bytes"></param>
  163. public void LoadFromBytes(byte[] _bytes)
  164. {
  165. if (mCharacterAppearance == null)
  166. mCharacterAppearance = new CharacterAppearance(CharacterData.Create(_bytes[1]));
  167. mCharacterAppearance.Load(_bytes);
  168. Initialize(mCharacterAppearance);
  169. }
  170. /// <summary>
  171. /// Save the character to a "*.bytes" file on disk, please use absolute full path and with extension. Example:"E:/Player.bytes"
  172. /// </summary>
  173. /// <param name="_absolutePath"></param>
  174. /// <param name="_filter"></param>
  175. public void SaveByteFileToDisk(string _absolutePath, BlurPrintType _filter)
  176. {
  177. CharacterManager.SaveCharacterData(mCharacterBoneControl, _absolutePath, _filter);
  178. }
  179. /// <summary>
  180. /// Save the character to a "*.png" file on disk, please use absolute full path and with extension. Example:"E:/Player.png"
  181. /// </summary>
  182. /// <param name="_absolutePath"></param>
  183. /// <param name="_photo"></param>
  184. /// <param name="_filter"></param>
  185. public void SavePngFileToDisk(string _absolutePath, Texture2D _photo, BlurPrintType _filter)
  186. {
  187. CharacterManager.SaveCharacterDataWithPhoto(mCharacterBoneControl, _photo, _absolutePath, _filter);
  188. }
  189. /// <summary>
  190. /// Get the bytes array of the character appearance save data. You can save this with your own save system.
  191. /// </summary>
  192. /// <param name="_filter"></param>
  193. /// <returns></returns>
  194. public byte[] GetSaveBytes(BlurPrintType _filter= BlurPrintType.AllAppearance)
  195. {
  196. return mCharacterAppearance.ToBytes(_filter);
  197. }
  198. /// <summary>
  199. /// Initializes the character with a specified appearance data.
  200. /// </summary>
  201. /// <param name="_data"></param>
  202. public void Initialize(CharacterAppearance _data)
  203. {
  204. if (Application.isPlaying && ResetCo != null) StopCoroutine(ResetCo);
  205. mAnimator = GetComponent<Animator>();
  206. mAnimator.avatar = null;
  207. if (mCharacterBoneControl != null) DestroyImmediate(mCharacterBoneControl.gameObject);
  208. mCharacterAppearance = _data;
  209. mCharacterBoneControl = Instantiate(Resources.Load<GameObject>("MasterCharacterCreator/Player/" + (sex == Sex.Female ? "CharacterFemale" : "CharacterMale")),transform).GetComponent<CharacterBoneControl>();
  210. mAnimator.runtimeAnimatorController = sex == Sex.Male ? MaleController : FemaleController;
  211. Avatar _avatar = mCharacterBoneControl.GetComponent<Animator>().avatar;
  212. DestroyImmediate(mCharacterBoneControl.GetComponent<Animator>());
  213. mCharacterBoneControl.transform.localPosition = Vector3.zero;
  214. mCharacterBoneControl.transform.localEulerAngles = Vector3.zero;
  215. mCharacterBoneControl.transform.localScale = Vector3.one;
  216. #if UNITY_EDITOR
  217. if (Application.isEditor && !Application.isPlaying)
  218. {
  219. if (!Directory.Exists(Application.dataPath + "/SoftKitty/MasterCharacterCreator/UniqueCharacterAssets"))
  220. Directory.CreateDirectory(Application.dataPath + "/SoftKitty/MasterCharacterCreator/UniqueCharacterAssets");
  221. if (!Directory.Exists(Application.dataPath + "/SoftKitty/MasterCharacterCreator/UniqueCharacterAssets/" + uid))
  222. Directory.CreateDirectory(Application.dataPath + "/SoftKitty/MasterCharacterCreator/UniqueCharacterAssets/" + uid);
  223. mCharacterBoneControl.EditorPath = "Assets/SoftKitty/MasterCharacterCreator/UniqueCharacterAssets/" + uid;
  224. mAnimator.avatar = _avatar;
  225. }
  226. #endif
  227. mCharacterBoneControl.Initialize(mCharacterAppearance);
  228. if (Application.isPlaying)
  229. {
  230. ResetCo = StartCoroutine(ResetAnimator(_avatar));
  231. CharacterManager.UpdateCharacterAppearance(uid, mCharacterAppearance);
  232. LoadDefaultWeapon();
  233. }
  234. mCharacterBoneControl.LookAtTarget = LookAtTarget;
  235. }
  236. /// <summary>
  237. /// Initializes the character with the default appearance.
  238. /// </summary>
  239. /// <param name="_sex"></param>
  240. public void Initialize(Sex _sex)
  241. {
  242. mAnimator = GetComponent<Animator>();
  243. mAnimator.avatar = null;
  244. if (mCharacterBoneControl != null) Destroy(mCharacterBoneControl.gameObject);
  245. mCharacterAppearance = new CharacterAppearance(CharacterData.Create((byte)_sex));
  246. mCharacterBoneControl = Instantiate(Resources.Load<GameObject>("MasterCharacterCreator/Player/" + (sex == Sex.Female ? "CharacterFemale" : "CharacterMale")), transform).GetComponent<CharacterBoneControl>();
  247. mAnimator.runtimeAnimatorController = sex == Sex.Male ? MaleController : FemaleController;
  248. Avatar _avatar = mCharacterBoneControl.GetComponent<Animator>().avatar;
  249. DestroyImmediate(mCharacterBoneControl.GetComponent<Animator>());
  250. mCharacterBoneControl.transform.localPosition = Vector3.zero;
  251. mCharacterBoneControl.transform.localEulerAngles = Vector3.zero;
  252. mCharacterBoneControl.transform.localScale = Vector3.one;
  253. mCharacterBoneControl.Initialize(mCharacterAppearance);
  254. StartCoroutine(ResetAnimator(_avatar));
  255. CharacterManager.UpdateCharacterAppearance(uid, mCharacterAppearance);
  256. mCharacterBoneControl.LookAtTarget = LookAtTarget;
  257. LoadDefaultWeapon();
  258. }
  259. #endregion
  260. #region Weapons
  261. /// <summary>
  262. /// Load the weapons set in the inspector.
  263. /// </summary>
  264. public void LoadDefaultWeapon()
  265. {
  266. UnequipAllWeapons();
  267. for (int i=0;i< Weapons.Length;i++) {
  268. if(Weapons[i] != null) EquipWeapon(Weapons[i], DefaultWeaponState);
  269. }
  270. }
  271. /// <summary>
  272. /// Equip a weapon and set its default state.
  273. /// </summary>
  274. /// <param name="_weapon"></param>
  275. /// <param name="_state"></param>
  276. public void EquipWeapon(WeaponController _weapon, WeaponState _state= WeaponState.Carry)
  277. {
  278. if (mCharacterBoneControl == null) {
  279. Debug.LogError("Trying to load the weapon when the character is not ready.");
  280. return;
  281. }
  282. if (WeaponEquipType == 3)
  283. {
  284. if (EquippedWeapons.ContainsKey(_weapon.Type)) UnequipWeapon(_weapon.Type);
  285. }
  286. else{
  287. if (_weapon.Type == WeaponType.TwoHanded)
  288. {
  289. if (EquippedWeapons.ContainsKey(WeaponType.LeftHand)) UnequipWeapon(WeaponType.LeftHand);
  290. if (EquippedWeapons.ContainsKey(WeaponType.RightHand)) UnequipWeapon(WeaponType.RightHand);
  291. }
  292. if ((_weapon.Type== WeaponType.LeftHand || _weapon.Type == WeaponType.RightHand || _weapon.Type == WeaponType.TwoHanded) && EquippedWeapons.ContainsKey(WeaponType.TwoHanded)) UnequipWeapon(WeaponType.TwoHanded);
  293. if (EquippedWeapons.ContainsKey(_weapon.Type)) UnequipWeapon(_weapon.Type);
  294. }
  295. Transform _parent=null;
  296. string _parentBoneName = "";
  297. int _stateId = 0;
  298. int _sexId = (int)mCharacterAppearance._Sex;
  299. if (_weapon.Data.VisibleWhenCarry && _state == WeaponState.Carry)
  300. {
  301. _parentBoneName= _weapon.Data.CarryParentTransform;
  302. _stateId = 1;
  303. } else {
  304. _parentBoneName = _weapon.Data.HoldParentTransform;
  305. _stateId = 0;
  306. }
  307. if (_parentBoneName != "" && mCharacterBoneControl.BoneDictionary.ContainsKey(_parentBoneName)) {
  308. _parent = mCharacterBoneControl.BoneDictionary[_parentBoneName];
  309. }
  310. if (_parent != null)
  311. {
  312. GameObject _newWeapon = Instantiate(_weapon.gameObject, _parent);
  313. _newWeapon.transform.localPosition = _weapon.Data.Pos[_sexId*2+_stateId];
  314. _newWeapon.transform.localEulerAngles = _weapon.Data.Rot[_sexId * 2 + _stateId];
  315. _newWeapon.transform.localScale = _weapon.Data.Scale[_sexId * 2 + _stateId];
  316. _newWeapon.gameObject.SetActive(_state != WeaponState.Hide);
  317. _newWeapon.GetComponent<WeaponController>().SetSheath(_state == WeaponState.Hold, this);
  318. EquippedWeapons.Add(_weapon.Type, _newWeapon.GetComponent<WeaponController>());
  319. CurrentWeaponState = _state;
  320. }
  321. else
  322. {
  323. Debug.LogError("Can not find parent bone ["+ _parentBoneName+"] for "+ _weapon.gameObject.name);
  324. }
  325. }
  326. /// <summary>
  327. /// Unequip a weapon with specified slot.
  328. /// </summary>
  329. /// <param name="_slot"></param>
  330. public void UnequipWeapon(WeaponType _slot)
  331. {
  332. if (EquippedWeapons.ContainsKey(_slot))
  333. {
  334. if (EquippedWeapons[_slot] != null)EquippedWeapons[_slot].Unequip();
  335. EquippedWeapons.Remove(_slot);
  336. }
  337. }
  338. /// <summary>
  339. /// Unequip all weapons.
  340. /// </summary>
  341. public void UnequipAllWeapons()
  342. {
  343. foreach (var key in EquippedWeapons.Keys)
  344. {
  345. if (EquippedWeapons[key] != null) EquippedWeapons[key].Unequip();
  346. }
  347. EquippedWeapons.Clear();
  348. }
  349. /// <summary>
  350. /// Switch the state of the weapon with specified slot.
  351. /// </summary>
  352. /// <param name="_state"></param>
  353. /// <param name="_slot"></param>
  354. public void SwitchWeaponState(WeaponState _state, WeaponType _slot)
  355. {
  356. if (EquippedWeapons.ContainsKey(_slot)) {
  357. if (_state == WeaponState.Hide) {
  358. EquippedWeapons[_slot].gameObject.SetActive(false);
  359. EquippedWeapons[_slot].SetSheath(false,this);
  360. } else {
  361. Transform _parent = null;
  362. string _parentBoneName = "";
  363. int _stateId = 0;
  364. int _sexId = (int)mCharacterAppearance._Sex;
  365. if (_state == WeaponState.Carry)
  366. {
  367. if (!EquippedWeapons[_slot].Data.VisibleWhenCarry)
  368. {
  369. EquippedWeapons[_slot].gameObject.SetActive(false);
  370. }
  371. else
  372. {
  373. _parentBoneName = EquippedWeapons[_slot].Data.CarryParentTransform;
  374. _stateId = 1;
  375. }
  376. }
  377. else if (_state == WeaponState.Hold)
  378. {
  379. _parentBoneName = EquippedWeapons[_slot].Data.HoldParentTransform;
  380. _stateId = 0;
  381. }
  382. if (_parentBoneName!="" && mCharacterBoneControl.BoneDictionary.ContainsKey(_parentBoneName))
  383. {
  384. _parent = mCharacterBoneControl.BoneDictionary[_parentBoneName];
  385. }
  386. if (_parent != null)
  387. {
  388. EquippedWeapons[_slot].transform.SetParent( _parent);
  389. EquippedWeapons[_slot].transform.localPosition = EquippedWeapons[_slot].Data.Pos[_sexId * 2 + _stateId];
  390. EquippedWeapons[_slot].transform.localEulerAngles = EquippedWeapons[_slot].Data.Rot[_sexId * 2 + _stateId];
  391. EquippedWeapons[_slot].transform.localScale = EquippedWeapons[_slot].Data.Scale[_sexId * 2 + _stateId];
  392. EquippedWeapons[_slot].gameObject.SetActive(true);
  393. EquippedWeapons[_slot].GetComponent<WeaponController>().SetSheath(_state == WeaponState.Hold, this);
  394. }
  395. else
  396. {
  397. Debug.LogError("Can not find parent bone [" + _parentBoneName + "] for " + EquippedWeapons[_slot].gameObject.name);
  398. }
  399. }
  400. }
  401. }
  402. /// <summary>
  403. /// Switch the state of all weapons
  404. /// </summary>
  405. /// <param name="_state"></param>
  406. public void SwitchWeaponState(WeaponState _state)
  407. {
  408. foreach (var key in EquippedWeapons.Keys)
  409. {
  410. if (EquippedWeapons[key] != null) SwitchWeaponState(_state, key);
  411. }
  412. CurrentWeaponState = _state;
  413. }
  414. /// <summary>
  415. /// Get the current weapon state.
  416. /// </summary>
  417. /// <returns></returns>
  418. public WeaponState GetWeaponState()
  419. {
  420. return CurrentWeaponState;
  421. }
  422. /// <summary>
  423. /// Return bool value for whether a weapon with specified uid is equipped.
  424. /// </summary>
  425. /// <param name="_uid"></param>
  426. /// <returns></returns>
  427. public bool isEquippedWeapon(string _uid)
  428. {
  429. return GetEquippedWeaponByUid(_uid) != null;
  430. }
  431. /// <summary>
  432. /// Get a equipped weapon with specified slot.
  433. /// </summary>
  434. /// <param name="_slot"></param>
  435. /// <returns></returns>
  436. public WeaponController GetEquippedWeaponByType(WeaponType _slot)
  437. {
  438. if (EquippedWeapons.ContainsKey(_slot))
  439. {
  440. return EquippedWeapons[_slot];
  441. }
  442. return null;
  443. }
  444. /// <summary>
  445. /// Get a equipped weapon with specified uid, return null if no match found.
  446. /// </summary>
  447. /// <param name="_uid"></param>
  448. /// <returns></returns>
  449. public WeaponController GetEquippedWeaponByUid(string _uid)
  450. {
  451. foreach (var key in EquippedWeapons.Keys)
  452. {
  453. if (EquippedWeapons[key] != null && EquippedWeapons[key].uid==_uid) return EquippedWeapons[key];
  454. }
  455. return null;
  456. }
  457. /// <summary>
  458. /// Get a list of all equipped weapon
  459. /// </summary>
  460. /// <returns></returns>
  461. public List<WeaponController> GetAllEquippedWeapon()
  462. {
  463. List<WeaponController> _weapons = new List<WeaponController>();
  464. foreach (var key in EquippedWeapons.Keys)
  465. {
  466. _weapons.Add(EquippedWeapons[key]);
  467. }
  468. return _weapons;
  469. }
  470. #endregion
  471. ///Bind an <EquipmentAppearance> class to your equipment data, and call this function when the character equips new gear to reflect the change in appearance.
  472. #region Equipment
  473. /// <summary>
  474. /// Equips a gear item and updates the character's appearance accordingly.
  475. /// </summary>
  476. /// <param name="_equipment"></param>
  477. public void Equip(EquipmentAppearance _equipment)
  478. {
  479. mCharacterAppearance._OutfitID[(int)_equipment.Type] = (byte)_equipment.GetId(sex);
  480. if (_equipment.UseCustomColor)
  481. {
  482. mCharacterAppearance._CusColor1[(int)_equipment.Type] = Uint8Color.Set(_equipment.CustomColor1);
  483. mCharacterAppearance._CusColor2[(int)_equipment.Type] = Uint8Color.Set(_equipment.CustomColor2);
  484. mCharacterAppearance._CusColor3[(int)_equipment.Type] = Uint8Color.Set(_equipment.CustomColor3);
  485. }
  486. else if((int)_equipment.Type<5)
  487. {
  488. OutfitColorSetting _setting = CharacterDataSetting.instance.GetOutfitColorSetting(sex, _equipment.Type, mCharacterAppearance._OutfitID[(int)_equipment.Type]);
  489. mCharacterAppearance._CusColor1[(int)_equipment.Type] = Uint8Color.Set(_setting.DefaultColor1);
  490. mCharacterAppearance._CusColor2[(int)_equipment.Type] = Uint8Color.Set(_setting.DefaultColor2);
  491. mCharacterAppearance._CusColor3[(int)_equipment.Type] = Uint8Color.Set(_setting.DefaultColor3);
  492. }
  493. else
  494. {
  495. mCharacterAppearance._CusColor1[(int)_equipment.Type] = Uint8Color.Set(Color.white);
  496. mCharacterAppearance._CusColor2[(int)_equipment.Type] = Uint8Color.Set(Color.white);
  497. mCharacterAppearance._CusColor3[(int)_equipment.Type] = Uint8Color.Set(Color.white);
  498. }
  499. }
  500. /// <summary>
  501. /// Equips an item with its slot and id and updates the character's appearance accordingly.
  502. /// </summary>
  503. /// <param name="_slot"></param>
  504. /// <param name="_id"></param>
  505. public void Equip(OutfitSlots _slot, int _id)
  506. {
  507. mCharacterAppearance._OutfitID[(int)_slot] = (byte)_id;
  508. if ((int)_slot < 5)
  509. {
  510. OutfitColorSetting _setting = CharacterDataSetting.instance.GetOutfitColorSetting(sex, _slot, mCharacterAppearance._OutfitID[(int)_slot]);
  511. mCharacterAppearance._CusColor1[(int)_slot] = Uint8Color.Set(_setting.DefaultColor1);
  512. mCharacterAppearance._CusColor2[(int)_slot] = Uint8Color.Set(_setting.DefaultColor2);
  513. mCharacterAppearance._CusColor3[(int)_slot] = Uint8Color.Set(_setting.DefaultColor3);
  514. }
  515. else
  516. {
  517. mCharacterAppearance._CusColor1[(int)_slot] = Uint8Color.Set(Color.white);
  518. mCharacterAppearance._CusColor2[(int)_slot] = Uint8Color.Set(Color.white);
  519. mCharacterAppearance._CusColor3[(int)_slot] = Uint8Color.Set(Color.white);
  520. }
  521. }
  522. /// <summary>
  523. /// Equips an item with its slot, id and custom colors, then updates the character's appearance accordingly.
  524. /// </summary>
  525. /// <param name="_slot"></param>
  526. /// <param name="_id"></param>
  527. /// <param name="_color1"></param>
  528. /// <param name="_color2"></param>
  529. /// <param name="_color3"></param>
  530. public void Equip(OutfitSlots _slot, int _id, Color _color1,Color _color2,Color _color3)
  531. {
  532. mCharacterAppearance._OutfitID[(int)_slot] = (byte)_id;
  533. mCharacterAppearance._CusColor1[(int)_slot] = Uint8Color.Set(_color1);
  534. mCharacterAppearance._CusColor2[(int)_slot] = Uint8Color.Set(_color2);
  535. mCharacterAppearance._CusColor3[(int)_slot] = Uint8Color.Set(_color3);
  536. }
  537. /// <summary>
  538. /// Unequips a specific outfit slot (e.g., helmet, armor).
  539. /// </summary>
  540. /// <param name="_slot"></param>
  541. public void Unequip(OutfitSlots _slot)
  542. {
  543. mCharacterAppearance._OutfitID[(int)_slot] = 0;
  544. if ((int)_slot < 5)
  545. {
  546. OutfitColorSetting _setting = CharacterDataSetting.instance.GetOutfitColorSetting(sex, _slot, 0);
  547. mCharacterAppearance._CusColor1[(int)_slot] = Uint8Color.Set(_setting.DefaultColor1);
  548. mCharacterAppearance._CusColor2[(int)_slot] = Uint8Color.Set(_setting.DefaultColor2);
  549. mCharacterAppearance._CusColor3[(int)_slot] = Uint8Color.Set(_setting.DefaultColor3);
  550. }
  551. }
  552. /// <summary>
  553. /// Returns whether a specific piece of equipment is equipped.
  554. /// </summary>
  555. /// <param name="_equipment"></param>
  556. /// <returns></returns>
  557. public bool isEquipped(EquipmentAppearance _equipment)
  558. {
  559. return mCharacterAppearance._OutfitID[(int)_equipment.Type] == _equipment.GetId(sex);
  560. }
  561. /// <summary>
  562. /// Returns whether a specific equipment with provided slot and id is equipped.
  563. /// </summary>
  564. /// <param name="_slot"></param>
  565. /// <param name="_id"></param>
  566. /// <returns></returns>
  567. public bool isEquipped(OutfitSlots _slot, int _id)
  568. {
  569. return mCharacterAppearance._OutfitID[(int)_slot] == _id;
  570. }
  571. /// <summary>
  572. /// Retrieves the mesh ID of the currently equipped item in the specified slot.
  573. /// </summary>
  574. /// <param name="_slot"></param>
  575. /// <returns></returns>
  576. public int GetEquippedId(OutfitSlots _slot)
  577. {
  578. return mCharacterAppearance._OutfitID[(int)_slot];
  579. }
  580. #endregion
  581. #region Character
  582. /// <summary>
  583. /// Take a photo of the character and return the photo as Texture2D.
  584. /// </summary>
  585. /// <param name="_imageSize"></param>
  586. /// <param name="_bgColor"></param>
  587. /// <param name="_cameraAngle"></param>
  588. /// <param name="_cameraLight"></param>
  589. /// <returns></returns>
  590. public Texture2D GetCharacterPhoto(Vector2 _imageSize, Color _bgColor, float _cameraAngle=0F,bool _cameraLight=true)
  591. {
  592. return PhotoHouse.TakePhoto(_imageSize,GetBoneByName("Bip001 Head"), _bgColor, _cameraAngle, _cameraLight);
  593. }
  594. /// <summary>
  595. /// Get the animation compnent of the back accessory.
  596. /// </summary>
  597. /// <returns></returns>
  598. public Animation GetBackAnimationComponent()
  599. {
  600. if (mCharacterBoneControl == null) return null;
  601. return mCharacterBoneControl.BackAnimation;
  602. }
  603. /// <summary>
  604. /// Get the animation compnent of the tail accessory.
  605. /// </summary>
  606. /// <returns></returns>
  607. public Animation GetTailAnimationComponent()
  608. {
  609. if (mCharacterBoneControl == null) return null;
  610. return mCharacterBoneControl.TailAnimation;
  611. }
  612. /// <summary>
  613. /// Get the animation compnent of the head accessory.
  614. /// </summary>
  615. /// <returns></returns>
  616. public Animation GetHeadAccessoryAnimationComponent()
  617. {
  618. if (mCharacterBoneControl == null) return null;
  619. return mCharacterBoneControl.HeadAccAnimation;
  620. }
  621. /// <summary>
  622. /// Get the bone transform of the character by the name of the bone.
  623. /// </summary>
  624. /// <param name="_name"></param>
  625. /// <returns></returns>
  626. public Transform GetBoneByName(string _name)
  627. {
  628. if (mCharacterBoneControl != null)
  629. {
  630. if (mCharacterBoneControl.BoneDictionary.ContainsKey(_name)) return mCharacterBoneControl.BoneDictionary[_name];
  631. }
  632. return null;
  633. }
  634. /// <summary>
  635. /// Sets the character's emotion and specifies how long the emotion will last
  636. /// </summary>
  637. /// <param name="_uid"></param>
  638. /// <param name="_length"></param>
  639. public void SetEmotion(string _uid, float _length = 3F)
  640. {
  641. if (mCharacterBoneControl == null) return;
  642. mCharacterBoneControl.SetEmotion(_uid, _length);
  643. }
  644. /// <summary>
  645. /// Stop the current emotion and reset it to default emotion.
  646. /// </summary>
  647. public void StopEmotion()
  648. {
  649. if (mCharacterBoneControl == null) return;
  650. mCharacterBoneControl.StopEmotion();
  651. }
  652. /// <summary>
  653. /// Sets the percentage of the character¡¯s eye openness. 1~100
  654. /// </summary>
  655. /// <param name="_openPercentage"></param>
  656. public void SetEyeOpen(float _openPercentage)
  657. {
  658. if (mCharacterBoneControl == null) return;
  659. mCharacterBoneControl.EyeOpen= _openPercentage;
  660. }
  661. /// <summary>
  662. /// Set the rim effect color, this could be useful for highlight the character or when the character gets hit.
  663. /// </summary>
  664. /// <param name="_color"></param>
  665. /// <param name="_intensity"></param>
  666. public void SetRimColor(Color _color, float _intensity)//
  667. {
  668. mCharacterBoneControl.RimColor = _color * _intensity;
  669. }
  670. /// <summary>
  671. /// Get the rim effect color, this could be useful for highlight the character or when the character gets hit.
  672. /// </summary>
  673. /// <returns></returns>
  674. public Color GetRimColor()
  675. {
  676. return mCharacterBoneControl.RimColor;
  677. }
  678. /// <summary>
  679. /// Forces the character to blink immediately.
  680. /// </summary>
  681. public void Blink()
  682. {
  683. if (mCharacterBoneControl == null) return;
  684. mCharacterBoneControl.Blink();
  685. }
  686. /// <summary>
  687. /// Makes the character look at a specified transform target.
  688. /// </summary>
  689. /// <param name="_target"></param>
  690. public void SetLookAt(Transform _target)
  691. {
  692. if (mCharacterBoneControl == null) return;
  693. LookAtTarget = _target;
  694. mCharacterBoneControl.LookAtTarget= LookAtTarget;
  695. }
  696. #endregion
  697. #region Customization
  698. /// <summary>
  699. /// Resets the character¡¯s appearance back to its default state.
  700. /// </summary>
  701. public void ResetCharacter()
  702. {
  703. Debug.Log("Reset Character");
  704. mCharacterAppearance = new CharacterAppearance(CharacterData.Create((byte)Sex.Male));
  705. Initialize(mCharacterAppearance);
  706. }
  707. /// <summary>
  708. /// Switches to the Character Customization UI with this character (for player use)
  709. /// </summary>
  710. public void CustomizeCharacter()
  711. {
  712. if (mCharacterAppearance == null) ResetCharacter();
  713. CharacterCusSetting _setting = new CharacterCusSetting()
  714. {
  715. AllowCustomOutfit = CharacterManager.instance.AllowOutfitsWhenCustomize,
  716. AllowNameChange = CharacterManager.instance.AllowChangeNameWhenCustomize,
  717. AllowSexSwitch = CharacterManager.instance.AllowChangeSexWhenCustomize,
  718. AllowRaceChange = CharacterManager.instance.AllowChangeRaceWhenCustomize,
  719. RaceSettingVisible = CharacterManager.instance.RaceSettingVisible,
  720. BackCategoryVisible = CharacterManager.instance.BackCategoryVisible,
  721. TailCategoryVisible = CharacterManager.instance.TailCategoryVisible
  722. };
  723. CharacterManager.StartCreation(this, CharacterManager.instance.BlueprintPath, SaveMethod.PngFile, _setting, SceneManager.GetActiveScene());
  724. }
  725. /// <summary>
  726. /// Switches to the Character Creation UI (for player use)
  727. /// </summary>
  728. public void CreateCharacter()
  729. {
  730. if (mCharacterAppearance == null) ResetCharacter();
  731. CharacterCusSetting _setting = new CharacterCusSetting()
  732. {
  733. AllowCustomOutfit = CharacterManager.instance.AllowOutfitsWhenCreate,
  734. AllowNameChange = true,
  735. AllowSexSwitch = CharacterManager.instance.AllowChangeSexWhenCreate,
  736. AllowRaceChange=true,
  737. RaceSettingVisible = CharacterManager.instance.RaceSettingVisible,
  738. BackCategoryVisible = CharacterManager.instance.BackCategoryVisible,
  739. TailCategoryVisible = CharacterManager.instance.TailCategoryVisible
  740. };
  741. CharacterManager.StartCreation(this, CharacterManager.instance.BlueprintPath, SaveMethod.PngFile, _setting, SceneManager.GetActiveScene());
  742. }
  743. /// <summary>
  744. /// Switches to the Character Creation UI (for developer use, with more options)
  745. /// </summary>
  746. public void CreateCharacterByDeveloper()
  747. {
  748. if (mCharacterAppearance == null) ResetCharacter();
  749. CharacterCusSetting _setting = new CharacterCusSetting()
  750. {
  751. AllowCustomOutfit = true,
  752. AllowNameChange = true,
  753. AllowSexSwitch = true,
  754. AllowRaceChange = true,
  755. RaceSettingVisible = true,
  756. BackCategoryVisible = true,
  757. TailCategoryVisible = true
  758. };
  759. #if UNITY_EDITOR
  760. CharacterManager.StartCreation(this, Application.dataPath + EditorRootPath, SaveMethod.BytesFile, _setting, SceneManager.GetActiveScene());
  761. #else
  762. string _path = Application.dataPath + "/../Blueprints";
  763. CharacterManager.StartCreation(this, CharacterManager.instance.BlueprintPath, SaveMethod.BytesFile, _setting, SceneManager.GetActiveScene());
  764. #endif
  765. }
  766. #endregion
  767. }
  768. }