Zeepblok
Zeepblok

Reputation: 133

Unity3d charactercontroller bouncing on platforms while jumping but not when falling

I have something strange happening in my game.I use 3d models and a fixed camera to make a 2D platformer. I have a charactercontroller with the following script for movement and jumping:

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement : MonoBehaviour
{
private CharacterController controller;
private Vector3 playerVelocity;
private bool groundedPlayer;

[SerializeField] private Animator _animator;
[SerializeField] private float playerSpeed = 2.0f;
[SerializeField] private float jumpHeight = 4.0f;
[SerializeField] private float gravityValue = -1f;

[SerializeField] private AudioSource _audioSource;
[SerializeField] private AudioClip _stepStone;

private void Start()
{
    controller = GetComponent<CharacterController>();
    _animator = GetComponent<Animator>();
    _audioSource = GetComponent<AudioSource>();
}

void Update()
{
    MovePlayer();
}

private void MovePlayer()
{
    float x = Input.GetAxis("Horizontal");
    groundedPlayer = controller.isGrounded;
    
    if (groundedPlayer && playerVelocity.y < 0)
    {
        playerVelocity.y = 0f;
        _animator.SetBool("Jumping", false);
    }

    Vector3 move = new Vector3(x, 0,0);
    controller.Move(move * Time.deltaTime * playerSpeed);

    if (move != Vector3.zero)
    {
        gameObject.transform.forward = move;
    }

    // Changes the height position of the player..
    if (Input.GetButtonDown("Jump") && groundedPlayer)
    {
        _animator.SetBool("Jumping", true);
        playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
    }

    playerVelocity.y += gravityValue * Time.deltaTime;
    controller.Move(playerVelocity * Time.deltaTime);

    if (groundedPlayer)
    {
        _animator.SetInteger("Speed", Convert.ToInt32(x));
    }
}

public void playStoneStep()
{
    _audioSource.PlayOneShot(_stepStone);
}
}

My character bounces if it jumps on platforms but not when falling on them. I tried a non bouncy material. how can I fix this? Here is a video showing it : https://youtu.be/ZhV8nHklsH8

Upvotes: 0

Views: 81

Answers (1)

CorrieJanse
CorrieJanse

Reputation: 2598

I would do this by adding something that checks if you land on the floor. I did below split your functionality into different, more manageable parts. I've added a layer mask which you will need to configure with the layer of the ground.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerMovement: MonoBehaviour
{
    private CharacterController controller;
    private Vector3 playerVelocity;
    private bool groundedPlayer;

    [SerializeField] private Animator _animator;
    [SerializeField] private float playerSpeed = 2.0f;
    [SerializeField] private float jumpHeight = 4.0f;
    [SerializeField] private float gravityValue = -1f;

    [SerializeField] privateLayerMask groundMask;

    [SerializeField] private AudioSource _audioSource;
    [SerializeField] private AudioClip _stepStone;

    private void Start()
    {
        controller = GetComponent<CharacterController>();
        _animator = GetComponent<Animator>();
        _audioSource = GetComponent<AudioSource>();
    }

    void Update()
    {
        HandleMovement();
        HandleJump();
        HandleGravity();
    }

    private void HandleMovement()
    {
        controller.Move(new Vector3(Input.GetAxis("Horizontal"), 0,0) * Time.deltaTime * playerSpeed);
        if (groundedPlayer)
        {
            _animator.SetInteger("Speed", Convert.ToInt32(x));
        }
    }

    private void HandleJump()
    {
        if (Input.GetButtonDown("Jump") && groundedPlayer)
        {
            _animator.SetBool("Jumping", true);
            playerVelocity.y += Mathf.Sqrt(jumpHeight * -3.0f * gravityValue);
        }
    }

    private void HandleGravity()
    {
        playerVelocity.y += gravityValue * Time.deltaTime;
        controller.Move(playerVelocity * Time.deltaTime);
    }
    
    void OnCollisionEnter(Collision col)
    {
        if (IsInLayerMask(col.gameObject, groundMask))
        {
            playerVelocity.y = 0f;
            _animator.SetBool("Jumping", false);
        }
    }
    
    private bool IsInLayerMask(GameObject obj, LayerMask layerMask)
    {
        return ((layerMask.value & (1 << obj.layer)) > 0);
    }

    public void playStoneStep()
    {
        _audioSource.PlayOneShot(_stepStone);
    }
}
    
    

Upvotes: 1

Related Questions