Код прыжка и движения для моего игрока работает только с перерывами - PullRequest
0 голосов
/ 10 марта 2020

Итак, я разрабатываю многопользовательскую онлайн-игру FPS для основной работы над SDD, и я столкнулся с проблемой. Ниже приведен код движения для моего игрока. Я пытаюсь внедрить в игру страйфинг и зайчик, поэтому я настроил тестовую среду в своем проекте, и мне удалось заставить все работать. Единственная проблема заключалась в том, что после того, как я попытался вставить это обратно в свой основной проект, он перестал работать.

Основная проблема в том, что прыжки иногда работают только иногда. Игрок прыгает только на очень небольшую величину и иногда остается там, что означает отсутствие трения, поскольку игрок застрял на земле. Он также, кажется, немного приподнимается под землей, но коллайдер на нем не должен допустить этого. Я пытался удалить код, который ускоряет падение вниз, но иногда это только исправляет.

Ссылка на код: https://pastebin.com/cLkemQhX

    public class PlayerMovement: MonoBehaviourPun
{
    [Header("Movement Settings")]
    public float maxVelocityGround = 15f;
    public float maxVelocityAir = 10f;
    public float groundAccelerate = 90f;
    public float airAccelerate = 180f;
    public float fallMultiplier = 1.2f;
    public float lookSens = 8f;
    public float slowDrag = 0;
    public float thrusterForce = 7f;
    public float friction = 10f;
    private float _friction = 0f;

    [Header("Rotation")]
    float xRot = 0F;
    float yRot = 0F;
    float minY = -90f;
    float maxY = 90f;
    Quaternion originalRotation;

    //More Movement Variables
    private float distToGround;
    private Vector3 _velocity;
    private Vector2 xyVelocity;


    [Header("References")]
    //public Text grounded;
    //public Text velocity;
    public Camera cam;
    private Move motor;
    private Rigidbody rb;
    private CapsuleCollider collidr;
    private GameObject rayPoint;



    //private PlayerSetup playerSetup;


    //Booleans
    private bool jumpy = false;

    void Start()
    {
        _friction = friction;

        //Locks the cursor to the middle of the screen, and hides it from view
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;

        //These attatch the correct objectss to their references in the script, defined above
        motor = GetComponent<Move>();
        rb = GetComponent<Rigidbody>();
        collidr = GetComponent<CapsuleCollider>();
        rayPoint = GameObject.Find("point");
        //playerSetup = GetComponent<PlayerSetup>();

        //Sets the distance to the ground from the center of the collider, used in determining whe nthe player is on the ground
        distToGround = collidr.bounds.extents.y;

        if (GetComponent<Rigidbody>())
            GetComponent<Rigidbody>().freezeRotation = true;
        originalRotation = transform.localRotation;

    }




    void FixedUpdate()
    {
        //Debug function that shows a visual representation of when the player is on the ground
        //string a = isGrounded().ToString();
        //grounded.GetComponent<Text>().text = a;

        //Finds the Velocity in the x plane. Also used in debug, as it shows it on screen
        //xyVelocity = new Vector2(rb.velocity.x, rb.velocity.z);
        //velocity.GetComponent<Text>().text = xyVelocity.magnitude.ToString("0.000");


        //This statement checks if the player both is on the ground, and has requested to jump. If so it will jump
        //while also not allowing multiple jumps while in the air. If the player holds it down, he will jump as soon
        //as he touches the ground, avoiding friction and allowing the player to bunnyhop
        if (Input.GetKey("space") && isGrounded())
        {
            rb.AddForce(Vector3.up * thrusterForce, ForceMode.Impulse);
            jumpy = true;
        }
        //rb.AddForce(Jump(), ForceMode.Impulse);
        //This makes you fall faster than you rise, and make jumping feel nicer overall.
        if (rb.velocity.y < 0)
        {
            rb.velocity += Vector3.up * Physics.gravity.y * fallMultiplier * Time.deltaTime;
        }


        //Gets the input from the axis'
        float input_y = Input.GetAxis("Vertical");
        float input_x = Input.GetAxis("Horizontal");

        //Calculates the direction we want to move in, taking into account mouse movement to allow for strafing
        Vector3 accelDir = (transform.forward * input_y + transform.right * input_x).normalized;

        //Checks if we are not pressing any inputs, and makes us decelerate faster, to make moving feel more snappy
        decelerate(accelDir);

        //This code adjusts the vector to be projected onto the plane that we are currently moving on. Makes strafing better
        RaycastHit hit;
        Physics.Raycast(collidr.center, Vector3.down, out hit, 1000);
        accelDir = Vector3.ProjectOnPlane(accelDir, hit.normal).normalized;

        //Finds the current velocity of our RIgidBody
        Vector3 curVel = rb.velocity;
        //Determines whether or not we want to use the air movement(ignore friction) or not.
        //The boolean checks if we have just jumped, so while we are still on the ground, we don't want to calculate friciton
        if (isGrounded() && jumpy == false)
        {
            _velocity = MoveGround(accelDir, curVel);
        }
        else
        {
            _velocity = MoveAir(accelDir, curVel);
        }

        //Apply Movement
        rb.velocity = _velocity;




        //These call the rotation functions below, one rotates the camera in the y plane, the other the rigidbody in the x plane, which has the camera as a child
        cameraRotate();
        rbRotate();

        jumpy = false;

    }

    private Vector3 MoveGround(Vector3 accelDir, Vector3 prevVelocity)
    {
        // Apply Friction
        float speed = prevVelocity.magnitude;
        if (speed != 0) // To avoid divide by zero errors
        {
            float drop = speed * _friction * Time.fixedDeltaTime;
            prevVelocity *= Mathf.Max(speed - drop, 0) / speed; // Scale the velocity based on friction.
        }

        return Accelerate(accelDir, prevVelocity, groundAccelerate, maxVelocityGround);
    }

    private Vector3 MoveAir(Vector3 accelDir, Vector3 prevVelocity)
    {
        return Accelerate(accelDir, prevVelocity, airAccelerate, maxVelocityAir);
    }

    private Vector3 Accelerate(Vector3 accelDir, Vector3 prevVelocity, float accelerate, float max_velocity)
    {
        float projVel = Vector3.Dot(prevVelocity, accelDir); // Vector projection of Current velocity onto accelDir.
        float accelVel = accelerate * Time.fixedDeltaTime; // Accelerated velocity in direction of movment

        // If necessary, truncate the accelerated velocity so the vector projection does not exceed max_velocity
        if (projVel + accelVel > max_velocity)
        {
            accelVel = max_velocity - projVel;
        };

        return prevVelocity + accelDir * accelVel;
    }


    //Function to check if we are on the ground
    public bool isGrounded()
    {
        return Physics.Raycast(collidr.bounds.center, Vector3.down, distToGround);

        //Below is a capsule cast, it would be better to implement because it has a thickness
        //return Physics.CheckCapsule(collider.bounds.center, new Vector3(collider.bounds.center.x, collider.bounds.min.y, collider.bounds.center.z), collider.radius * 0.9f);
    }

    /// <summary>
    /// decelerates us faster when not moving
    /// </summary>
    /// <param name="input"></param>
    public void decelerate(Vector3 input)
    {
        if (input == Vector3.zero)
        {
            _friction = 10f * friction;
        }
        else
        {
            _friction = friction;
        }
    }
    /// <summary>
    /// This function is the camera rotation function
    /// </summary>
    public void cameraRotate()
    {
        //Get the input from the mouse and multiply it by sensitivity so it can be adjusted from ingame
        yRot += Input.GetAxis("Mouse Y") * lookSens;
        //Clamp it so that we cant just keep spinning in the Y direction
        yRot = clamp(yRot, minY, maxY);
        //Calculate the quaternion using the amount of rotation found before. We use the negative mouse input as the amount
        //of rotation, and then specify that we want this rotation to be around the x axis. It seems counter intuitive, but this is the way to do it
        Quaternion yRotAngle = Quaternion.AngleAxis(-yRot, Vector3.right);
        //Apply this rotation to the cameras transform
        cam.transform.localRotation = originalRotation * yRotAngle;
    }
    /// <summary>
    /// Basically the same as above, but we dont need to clamp it because we want to be able to forever spin to the left and right
    /// </summary>
    public void rbRotate()
    {
        xRot += Input.GetAxis("Mouse X") * lookSens;
        Quaternion xRotAngle = Quaternion.AngleAxis(xRot, Vector3.up);
        rb.transform.localRotation = originalRotation * xRotAngle;
    }
    /// <summary>
    /// just clamps the angle we input between the next 2 floats
    /// </summary>
    /// <param name="angle">the float representation of the angle</param>
    /// <param name="min">the min that the angle can be</param>
    /// <param name="max">you got it by now right?></param>
    /// <returns></returns>
    private float clamp(float angle, float min, float max)
    {
        return Mathf.Clamp(angle, min, max);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...