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.

168 lines
5.4 KiB

  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using System.Linq;
  5. /// <summary>
  6. /// Class which defines blocks around the level
  7. /// </summary>
  8. [RequireComponent(typeof(BoxCollider))]
  9. public class Block : MonoBehaviour
  10. {
  11. #region Inspector Fields
  12. [SerializeField]
  13. [Tooltip("Offset from the top of the block from which a character should stand")]
  14. private Vector3 VisualOffset = Vector3.zero;
  15. [SerializeField]
  16. [Tooltip("Can this type of block be walked on")]
  17. public bool is_Walkable = true;
  18. [Tooltip("Can this block be spawned on")]
  19. public bool isSpawnable = false;
  20. [Tooltip("Direction Player is poting at when spawned")]
  21. public Direction SpawnDirection = Direction.Forward;
  22. #endregion InspectorFields
  23. #region ReadOnly Properties
  24. /// <summary>
  25. /// Blocks position in global space
  26. /// </summary>
  27. public Vector3 position { get { return transform.position; } }
  28. /// <summary>
  29. /// Position character should stand in global space
  30. /// </summary>
  31. public Vector3 VisualPosition { get { return position + VisualOffset + Vector3.up * 0.5f; } }
  32. #endregion ReadOnly Properties
  33. #region Public Functions
  34. /// <summary>
  35. /// Is a block valid to walk on
  36. /// </summary>
  37. /// <param name="layerMask">Layers to check for when checking for blocks above</param>
  38. /// <returns></returns>
  39. public bool isWalkable(LayerMask layerMask)
  40. {
  41. //checks if there is no block above this one and that this is tagged as walkable
  42. return (is_Walkable && !isBlockAtPosition(position + Vector3.up, 1, layerMask));
  43. }
  44. /// <summary>
  45. /// Is called after all players have taken one move
  46. ///
  47. /// Should be implemented by a derived class
  48. /// </summary>
  49. public virtual void OnPlayersMoved()
  50. {
  51. }
  52. /// <summary>
  53. /// Is called when a player moves onto this block
  54. ///
  55. /// Should be implemented by a derived class
  56. /// </summary>
  57. /// <param name="player">Player which moved on to block</param>
  58. public virtual void OnWalkedOnByPlayer(PlayerData player)
  59. {
  60. }
  61. /// <summary>
  62. /// Called after all players have finished all their moves
  63. ///
  64. /// Should be implemented by a derived class
  65. /// </summary>
  66. public virtual void OnRoundEnd()
  67. {
  68. }
  69. #endregion Public Functions
  70. #region Editor Functions
  71. private void OnDrawGizmos()
  72. {
  73. if (!isSpawnable)
  74. return;
  75. Vector3 DrawPosition = VisualPosition + Vector3.up * 0.4f;
  76. Vector3 Perp = Quaternion.Euler(0, 90, 0) * SpawnDirection.ToVector();
  77. DebugExtensions.DrawCube(DrawPosition, 0.4f, Color.magenta, 0);
  78. //Eyes
  79. Vector3 eyePosition = DrawPosition + SpawnDirection.ToVector() * 0.4f;
  80. DebugExtensions.DrawCube(eyePosition + Perp * 0.2f, 0.1f, Color.magenta, 0);
  81. DebugExtensions.DrawCube(eyePosition - Perp * 0.2f, 0.1f, Color.magenta, 0);
  82. //ears
  83. Vector3 earPosition = DrawPosition + SpawnDirection.ToVector() * 0.2f + Vector3.up * 0.4f;
  84. Vector3 earScale = Quaternion.LookRotation(SpawnDirection.ToVector()) * new Vector3(0.1f, 0.1f, 0.05f);
  85. DebugExtensions.DrawCube(earPosition + Perp * 0.3f, earScale, Color.magenta, 0);
  86. DebugExtensions.DrawCube(earPosition - Perp * 0.3f, earScale, Color.magenta, 0);
  87. }
  88. #endregion Editor Functions
  89. #region Static Functions
  90. /// <summary>
  91. /// Checks if there is a block at supplied position
  92. /// </summary>
  93. /// <param name="position">position to check at</param>
  94. /// <param name="Scale">Scale of block. (should be 1)</param>
  95. /// <param name="layerMask">Layers to check on</param>
  96. /// <param name="hit">Block hit</param>
  97. /// <returns>if a block is at position</returns>
  98. public static bool isBlockAtPosition(Vector3 position, float Scale, LayerMask layerMask, out Block hit)
  99. {
  100. //Turn scale into halfextent and shrink a bit so it doesn't hit bordering blocks
  101. Vector3 halfExtent = Vector3.one * ((Scale - 0.1f) / 2);
  102. //Get every collider which is at position
  103. Collider[] cols = Physics.OverlapBox(position, halfExtent, Quaternion.identity, layerMask);
  104. //Filter colliders for only GameObjects with an Block component
  105. Block[] blocks = cols.Where(p => p.GetComponent<Block>() != null).Select(p => p.GetComponent<Block>()).ToArray();
  106. //Draw cube, for visuals
  107. //DebugExtensions.DrawCube(position, halfExtent, Color.cyan, 1, false);
  108. //if didn't hit anyblocks return false
  109. if (blocks.Length == 0)
  110. {
  111. hit = null;
  112. return false;
  113. }
  114. else
  115. {
  116. //else get the closest block to disered position, (in case we hit mulitple blocks)
  117. hit = Utility.minBy(blocks, p => Vector3.Distance(p.transform.position, position));
  118. return true;
  119. }
  120. }
  121. /// <summary>
  122. /// Checks if there is a block at supplied position
  123. /// </summary>
  124. /// <param name="position">position to check at</param>
  125. /// <param name="Scale">Scale of block. (should be 1)</param>
  126. /// <param name="layerMask">Layers to check on</param>
  127. /// <returns>if a block is at position</returns>
  128. public static bool isBlockAtPosition(Vector3 position, float scale, LayerMask layerMask)
  129. {
  130. //Return Overloaded function above
  131. Block hit;
  132. return (isBlockAtPosition(position, scale, layerMask, out hit));
  133. }
  134. #endregion
  135. }