Hi, I’m a bit of a newbie to Unity (and to making games), but I’m trying to build a retro-style 2D platform game along the lines of Super Mario Bros. I’m using 2D raycasting rather than physics to achieve that classic feel, but I’m having a problem where my player character is intersecting the floors and walls that I’ve set up. They stop his movement, but he sits a little inside them.
I’m using 16-bit-style pixel graphics, so I’m trying to keep the positions of all assets integers rather than floats.
I’m not sure what I’m doing wrong so I’m including my whole character controller code. I’d really appreciate any help from anyone.
Thanks very much!
using UnityEngine;
using System.Collections;
public class PlayerController : MonoBehaviour {
public int positionX, positionY;
public int speed;
public LayerMask playerLayerMask;
private float moveHorizontal, moveVertical;
private Animator animator;
private RaycastHit2D hitFront1, hitRear1, hitBottom1, hitTop1;
private int distXToMove, distYToMove;
private bool jump;
private int jumpCount;
private bool jumping;
private int fallAccel;
private int fallAccelMax;
void Start()
{
animator = this.GetComponent<Animator> ();
jumping = false;
fallAccelMax = 10;
fallAccel = 0;
jumpCount = 15;
}
void Update ()
{
GetPosition (); // Get player position.
GetPlayerInput (); // Get input from the player.
PerformPhysics ();
AnimateSprite (); // Choose correct animation.
CollisionDetection (); // Detect collisions with objects.
TranslatePlayer (); // Move the player.
}
void GetPosition()
{
positionX = (int)transform.position.x; // Store initial position.
positionY = (int)transform.position.y; //
}
void GetPlayerInput ()
{
moveHorizontal = (int)Input.GetAxis ("Horizontal"); // Get direction.
distXToMove = (int)(moveHorizontal * speed);
if (!jumping)
{
jump = Input.GetKeyDown ("joystick button 1");
if (jump)
jumping = true;
}
}
void PerformPhysics()
{
if (!hitBottom1 && fallAccel < fallAccelMax && !jumping)
fallAccel++;
else if (hitBottom1)
fallAccel = 0;
distYToMove = (int)(-fallAccel);
if (jumping)
{
if (jumpCount > 0)
{
distYToMove = jumpCount;
jumpCount--;
}
else
{
jumpCount = 15;
jumping = false;
}
}
}
void AnimateSprite()
{
if (moveHorizontal != 0)
{
// Play run animation if moving horizontally.
animator.SetInteger ("PixelMeState", 1);
// Reflect player in X if moving left.
if (moveHorizontal < 0)
transform.localScale = new Vector2(-1, 1);
else if (moveHorizontal > 0)
transform.localScale = new Vector2(1, 1);
}
// Play idle animation by default.
else
animator.SetInteger ("PixelMeState", 0);
}
void CollisionDetection()
{
// Check for collision from RHS of character.
hitFront1 = Physics2D.Raycast(transform.position + new Vector3 (5, 12, 0),
new Vector3 (distXToMove, 0, 0), distXToMove, playerLayerMask);
// Draw line to show ray from RHS of character.
Debug.DrawRay (transform.position + new Vector3 (5, 12, 0),
new Vector3 (distXToMove, 0, 0), Color.green);
// Check for collision from LHS of character.
hitRear1 = Physics2D.Raycast(transform.position + new Vector3 (-6, 12, 0),
new Vector3 (distXToMove, 0, 0), distXToMove, playerLayerMask);
// Draw line to show ray from LHS of character.
Debug.DrawRay (transform.position + new Vector3 (-6, 12, 0),
new Vector3 (distXToMove, 0, 0), Color.red);
// Check for collision from bottom of character.
hitBottom1 = Physics2D.Raycast(transform.position, new Vector3 (0, distYToMove, 0),
distYToMove, playerLayerMask);
// Draw line to show ray from bottom of character.
Debug.DrawRay (transform.position, new Vector3 (0, distYToMove, 0), Color.grey);
// Check for collision from top of character.
hitTop1 = Physics2D.Raycast(transform.position + new Vector3 (0, 24, 0),
new Vector3 (0, distYToMove, 0), distYToMove, playerLayerMask);
// Draw line to show ray from top of character.
Debug.DrawRay (transform.position + new Vector3 (0, 24, 0),
new Vector3 (0, distYToMove, 0), Color.cyan);
}
void TranslatePlayer()
{
// If wall will be reached this frame, and the player isn't already there,
// move the remaining distance to the wall.
if (hitFront1 && hitFront1.collider.tag == "Wall" && distXToMove > 0)
distXToMove = (int)hitFront1.distance;
// If wall will be reached this frame, and the player isn't already there,
// move the remaining distance to the wall.
if (hitRear1 && hitRear1.collider.tag == "Wall" && distXToMove < 0)
distXToMove = (int)hitRear1.distance;
// If platform will be reached this frame, and the player isn't already there,
// move the remaining distance to the platform.
if (hitBottom1 && hitBottom1.collider.tag == "Platform" && distYToMove < 0)
distYToMove = (int)hitBottom1.distance;
// If platform will be reached this frame, and the player isn't already there,
// move the remaining distance to the platform.
if (hitTop1 && hitTop1.collider.tag == "Ceiling" && distYToMove > 0)
distYToMove = (int)hitTop1.distance;
positionX += distXToMove; // Increment position
positionY += distYToMove; //
// Set new player position.
transform.position = new Vector2 (positionX, positionY);
}