using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; using UnityEngine.SceneManagement; public class Character : MonoBehaviour { public string nextScene; #region Inspector Fields [SerializeField] private Inventory startingInventory; [SerializeField] [Tooltip("Will move to this block at start, else will try and find a block below")] private Block CurrentBlock; [SerializeField] [Tooltip("Layers to ignore when checking for blocks")] private LayerMask Ignore; [Tooltip("Current Inventory of the player")] public Inventory Inventory; #endregion Inspector Fields #region Unity Functions private void Awake() { if (Inventory != null || startingInventory != null) Inventory.Clone(startingInventory); //If no starting block find one below it if (CurrentBlock == null) Block.isBlockAtPosition(transform.position + Vector3.down / 2, 1, ~Ignore, out CurrentBlock); //move to starting block transform.position = CurrentBlock.VisualPosition; } #endregion Unity Functions #region Class Implementation public Vector3 yValue(float time, float heightMultiplier) { float y = Mathf.Sin((Mathf.PI*time)) * heightMultiplier; return new Vector3(0, y, 0); } IEnumerator MoveCoroutine(Block Target, Transform Current, float time, float heightMax) { float elapsedTime = 0; Vector3 startPosition = Current.position; time *= 0.8f; while (elapsedTime < time) { transform.position = Vector3.Lerp(startPosition, Target.VisualPosition, (elapsedTime / time)); transform.position += yValue((elapsedTime / time), heightMax); yield return new WaitForEndOfFrame(); elapsedTime += Time.deltaTime; } transform.position = Target.VisualPosition; } IEnumerator rotateCoroutine(Direction direction, Transform Current, float time, float heightMax) { float elapsedTime = 0; time *= 0.8f; Vector3 endDirection = direction.ToVector(Current); Vector3 startDirection = Current.forward; Vector3 startPosition = transform.position; while (elapsedTime < time) { transform.forward = Vector3.Slerp(startDirection, endDirection, (elapsedTime / time)); transform.position = startPosition +yValue((elapsedTime / time), heightMax); yield return new WaitForEndOfFrame(); elapsedTime += Time.deltaTime; } transform.forward = endDirection; } /// /// Moves one block in specefied direction, Can walk off obstacles /// /// direction to walk /// Technically is same as JumpLong(1) but kept seperate to avoid confusion public void Move(Direction direction, float speed) { //setting up variables Vector3 position = CurrentBlock.position + direction.ToVector(transform); // position wanted Block hit; //output of block detection Block moveTo = CurrentBlock; //block we'll actually move to //if move is obstucted no where to move if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore)) return; //If block at Position is walkable set it to moveTo if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) moveTo = hit; //else if block down one is walkable else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) moveTo = hit; //set current block && move CurrentBlock = moveTo; StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.3f)); //transform.position = CurrentBlock.VisualPosition; } /// /// Upon collision with a floating block, collect its /// Upon collision with the end portal, end of level /// /// name of collided object void OnTriggerEnter(Collider other) { Collectable collectable = other.GetComponentInChildren(); if (collectable != null) { collectable.OnCollect(this); } if (other.gameObject.name == "End Portal") { other.GetComponent().enabled = false; SceneManager.LoadScene(nextScene); } } /// /// Rotates to point in specific direction based on current direction /// /// Local direction to point public void Rotate(Direction direction, float speed) { StartCoroutine(rotateCoroutine(direction, transform, speed, 0.15f)); //transform.forward = direction.ToVector(transform); } /// /// Jumps in specefied direction, picks between Long Jump and Jumping up /// /// Direction to Jump public void Jump(Direction direction, float speed) { //if there is a block infront JumpUp else LongJump if (Block.isBlockAtPosition(CurrentBlock.position + direction.ToVector(transform) + Vector3.up, 1, ~Ignore)) JumpUp(direction, speed); else JumpLong(direction, speed); } #endregion Class Implementation #region Private Functions /// /// Jumps up obstacle of specific height. Jumps as high as possible /// /// Direction of obstacle /// max height private void JumpUp(Direction direction, float speed, int height = 1) { //setting up variables Vector3 position; // position wanted Block hit; //output of block detection Block moveTo = CurrentBlock; //block we'll actually move to //Check blocks in going up then move to the heighest walkable one for (int i = 0; i <= height; i++) { //next position up the tower position = CurrentBlock.position + direction.ToVector(transform) + (Vector3.up * i); //if block is walkable set it to last known position if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) moveTo = hit; } //set current block && move CurrentBlock = moveTo; StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.5f)); //transform.position = CurrentBlock.VisualPosition; } /// /// Long jumps forward a specified distance. Can Jump gaps. Stops at obstruction /// /// Direction to Jump /// Max distance private void JumpLong(Direction direction, float speed, int Distance = 2) { //setting up variables Vector3 position; // position wanted Block hit; //output of block detection Block moveTo = CurrentBlock; //block we'll actually move to //Check blocks in front until we hit an obstruction or went the distance for (int i = 1; i <= Distance; i++) { //Next position to MoveTo position = CurrentBlock.position + (direction.ToVector(transform) * i); //if jump is obstructed, stop and go to last known block if (Block.isBlockAtPosition(position + Vector3.up, 1, ~Ignore)) break; //If block at Position is walkable set it to last known position if (Block.isBlockAtPosition(position, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) moveTo = hit; //else if block down one is walkable else if (Block.isBlockAtPosition(position + Vector3.down, 1, ~Ignore, out hit) && hit.isWalkable(~Ignore)) moveTo = hit; }//end for //Set Current Block and move CurrentBlock = moveTo; StartCoroutine(MoveCoroutine(CurrentBlock, transform, speed, 0.5f)); //transform.position = CurrentBlock.VisualPosition; } #endregion Private Functions }