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.
 
 
 
 

133 lines
4.7 KiB

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
/// <summary>
/// Class which defines blocks around the level
/// </summary>
[RequireComponent(typeof(BoxCollider))]
public class Block : MonoBehaviour
{
#region Inspector Fields
[SerializeField]
[Tooltip("Offset from the top of the block from which a character should stand")]
private Vector3 VisualOffset = Vector3.zero;
[SerializeField]
[Tooltip("Can this type of block be walked on")]
private bool _isWalkable = true;
[Tooltip("Can this block be spawned on")]
public bool isSpawnable = false;
[Tooltip("Direction Player is poting at when spawned")]
public Direction SpawnDirection = Direction.Forward;
#endregion InspectorFields
#region ReadOnly Properties
/// <summary>
/// Blocks position in global space
/// </summary>
public Vector3 position { get { return transform.position; } }
/// <summary>
/// Position character should stand in global space
/// </summary>
public Vector3 VisualPosition { get { return position + VisualOffset + Vector3.up * 0.5f; } }
#endregion ReadOnly Properties
#region Public Functions
/// <summary>
/// Is a block valid to walk on
/// </summary>
/// <param name="layerMask">Layers to check for when checking for blocks above</param>
/// <returns></returns>
public bool isWalkable(LayerMask layerMask)
{
//checks if there is no block above this one and that this is tagged as walkable
return (_isWalkable && !isBlockAtPosition(position + Vector3.up, 1, layerMask));
}
#endregion Public Functions
private void OnDrawGizmos()
{
if (!isSpawnable)
return;
Vector3 DrawPosition = VisualPosition + Vector3.up * 0.4f;
Vector3 Perp = Quaternion.Euler(0, 90, 0) * SpawnDirection.ToVector();
DebugExtensions.DrawCube(DrawPosition, 0.4f, Color.magenta, 0);
//Eyes
Vector3 eyePosition = DrawPosition + SpawnDirection.ToVector() * 0.4f;
DebugExtensions.DrawCube(eyePosition + Perp * 0.2f, 0.1f, Color.magenta, 0);
DebugExtensions.DrawCube(eyePosition - Perp * 0.2f, 0.1f, Color.magenta, 0);
//ears
Vector3 earPosition = DrawPosition + SpawnDirection.ToVector() * 0.2f + Vector3.up * 0.4f;
Vector3 earScale = Quaternion.LookRotation(SpawnDirection.ToVector()) * new Vector3(0.1f, 0.1f, 0.05f);
DebugExtensions.DrawCube(earPosition + Perp * 0.3f, earScale, Color.magenta, 0);
DebugExtensions.DrawCube(earPosition - Perp * 0.3f, earScale, Color.magenta, 0);
}
#region Static Functions
/// <summary>
/// Checks if there is a block at supplied position
/// </summary>
/// <param name="position">position to check at</param>
/// <param name="Scale">Scale of block. (should be 1)</param>
/// <param name="layerMask">Layers to check on</param>
/// <param name="hit">Block hit</param>
/// <returns>if a block is at position</returns>
public static bool isBlockAtPosition(Vector3 position, float Scale, LayerMask layerMask, out Block hit)
{
//Turn scale into halfextent and shrink a bit so it doesn't hit bordering blocks
Vector3 halfExtent = Vector3.one * ((Scale - 0.1f) / 2);
//Get every collider which is at position
Collider[] cols = Physics.OverlapBox(position, halfExtent, Quaternion.identity, layerMask);
//Filter colliders for only GameObjects with an Block component
Block[] blocks = cols.Where(p => p.GetComponent<Block>() != null).Select(p => p.GetComponent<Block>()).ToArray();
//Draw cube, for visuals
//DebugExtensions.DrawCube(position, halfExtent, Color.cyan, 1, false);
//if didn't hit anyblocks return false
if (blocks.Length == 0)
{
hit = null;
return false;
}
else
{
//else get the closest block to disered position, (in case we hit mulitple blocks)
hit = Utility.minBy(blocks, p => Vector3.Distance(p.transform.position, position));
return true;
}
}
/// <summary>
/// Checks if there is a block at supplied position
/// </summary>
/// <param name="position">position to check at</param>
/// <param name="Scale">Scale of block. (should be 1)</param>
/// <param name="layerMask">Layers to check on</param>
/// <returns>if a block is at position</returns>
public static bool isBlockAtPosition(Vector3 position, float scale, LayerMask layerMask)
{
//Return Overloaded function above
Block hit;
return (isBlockAtPosition(position, scale, layerMask, out hit));
}
#endregion
}