Question by
FinalShroom · Jun 12, 2018 at 06:46 PM ·
movementtransformscript.movement scripttransform.rotation
RogueLike 2D (Tutorial) Rotation of Player
Hi,
I am looking to improve upon the Roguelike2D tutorial. I want the player and enemies rotate to the direction they are facing before moving. If possible specifically for this tutorial as it uses 1 script for both the player and enemy movement (which most examples I've looked at don't).
Here is the code...
using UnityEngine;
using System.Collections;
namespace Completed
{
//The abstract keyword enables you to create classes and class members that are incomplete and must be implemented in a derived class.
public abstract class MovingObject : MonoBehaviour
{
public float moveTime = 0.1f; //Time it will take object to move, in seconds.
public LayerMask blockingLayer; //Layer on which collision will be checked.
private BoxCollider2D boxCollider; //The BoxCollider2D component attached to this object.
private Rigidbody2D rb2D; //The Rigidbody2D component attached to this object.
private float inverseMoveTime; //Used to make movement more efficient.
//Protected, virtual functions can be overridden by inheriting classes.
protected virtual void Start ()
{
//Get a component reference to this object's BoxCollider2D
boxCollider = GetComponent <BoxCollider2D> ();
//Get a component reference to this object's Rigidbody2D
rb2D = GetComponent <Rigidbody2D> ();
//By storing the reciprocal of the move time we can use it by multiplying instead of dividing, this is more efficient.
inverseMoveTime = 1f / moveTime;
}
//Move returns true if it is able to move and false if not.
//Move takes parameters for x direction, y direction and a RaycastHit2D to check collision.
protected bool Move (int xDir, int yDir, out RaycastHit2D hit)
{
//Store start position to move from, based on objects current transform position.
Vector2 start = transform.position;
// Calculate end position based on the direction parameters passed in when calling Move.
Vector2 end = start + new Vector2 (xDir, yDir);
//Disable the boxCollider so that linecast doesn't hit this object's own collider.
boxCollider.enabled = false;
//Cast a line from start point to end point checking collision on blockingLayer.
hit = Physics2D.Linecast (start, end, blockingLayer);
//Re-enable boxCollider after linecast
boxCollider.enabled = true;
//Check if anything was hit
if(hit.transform == null)
{
//If nothing was hit, start SmoothMovement co-routine passing in the Vector2 end as destination
StartCoroutine (SmoothMovement (end));
//Return true to say that Move was successful
return true;
}
//If something was hit, return false, Move was unsuccesful.
return false;
}
//Co-routine for moving units from one space to next, takes a parameter end to specify where to move to.
protected IEnumerator SmoothMovement (Vector3 end)
{
//Calculate the remaining distance to move based on the square magnitude of the difference between current position and end parameter.
//Square magnitude is used instead of magnitude because it's computationally cheaper.
float sqrRemainingDistance = (transform.position - end).sqrMagnitude;
//While that distance is greater than a very small amount (Epsilon, almost zero):
while(sqrRemainingDistance > float.Epsilon)
{
//Find a new position proportionally closer to the end, based on the moveTime
Vector3 newPostion = Vector3.MoveTowards(rb2D.position, end, inverseMoveTime * Time.deltaTime);
//Call MovePosition on attached Rigidbody2D and move it to the calculated position.
rb2D.MovePosition (newPostion);
//Recalculate the remaining distance after moving.
sqrRemainingDistance = (transform.position - end).sqrMagnitude;
//Return and loop until sqrRemainingDistance is close enough to zero to end the function
yield return null;
}
}
//The virtual keyword means AttemptMove can be overridden by inheriting classes using the override keyword.
//AttemptMove takes a generic parameter T to specify the type of component we expect our unit to interact with if blocked (Player for Enemies, Wall for Player).
protected virtual void AttemptMove <T> (int xDir, int yDir)
where T : Component
{
//Hit will store whatever our linecast hits when Move is called.
RaycastHit2D hit;
//Set canMove to true if Move was successful, false if failed.
bool canMove = Move (xDir, yDir, out hit);
//Check if nothing was hit by linecast
if(hit.transform == null)
//If nothing was hit, return and don't execute further code.
return;
//Get a component reference to the component of type T attached to the object that was hit
T hitComponent = hit.transform.GetComponent <T> ();
//If canMove is false and hitComponent is not equal to null, meaning MovingObject is blocked and has hit something it can interact with.
if(!canMove && hitComponent != null)
//Call the OnCantMove function and pass it hitComponent as a parameter.
OnCantMove (hitComponent);
}
//The abstract modifier indicates that the thing being modified has a missing or incomplete implementation.
//OnCantMove will be overriden by functions in the inheriting classes.
protected abstract void OnCantMove <T> (T component)
where T : Component;
}
}
Thanks in advance for any help provided.
Comment
Answer by FinalShroom · Jun 13, 2018 at 02:26 PM
Fixed. Added new script called Rotation here is the code if anyone needs.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Rotation : MonoBehaviour {
Direction currentDir;
Vector2 input;
bool isMoving = false;
Vector3 startPos;
Vector3 endPos;
float t;
public Sprite northSprite;
public Sprite eastSprite;
public Sprite southSprite;
public Sprite westSprite;
public float walkSpeed;
public bool isAllowedToMove = true;
void Start()
{
isAllowedToMove = true;
}
void Update () {
if(!isMoving && isAllowedToMove)
{
input = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"));
if (Mathf.Abs(input.x) > Mathf.Abs(input.y))
input.y = 0;
else
input.x = 0;
if(input != Vector2.zero)
{
if(input.x < 0)
{
currentDir = Direction.West;
}
if(input.x > 0)
{
currentDir = Direction.East;
}
if(input.y < 0)
{
currentDir = Direction.South;
}
if (input.y > 0)
{
currentDir = Direction.North;
}
switch(currentDir)
{
case Direction.North:
gameObject.GetComponent<SpriteRenderer>().sprite = northSprite;
break;
case Direction.East:
gameObject.GetComponent<SpriteRenderer>().sprite = eastSprite;
break;
case Direction.South:
gameObject.GetComponent<SpriteRenderer>().sprite = southSprite;
break;
case Direction.West:
gameObject.GetComponent<SpriteRenderer>().sprite = westSprite;
break;
}
}
}
}
}
enum Dir
{
North,
East,
South,
West
}