团结4.5.1 2D播放器文件错误引力....(真的加重)

时间:2014-07-01 02:58:00

标签: unity3d gravity

我真的希望你们能帮助我解决我的问题,这是我的最后一招,我非常沮丧。

我正在创建一个2D Side-Scroller游戏,在编写播放器文件时,我遇到了一个非常讨厌的事情,我不知道问题出在哪里。玩家中的其他任何东西都很好,如果玩家正在倾斜,然后脱落,会发生什么?重力(我假设)正在被搞乱,当你在空中他只是漂浮而不是下降;如果你跳(在倾斜之后行走),他只会做一个十三小跳。我已经多次调试了整个文件,似乎无法搞清楚。

如果有人请求帮助,我会把整个播放器文件。如果你有一个统一的2D sidescroller游戏,你可以把这个文件放在一个带有rigidBody2D和isKinemic的游戏对象上。

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;


                }

    }


}

请有人帮忙。

0 个答案:

没有答案