You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

298 lines
10 KiB

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. using UnityEngine.SceneManagement;
  6. public class Character : MonoBehaviour
  7. {
  8. public string nextScene;
  9. Animator characterAnimator;
  10. #region Inspector Fields
  11. [SerializeField]
  12. [Tooltip("Will move to this block at start, else will try and find a block below")]
  13. private Block _currentBlock;
  14. [SerializeField]
  15. [Tooltip("Layers to ignore when checking for blocks")]
  16. private LayerMask Ignore;
  17. [Tooltip("Current Inventory of the player")]
  18. public Inventory Inventory;
  19. public bool CloneInventoryOnStart = false;
  20. [SerializeField]
  21. [Tooltip("Character to display")]
  22. private string CharacterModel = "Bear";
  23. #endregion Inspector Fields
  24. #region Read Only
  25. public Block CurrentBlock { get { return _currentBlock; } }
  26. #endregion Read Only
  27. #region Unity Functions
  28. private void Start()
  29. {
  30. if (Inventory != null && CloneInventoryOnStart)
  31. Inventory = Inventory.Clone(Inventory);
  32. //If no starting block find one below it
  33. if (_currentBlock == null)
  34. Block.isBlockAtPosition(transform.position + Vector3.down / 2, 1, ~Ignore, out _currentBlock);
  35. //move to starting block
  36. transform.position = _currentBlock.VisualPosition;
  37. //get character string from player replace from "Bear"
  38. GameObject prefab = Resources.Load(CharacterModel) as GameObject;
  39. GameObject animal = Instantiate(prefab, this.gameObject.transform);
  40. characterAnimator = GetComponentInChildren<Animator>();
  41. }
  42. #endregion Unity Functions
  43. #region Class Implementation
  44. public void Initialise(Block startingBlock, Inventory inventory, string Character) {
  45. _currentBlock = startingBlock;
  46. Inventory = inventory;
  47. CharacterModel = Character;
  48. }
  49. public Vector3 yValue(float time, float heightMultiplier)
  50. {
  51. float y = Mathf.Sin((Mathf.PI*time)) * heightMultiplier;
  52. return new Vector3(0, y, 0);
  53. }
  54. IEnumerator JumpCoroutine(Block Target, Transform Current, float time, float heightMax)
  55. {
  56. float elapsedTime = 0;
  57. Vector3 startPosition = Current.position;
  58. time *= 0.8f;
  59. characterAnimator.Play("Jump Inplace");
  60. yield return new WaitForSeconds(0.15f);
  61. while (elapsedTime < time)
  62. {
  63. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  64. transform.position += yValue((elapsedTime / time), heightMax);
  65. yield return new WaitForEndOfFrame();
  66. elapsedTime += Time.deltaTime;
  67. }
  68. transform.position = Target.VisualPosition;
  69. }
  70. IEnumerator MoveCoroutine(Block Target, Transform Current, float time, float heightMax)
  71. {
  72. float elapsedTime = 0;
  73. Vector3 startPosition = Current.position;
  74. time *= 0.8f;
  75. characterAnimator.Play("Walk");
  76. yield return new WaitForSeconds(0.05f);
  77. while (elapsedTime < time)
  78. {
  79. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  80. yield return new WaitForEndOfFrame();
  81. elapsedTime += Time.deltaTime;
  82. }
  83. transform.position = Target.VisualPosition;
  84. }
  85. IEnumerator MoveDownCoroutine(Block Target, Transform Current, float time, float heightMax)
  86. {
  87. float elapsedTime = 0;
  88. Vector3 startPosition = Current.position;
  89. time *= 0.8f;
  90. characterAnimator.Play("Walk");
  91. while (elapsedTime < time)
  92. {
  93. transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time));
  94. transform.position += yValue((elapsedTime / time), heightMax);
  95. yield return new WaitForEndOfFrame();
  96. elapsedTime += Time.deltaTime;
  97. }
  98. transform.position = Target.VisualPosition;
  99. }
  100. IEnumerator rotateCoroutine(Direction direction, Transform Current, float time, float heightMax)
  101. {
  102. float elapsedTime = 0;
  103. time *= 0.8f;
  104. Vector3 endDirection = direction.ToVector(Current);
  105. Vector3 startDirection = Current.forward;
  106. Vector3 startPosition = transform.position;
  107. while (elapsedTime < time)
  108. {
  109. characterAnimator.Play("Jump");
  110. transform.forward = Vector3.Slerp(startDirection, endDirection, (elapsedTime / time));
  111. yield return new WaitForEndOfFrame();
  112. elapsedTime += Time.deltaTime;
  113. }
  114. transform.forward = endDirection;
  115. }
  116. /// <summary>
  117. /// Moves one block in specefied direction, Can walk off obstacles
  118. /// </summary>
  119. /// <param name="direction">direction to walk</param>
  120. /// <remarks>Technically is same as JumpLong(1) but kept seperate to avoid confusion</remarks>
  121. public void Move(Direction direction, float speed)
  122. {
  123. //setting up variables
  124. Vector3 position = _currentBlock.position + direction.ToVector(transform); // position wanted
  125. Block hit; //output of block detection
  126. Block moveTo = _currentBlock; //block we'll actually move to
  127. //if move is obstucted no where to move
  128. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  129. return;
  130. //If block at Position is walkable set it to moveTo
  131. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
  132. moveTo = hit;
  133. _currentBlock = moveTo;
  134. StartCoroutine(MoveCoroutine(_currentBlock, transform, speed, 0.3f)); }
  135. //else if block down one is walkable
  136. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)){
  137. moveTo = hit;
  138. _currentBlock = moveTo;
  139. StartCoroutine(MoveDownCoroutine(_currentBlock, transform, speed, 0.3f));
  140. }
  141. //set current block && move
  142. //CurrentBlock = moveTo;
  143. //StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.3f));
  144. //transform.position = CurrentBlock.VisualPosition;
  145. }
  146. /// <summary>
  147. /// Upon collision with a floating block, collect its
  148. /// Upon collision with the end portal, end of level
  149. /// </summary>
  150. /// <param name="other">name of collided object</param>
  151. void OnTriggerEnter(Collider other)
  152. {
  153. Collectable collectable = other.GetComponentInChildren<Collectable>();
  154. if (collectable != null)
  155. {
  156. collectable.OnCollect(this);
  157. }
  158. if (other.gameObject.name == "collect_sphere"){
  159. other.gameObject.SetActive(false);
  160. //player.collected +=1;
  161. }
  162. if (other.gameObject.name == "End Portal")
  163. {
  164. other.GetComponent<Collider>().enabled = false;
  165. SceneManager.LoadScene(nextScene);
  166. }
  167. }
  168. /// <summary>
  169. /// Rotates to point in specific direction based on current direction
  170. /// </summary>
  171. /// <param name="direction">Local direction to point</param>
  172. public void Rotate(Direction direction, float speed)
  173. {
  174. StartCoroutine(rotateCoroutine(direction, transform, speed, 0.15f));
  175. //transform.forward = direction.ToVector(transform);
  176. }
  177. /// <summary>
  178. /// Jumps in specefied direction, picks between Long Jump and Jumping up
  179. /// </summary>
  180. /// <param name="direction">Direction to Jump</param>
  181. public void Jump(Direction direction, float speed)
  182. {
  183. //if there is a block infront JumpUp else LongJump
  184. if (Block.isBlockAtPosition(_currentBlock.position + direction.ToVector(transform) + Vector3.up, 1, ~Ignore))
  185. JumpUp(direction, speed);
  186. else
  187. JumpLong(direction, speed);
  188. }
  189. #endregion Class Implementation
  190. #region Private Functions
  191. /// <summary>
  192. /// Jumps up obstacle of specific height. Jumps as high as possible
  193. /// </summary>
  194. /// <param name="direction">Direction of obstacle</param>
  195. /// <param name="height">max height</param>
  196. private void JumpUp(Direction direction, float speed, int height = 1)
  197. {
  198. //setting up variables
  199. Vector3 position; // position wanted
  200. Block hit; //output of block detection
  201. Block moveTo = _currentBlock; //block we'll actually move to
  202. //Check blocks in going up then move to the heighest walkable one
  203. for (int i = 0; i <= height; i++)
  204. {
  205. //next position up the tower
  206. position = _currentBlock.position + direction.ToVector(transform) + (Vector3.up * i);
  207. //if block is walkable set it to last known position
  208. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  209. moveTo = hit;
  210. }
  211. //set current block && move
  212. _currentBlock = moveTo;
  213. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  214. //transform.position = CurrentBlock.VisualPosition;
  215. }
  216. /// <summary>
  217. /// Long jumps forward a specified distance. Can Jump gaps. Stops at obstruction
  218. /// </summary>
  219. /// <param name="direction">Direction to Jump</param>
  220. /// <param name="Distance">Max distance</param>
  221. private void JumpLong(Direction direction, float speed, int Distance = 2)
  222. {
  223. //setting up variables
  224. Vector3 position; // position wanted
  225. Block hit; //output of block detection
  226. Block moveTo = _currentBlock; //block we'll actually move to
  227. //Check blocks in front until we hit an obstruction or went the distance
  228. for (int i = 1; i <= Distance; i++)
  229. {
  230. //Next position to MoveTo
  231. position = _currentBlock.position + (direction.ToVector(transform) * i);
  232. //if jump is obstructed, stop and go to last known block
  233. if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore))
  234. break;
  235. //If block at Position is walkable set it to last known position
  236. if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  237. moveTo = hit;
  238. //else if block down one is walkable
  239. else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore))
  240. moveTo = hit;
  241. }//end for
  242. //Set Current Block and move
  243. _currentBlock = moveTo;
  244. StartCoroutine(JumpCoroutine(_currentBlock, transform, speed, 0.5f));
  245. //transform.position = CurrentBlock.VisualPosition;
  246. }
  247. #endregion Private Functions
  248. }