LoadExtraAnimationsSample.cs 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. #pragma warning disable 649
  2. using System.Collections.Generic;
  3. using TriLibCore.Extensions;
  4. using TriLibCore.Utils;
  5. using UnityEngine;
  6. using UnityEngine.UI;
  7. #if UNITY_EDITOR
  8. using UnityEditor;
  9. #endif
  10. namespace TriLibCore.Samples
  11. {
  12. /// <summary>
  13. /// Represents a sample that loads a base Model and adds extra Animations from other Models to it.
  14. /// </summary>
  15. public class LoadExtraAnimationsSample : MonoBehaviour
  16. {
  17. /// <summary>
  18. /// Returns the path to the base "BuddyBase.fbx" Model.
  19. /// </summary>
  20. private string BaseModelPath
  21. {
  22. get
  23. {
  24. #if UNITY_EDITOR
  25. return $"{Application.dataPath}/TriLib/TriLibSamples/LoadExtraAnimations/Models/BuddyBase.fbx";
  26. #else
  27. return "Models/BuddyBase.fbx";
  28. #endif
  29. }
  30. }
  31. /// <summary>
  32. /// Button to instantiate when a new Animation is loaded.
  33. /// </summary>
  34. [SerializeField]
  35. private Button _playAnimationTemplate;
  36. /// <summary>
  37. /// The Animation Component from the base Model.
  38. /// </summary>
  39. private Animation _baseAnimation;
  40. /// <summary>
  41. /// Gathers the AssetLoaderContext from the loaded Animations.
  42. /// This list is used to process the Animations if the Animations are loaded before the base Model.
  43. /// </summary>
  44. private readonly IList<AssetLoaderContext> _loadedAnimations = new List<AssetLoaderContext>();
  45. /// <summary>
  46. /// Cached Asset Loader Options instance.
  47. /// </summary>
  48. private AssetLoaderOptions _assetLoaderOptions;
  49. /// <summary>
  50. /// Loads the "Models/BuddyBase.fbx" Model, then loads all the extra Animations in the same folder.
  51. /// </summary>
  52. private void Start()
  53. {
  54. LoadBaseModel();
  55. LoadAnimation("BuddyIdle.fbx");
  56. LoadAnimation("BuddyWalk.fbx");
  57. LoadAnimation("BuddyJump.fbx");
  58. }
  59. /// <summary>
  60. /// Loads the Animations from the given Model.
  61. /// </summary>
  62. /// <param name="modelFilename">The animated Model filename under the same folder as the base Model.</param>
  63. private void LoadAnimation(string modelFilename)
  64. {
  65. var modelsDirectory = FileUtils.GetFileDirectory(BaseModelPath);
  66. var modelPath = FileUtils.SanitizePath($"{modelsDirectory}/{modelFilename}");
  67. if (_assetLoaderOptions == null)
  68. {
  69. _assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(false, true);
  70. _assetLoaderOptions.ImportMeshes = false;
  71. _assetLoaderOptions.ImportTextures = false;
  72. _assetLoaderOptions.ImportMaterials = false;
  73. }
  74. AssetLoader.LoadModelFromFile(modelPath, OnAnimationModelLoad, null, OnProgress, OnError, gameObject, _assetLoaderOptions);
  75. }
  76. /// <summary>
  77. /// Gathers all Animations from the loaded Model and adds them to the base Model Animation Component.
  78. /// </summary>
  79. /// <param name="assetLoaderContext">The context used to load the Model.</param>
  80. private void OnAnimationModelLoad(AssetLoaderContext assetLoaderContext)
  81. {
  82. Debug.Log($"Animation loaded: {FileUtils.GetShortFilename(assetLoaderContext.Filename)}");
  83. if (_baseAnimation != null)
  84. {
  85. AddAnimation(assetLoaderContext);
  86. }
  87. else
  88. {
  89. _loadedAnimations.Add(assetLoaderContext);
  90. }
  91. assetLoaderContext.RootGameObject.SetActive(false);
  92. }
  93. /// <summary>
  94. /// Adds the Animation Clips from the given AssetLoaderContext RootGameObject to the base Model Animations list.
  95. /// </summary>
  96. /// <param name="loadedAnimationContext">The AssetLoaderContext containing the loaded Animation component.</param>
  97. private void AddAnimation(AssetLoaderContext loadedAnimationContext)
  98. {
  99. var rootGameObjectAnimation = loadedAnimationContext.RootGameObject.GetComponent<Animation>();
  100. if (rootGameObjectAnimation != null)
  101. {
  102. var shortFilename = FileUtils.GetShortFilename(loadedAnimationContext.Filename);
  103. var newAnimationClips = rootGameObjectAnimation.GetAllAnimationClips();
  104. foreach (var newAnimationClip in newAnimationClips)
  105. {
  106. var animationName = $"{shortFilename}_{newAnimationClip.name}";
  107. _baseAnimation.AddClip(newAnimationClip, animationName);
  108. var playAnimationButton = Instantiate(_playAnimationTemplate, _playAnimationTemplate.transform.parent);
  109. var playAnimationButtonText = playAnimationButton.GetComponentInChildren<Text>();
  110. playAnimationButtonText.text = shortFilename;
  111. playAnimationButton.gameObject.SetActive(true);
  112. playAnimationButton.onClick.AddListener(delegate
  113. {
  114. _baseAnimation.CrossFade(animationName);
  115. });
  116. }
  117. }
  118. Destroy(loadedAnimationContext.RootGameObject);
  119. }
  120. /// <summary>
  121. /// Loads the Model from BaseModelPath including all Model data.
  122. /// </summary>
  123. private void LoadBaseModel()
  124. {
  125. if (_assetLoaderOptions == null)
  126. {
  127. _assetLoaderOptions = AssetLoader.CreateDefaultLoaderOptions(false, true);
  128. }
  129. AssetLoader.LoadModelFromFile(BaseModelPath, OnBaseModelLoad, OnBaseModelMaterialsLoad, OnProgress, OnError, gameObject, _assetLoaderOptions);
  130. }
  131. /// <summary>
  132. /// Called when any error occurs.
  133. /// </summary>
  134. /// <param name="obj">The contextualized error, containing the original exception and the context passed to the method where the error was thrown.</param>
  135. private void OnError(IContextualizedError obj)
  136. {
  137. Debug.LogError($"An error occurred while loading your Model: {obj.GetInnerException()}");
  138. }
  139. /// <summary>
  140. /// Called when a Model loading progress changes.
  141. /// </summary>
  142. /// <param name="assetLoaderContext">The context used to load the Model.</param>
  143. /// <param name="progress">The loading progress.</param>
  144. private void OnProgress(AssetLoaderContext assetLoaderContext, float progress)
  145. {
  146. }
  147. /// <summary>
  148. /// Called when the Base Model (including Textures and Materials) has been fully loaded.
  149. /// This method processes previously loaded Animations from the loaded Animations list.
  150. /// </summary>
  151. /// <param name="assetLoaderContext">The context used to load the Model.</param>
  152. private void OnBaseModelMaterialsLoad(AssetLoaderContext assetLoaderContext)
  153. {
  154. Debug.Log($"Base Model loaded:{FileUtils.GetShortFilename(assetLoaderContext.Filename)}");
  155. _baseAnimation = assetLoaderContext.RootGameObject.GetComponent<Animation>();
  156. for (var i = _loadedAnimations.Count - 1; i >= 0; i--)
  157. {
  158. AddAnimation(_loadedAnimations[i]);
  159. _loadedAnimations.RemoveAt(i);
  160. }
  161. }
  162. /// <summary>
  163. /// Called when the Base Model Meshes and hierarchy are loaded.
  164. /// </summary>
  165. /// <param name="assetLoaderContext">The context used to load the Model.</param>
  166. private void OnBaseModelLoad(AssetLoaderContext assetLoaderContext)
  167. {
  168. }
  169. }
  170. }