Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

unity 4.5.1 2D player file faulty gravity …(really aggrivating)

Discussion in 'Scripting' started by d3thdrug, Jul 1, 2014.

  1. d3thdrug

    d3thdrug

    Joined:
    Feb 23, 2014
    Posts:
    3
    I really hope you guys can help me with my problem, this was my last resort and im super frustrated.

    I'm creating a 2D Side-Scroller game and while coding the player file, I've ran into a very annoying thing that I don't know where the problem is. Everything else in the player is fine, what happens is that if the player is walking on a slant, and then comes off; the gravity (I'm assuming) is being messed with and when your in the air he just floats down instead of falling; also if you jump (after walking on the slant) he just does a teeeeeeny tiny hop. I have debugged the whole file several times and can't seem to figure it out.

    If someone would please help, I'll put the whole player file. If you have a 2D sidescroller game in unity, you can just put this file on a gameobject with a rigidBody2D and isKinemic is true..


    using UnityEngine;
    using System.Collections;
    using System;

    public class PlayerControl : MonoBehaviour {

    private Animator anim;
    public static PlayerControl instance;
    public static bool isShooting;
    [HideInInspector]
    public bool facingRight;
    private float normalSpeed;

    private static readonly float slopeLimitTangent = Mathf.Tan(75f * Mathf.Deg2Rad);

    public float maxSpeed = 8f;
    private float speedAccelerationOnGround = 10f;
    private float speedAccelerationInAir = 5f;
    private Vector2 velocity {get {return vel;}}

    public int health = 100;
    private bool isDead;

    private const float skinWidth = .02f;
    private const int horizRays = 8;
    private const int vertRays = 4;

    public enum JumpBehavior {

    JumpOnGround,
    JumpAnywhere,
    CantJump
    };
    public JumpBehavior jumpWhere;
    private float jumpIn;
    public float jumpFreq = 0.25f;
    public float jumpMag = 16;
    public LayerMask whatIsGround;
    private bool grounded { get { return colBelow; } }
    private bool cooldown;
    public GameObject standingOn {get; private set;}
    public Vector3 platformVelocity {get;private set;}
    public bool canJump { get {
    if (jumpWhere == JumpBehavior.JumpAnywhere)
    return jumpIn <= 0;
    if (jumpWhere == JumpBehavior.JumpOnGround)
    return grounded;

    return false;
    }
    }


    public bool colRight { get; set;}
    public bool colLeft { get; set;}
    public bool colAbove{ get; set;}
    public bool colBelow{ get; set;}
    public bool upSlope{ get; set;}
    public bool downSlope{get;set;}
    public float slopeAngle {get;set;}
    public bool hasCollisions { get { return colRight || colLeft || colAbove || colBelow; }
    }

    private float
    vertDistanceBetweenRays,
    horizDistanceBetweenRays;
    private Vector3 raycastTopLeft;
    private Vector3 raycastBottomRight;
    private Vector3 raycastBottomLeft;

    private Vector2 maxVelocity = new Vector2(float.MaxValue,
    float.MaxValue);
    private Vector2 vel;

    [Range(0, 90)]
    public float slopeLimit = 30;
    public float gravity = -15;

    private GameObject lastStandingOn;
    private Vector3 activeGlobalPlatformPoint;
    private Vector3 activeLocalPlatformPoint;

    public static int scene = 0;

    void Start () {

    instance = this;
    anim = GetComponent<Animator> ();

    float colliderWidth = GetComponent<BoxCollider2D>().size.x * Mathf.Abs
    (transform.localScale.x) - (2 * skinWidth);
    horizDistanceBetweenRays = colliderWidth / (vertRays - 1);

    float colliderHeight = GetComponent<BoxCollider2D>().size.y * Mathf.Abs
    (transform.localScale.y) - (2 * skinWidth);
    vertDistanceBetweenRays = colliderHeight / (horizRays - 1);
    }


    void Update () {

    if (!isDead)
    HandleInput();

    float movementFactor = grounded ? speedAccelerationOnGround : speedAccelerationInAir;

    if (isDead)
    HorizForce(0);
    else
    HorizForce(Mathf.Lerp(velocity.x, normalSpeed * maxSpeed, Time.deltaTime * movementFactor));


    anim.SetBool("Grounded", grounded);
    anim.SetBool("Dead", isDead);
    anim.SetFloat("Speed", Mathf.Abs(velocity.x) / maxSpeed);


    }

    public void LateUpdate() {
    jumpIn -= Time.deltaTime;

    vel.y += gravity * Time.deltaTime;
    Move (vel * Time.deltaTime);
    }

    public void AddForce(Vector2 force) {
    vel += force;
    }

    public void SetForce(Vector2 force) {
    vel = force;
    }

    public void HorizForce(float x) {
    vel.x = x;
    }

    public void VertForce(float y) {
    vel.y = y;
    }

    public void Jump() {
    AddForce(new Vector2(0, jumpMag));
    jumpIn = jumpFreq;
    anim.SetTrigger("Jump");
    }

    void HandleInput() {

    float h = Input.GetAxis("Horizontal");
    normalSpeed = h;

    if (h < 0) {

    if (!facingRight)
    Flip ();
    facingRight = true;
    } else

    if (h > 0) {
    if (facingRight)
    Flip ();
    facingRight = false;
    } else
    normalSpeed = 0;

    if (canJump && Input.GetButtonDown("Jump"))
    Jump();


    if (Input.GetButton("melee") && !Input.GetButtonDown ("Fire1") && MeleeAttack.canHit) {
    anim.SetTrigger ("Attack");
    MeleeAttack.canHit = false;

    MeleeAttack.instance.cooldown ();
    }
    }

    private void Flip() {
    transform.localScale = new Vector3(-transform.localScale.x, transform.localScale.y, transform.localScale.z);
    facingRight = transform.localScale.x > 0;
    }

    void ResetColliders() {

    colLeft = false;
    colRight = false;
    colAbove = false;
    colBelow = false;
    colLeft = false;

    slopeAngle = 0;

    }

    void Move(Vector2 deltaMove) {
    bool wasGrounded = colBelow;
    ResetColliders();

    HandlePlatforms ();
    CalcRayOrigins();

    if (deltaMove.y < 0 && wasGrounded)
    HandleVerticalSlope(ref deltaMove);

    if (Mathf.Abs(deltaMove.x) > 0.001f)
    MoveHoriz(ref deltaMove);

    MoveVert(ref deltaMove);
    //CorrectHorizPlacement(ref deltaMove, true);
    //CorrectHorizPlacement(ref deltaMove, false);

    transform.Translate(deltaMove, Space.World);

    if (Time.deltaTime > 0)
    vel = deltaMove / Time.deltaTime;

    vel.x = Mathf.Min(vel.x, maxVelocity.x);
    vel.y = Mathf.Min(vel.y, maxVelocity.y);

    if (upSlope)
    vel.y = 0;

    if (standingOn != null) {
    activeGlobalPlatformPoint = transform.position;
    activeLocalPlatformPoint = standingOn.transform.InverseTransformPoint(transform.position);

    if (lastStandingOn != standingOn) {
    if (lastStandingOn != null)
    lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);

    standingOn.SendMessage("ControllerEnter2D", this, SendMessageOptions.DontRequireReceiver);
    lastStandingOn = standingOn;
    } else if (standingOn != null)
    standingOn.SendMessage("ControllerStay2D", this, SendMessageOptions.DontRequireReceiver);
    else if (lastStandingOn != null) {
    lastStandingOn.SendMessage("ControllerExit2D", this, SendMessageOptions.DontRequireReceiver);
    lastStandingOn = null;
    }
    }


    }

    void MoveHoriz(ref Vector2 deltaMove) {
    bool goingRight = deltaMove.x > 0;
    float rayDistance = Mathf.Abs (deltaMove.x) + skinWidth;
    Vector2 rayDirection = goingRight ? Vector2.right : -Vector2.right;
    Vector3 rayOrigin = goingRight ? raycastBottomRight : raycastBottomLeft;

    for (int i = 0; i < horizRays; i++) {
    Vector2 rayVect = new Vector2(rayOrigin.x, rayOrigin.y + (i * vertDistanceBetweenRays));
    Debug.DrawRay(rayVect, rayDirection * rayDistance, Color.red);

    RaycastHit2D raycastHit = Physics2D.Raycast(rayVect, rayDirection, rayDistance, whatIsGround);

    if (!raycastHit) continue;

    if (i == 0 && HandleHorizontalSlope(ref deltaMove, Vector2.Angle(raycastHit.normal, Vector2.up), goingRight))
    break;

    deltaMove.x = raycastHit.point.x - rayVect.x;
    rayDistance = Mathf.Abs (deltaMove.x);

    if (goingRight) {
    deltaMove.x -= skinWidth;
    colRight = true;
    } else {
    deltaMove.x += skinWidth;
    colLeft = true;
    }

    if (rayDistance < skinWidth + .0001f)
    break;


    }
    }

    private void HandlePlatforms() {
    if (standingOn != null) {
    Vector3 newGlobalPlatformPoint = standingOn.transform.TransformPoint(activeLocalPlatformPoint);
    Vector3 moveDistance = newGlobalPlatformPoint - activeGlobalPlatformPoint;

    if (moveDistance != Vector3.zero)
    transform.Translate(moveDistance, Space.World);

    platformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
    } else
    platformVelocity = Vector3.zero;

    standingOn = null;
    }

    private void MoveVert(ref Vector2 deltaMovement) {
    bool isGoingUp = deltaMovement.y > 0;
    float rayDistance = Mathf.Abs(deltaMovement.y) + skinWidth;
    Vector2 rayDirection = isGoingUp ? Vector2.up : -Vector2.up;
    Vector2 rayOrigin = isGoingUp ? raycastTopLeft : raycastBottomLeft;

    rayOrigin.x += deltaMovement.x;

    float standingOnDistance = float.MaxValue;
    for (int i = 0; i < vertRays; i++) {
    Vector2 rayVector = new Vector2(rayOrigin.x + (i * horizDistanceBetweenRays), rayOrigin.y);
    Debug.DrawRay(rayVector, rayDirection * rayDistance, Color.red);

    RaycastHit2D rayCastHit = Physics2D.Raycast(rayVector, rayDirection, rayDistance, whatIsGround);

    if (!rayCastHit)
    continue;

    if (!isGoingUp) {
    float verticalDistanceToHit = transform.position.y - rayCastHit.point.y;
    if (verticalDistanceToHit < standingOnDistance) {
    standingOnDistance = verticalDistanceToHit;
    standingOn = rayCastHit.collider.gameObject;
    }
    }

    deltaMovement.y = rayCastHit.point.y - rayVector.y;
    rayDistance = Mathf.Abs(deltaMovement.y);

    if (isGoingUp) {
    deltaMovement.y -= skinWidth;
    colAbove = true;
    } else {
    deltaMovement.y += skinWidth;
    colBelow = true;
    }

    if (!isGoingUp && deltaMovement.y > .0001f)
    upSlope = true;

    if (rayDistance < skinWidth + .0001f)
    break;
    }


    }

    private void HandleVerticalSlope(ref Vector2 deltaMove) {
    float center = (raycastBottomLeft.x + raycastBottomRight.x) / 2;
    Vector2 direction = -Vector2.up;

    float slopeDistance = slopeLimitTangent + (raycastBottomRight.x - center);
    Vector2 slopeRayVector = new Vector2(center, raycastBottomLeft.y);

    Debug.DrawRay(slopeRayVector, direction * slopeDistance, Color.yellow);

    RaycastHit2D rayCastHit = Physics2D.Raycast(slopeRayVector, direction, slopeDistance, whatIsGround);
    if (!rayCastHit)
    return;

    float angle = Vector2.Angle(rayCastHit.normal, Vector2.up);
    if (Mathf.Abs (angle) < .0001f)
    return;

    downSlope = true;
    slopeAngle = angle;
    deltaMove.y = rayCastHit.point.y - slopeRayVector.y;


    transform.rotation = Quaternion.Euler (0, 0, facingRight ? angle : -angle);

    }

    private bool HandleHorizontalSlope(ref Vector2 deltaMove, float angle, bool isGoingRight) {
    if (Mathf.RoundToInt(angle) == 90)
    return false;
    if (angle > slopeLimit) {
    deltaMove.x = 0;
    return true;
    }
    if (deltaMove.y > .07f)
    return true;
    deltaMove.x += isGoingRight ? -skinWidth : skinWidth;
    deltaMove.y = Mathf.Abs(Mathf.Tan(angle * Mathf.Deg2Rad) * deltaMove.x);
    upSlope = true;
    colBelow = true;
    return true;

    }

    void CalcRayOrigins() {
    Vector2 size = new Vector2(GetComponent<BoxCollider2D>().size.x * Mathf.Abs(transform.localScale.x), GetComponent<BoxCollider2D>().size.y * Mathf.Abs(transform.localScale.y)) / 2;
    Vector2 center = new Vector2(GetComponent<BoxCollider2D>().center.x * transform.localScale.x, GetComponent<BoxCollider2D>().center.y * transform.localScale.y);

    raycastTopLeft = transform.position + new Vector3(center.x - size.x + skinWidth, center.y + size.y - skinWidth);
    raycastBottomRight = transform.position + new Vector3(center.x + size.x - skinWidth, center.y - size.y + skinWidth);
    raycastBottomLeft = transform.position + new Vector3(center.x - size.x + skinWidth, center.y - size.y + skinWidth);
    }

    void CorrectHorizPlacement(ref Vector2 deltaMove, bool isRight) {

    float halfWidth = (GetComponent<BoxCollider2D> ().size.x * transform.localScale.x) / 2f;
    Vector3 rayOrigin = isRight ? raycastBottomRight : raycastBottomLeft;

    if (isRight)
    rayOrigin.x -= (halfWidth + skinWidth);
    else
    rayOrigin.x += (halfWidth + skinWidth);

    Vector2 rayDirection = isRight ? Vector2.right : -Vector2.right;
    float offset = 0;

    for (int i = 1; i < horizRays - 1; i++) {
    Vector2 rayVector = new Vector2(deltaMove.x + rayOrigin.x, deltaMove.y + rayOrigin.y + (i * vertDistanceBetweenRays));

    RaycastHit2D raycastHit = Physics2D.Raycast(rayVector, rayDirection, halfWidth, whatIsGround);
    if (!raycastHit) continue;

    offset = isRight ? ((raycastHit.point.x - transform.position.x) - halfWidth) : (halfWidth - (transform.position.x - raycastHit.point.x));

    deltaMove.x += offset;


    }

    }

    }