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

Question how to make player still move when jumping? [READ THREAD BC IT WILL MAKE MORE SENSE]

Discussion in 'Scripting' started by SpyderManToo, Jun 28, 2021.

  1. SpyderManToo

    SpyderManToo

    Joined:
    Dec 8, 2020
    Posts:
    387
    so recently, ive been trying to fix a problem where the player can still climb walls. i fixed this problem but now, once the player jumps, he can only move in one direction(which makes sense logically) but if you jump before moving, you cant move at all, how can i fix this while still maintaining the player not climbing up walls?

    here is my script
    Code (CSharp):
    1. using System.Collections.Generic;
    2. using UnityEngine;
    3.  
    4. public class PlayerController : MonoBehaviour
    5. {
    6.     public static PlayerController instance;
    7.  
    8.     [Header("Movement and Jump")]
    9.     public float moveSpeed;
    10.     public float runSpeed = 12f;
    11.     public float jumpPower;
    12.  
    13.     [HideInInspector]
    14.     public bool canJump;
    15.     private bool canDoubleJump = false;
    16.  
    17.     public Animator anim;
    18.     private Rigidbody rb;
    19.  
    20.     private Vector3 newMovePos;
    21.  
    22.     private float bounceAmount;
    23.     private bool bounce;
    24.     [HideInInspector]
    25.     public bool canWalk;
    26.  
    27.     bool isGrounded;
    28.     public Transform groundCheck;
    29.     public LayerMask ground;
    30.     public float groundDistance = 0.4f;
    31.  
    32.     [Header("Looking")]
    33.     public Transform camHolder;
    34.     public Transform camTrans;
    35.     public float mouseSens;
    36.     float verticalLookRotation = 0f;
    37.  
    38.     [Header("Shooting")]
    39.     public List<Gun> allGuns = new List<Gun>();
    40.     public List<Gun> unlockableGuns = new List<Gun>();
    41.     public Gun activeGun;
    42.     public int startGun;
    43.     private int currentGun;
    44.  
    45.     public LayerMask layersThatAffectShooting;
    46.  
    47.     [Space(25)]
    48.     public Transform firePoint;
    49.  
    50.     [Space(25)]
    51.     public Transform ADSPoint, gunHolder;
    52.     private Vector3 gunStartPos;
    53.     public float adsSpeed = 2f;
    54.  
    55.     [Space(20)]
    56.     public GameObject muzzleFlash;
    57.  
    58.     [Header("Audio")]
    59.     public AudioSource footstepFast, footstepSlow;
    60.  
    61.     private void Awake()
    62.     {
    63.         Time.timeScale = 1f;
    64.         instance = this;
    65.     }
    66.  
    67.     // Start is called before the first frame update
    68.     void Start()
    69.     {
    70.         rb = GetComponent<Rigidbody>();
    71.  
    72.         for (int i = 0; i < allGuns.Count; i++)
    73.         {
    74.             allGuns[i].gameObject.SetActive(false);
    75.         }
    76.  
    77.         currentGun = startGun;
    78.  
    79.         SwitchGun();
    80.  
    81.         gunStartPos = gunHolder.localPosition;
    82.     }
    83.  
    84.     // Update is called once per frame
    85.     void Update()
    86.     {
    87.         if (!UIController.instance.pauseMenu.activeInHierarchy && !GameManager.instance.levelEnding)
    88.         {
    89.             muzzleFlash.SetActive(false);
    90.  
    91.             //isGrounded = ;
    92.             //Debug.Log(isGrounded.ToString());
    93.  
    94.             canJump = Physics.CheckSphere(groundCheck.position, groundDistance, ground);
    95.             Debug.Log(canJump.ToString());
    96.  
    97.             Jump();
    98.             HandleADS();
    99.             Look();
    100.             Shoot();
    101.             WeaponSwitchInput();
    102.             SwitchGun();
    103.  
    104.             if(bounce)
    105.             {
    106.                 bounce = false;
    107.                 rb.AddForce(transform.up * bounceAmount, ForceMode.Impulse);
    108.  
    109.                 canDoubleJump = true;
    110.             }
    111.  
    112.             anim.SetFloat("moveSpeed", newMovePos.magnitude);
    113.             anim.SetBool("onGround", canJump);
    114.         }
    115.     }
    116.  
    117.     private void FixedUpdate()
    118.     {
    119.         if (!UIController.instance.pauseMenu.activeInHierarchy && !GameManager.instance.levelEnding)
    120.         {
    121.             Movement();
    122.         }
    123.     }
    124.  
    125.     void Movement()
    126.     {
    127.         if (canJump)
    128.         {
    129.             float x = Input.GetAxis("Horizontal");
    130.             float y = Input.GetAxis("Vertical");
    131.  
    132.             if (Input.GetKey(KeyCode.LeftShift))
    133.             {
    134.                 x *= runSpeed;
    135.                 y *= runSpeed;
    136.             }
    137.             else
    138.             {
    139.                 x *= moveSpeed;
    140.                 y *= moveSpeed;
    141.             }
    142.  
    143.             Vector3 movePos = transform.right * x + transform.forward * y;
    144.             newMovePos = new Vector3(movePos.x, rb.velocity.y, movePos.z);
    145.  
    146.             rb.velocity = newMovePos;
    147.         }
    148.     }
    149.  
    150.     void Jump()
    151.     {
    152.         //Handle Jumping
    153.         if (Input.GetKeyDown(KeyCode.Space))
    154.         {
    155.             if (canJump)
    156.             {
    157.                 rb.AddForce(transform.up * jumpPower, ForceMode.Impulse);
    158.  
    159.                 //moveInput.y = jumpPower;
    160.  
    161.                 canJump = false;
    162.                 canDoubleJump = true;
    163.  
    164.                 AudioManager.instance.PlaySFX(8);
    165.                
    166.             }
    167.             else if (canDoubleJump)
    168.             {
    169.                 rb.AddForce(transform.up * jumpPower, ForceMode.Impulse);
    170.                 //moveInput.y = jumpPower;
    171.  
    172.                 canDoubleJump = false;
    173.  
    174.                 AudioManager.instance.PlaySFX(8);
    175.             }
    176.         }
    177.     }
    178. }
    i got rid of all the code that isnt relevant to this topic btw
     
  2. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,644
    Just add movement while canJump is false...?
     
  3. SpyderManToo

    SpyderManToo

    Joined:
    Dec 8, 2020
    Posts:
    387
    no that wont work bc then i can climb walls, i use physics.checksphere for canjump(canjump is basically isGrounded) and if i allow movement, the player will be able to go up walls that are too steep for him(not completely vertical but like a very steep slope)
     
  4. RadRedPanda

    RadRedPanda

    Joined:
    May 9, 2018
    Posts:
    1,644
    You can't both not allow the player to move and have them be able to move, it contradicts itself. Best I can say is to give them control for like 0.2 seconds after they jump.
     
  5. vargata

    vargata

    Joined:
    Nov 26, 2013
    Posts:
    120
    do you have a navmesh? (I guess if you have npc-s then yes) so instead of this silly checksphere you could check if the player is on the navmesh. that limits where he can go.
     
  6. SpyderManToo

    SpyderManToo

    Joined:
    Dec 8, 2020
    Posts:
    387
    ...omg thats brilliant yes i do have a navmesh, how can i do that?
     
  7. SpyderManToo

    SpyderManToo

    Joined:
    Dec 8, 2020
    Posts:
    387
    i made a coroutine for this but im not sure where to put it
     
  8. vargata

    vargata

    Joined:
    Nov 26, 2013
    Posts:
    120
    look up NavMesh.SamplePosition
     
  9. SpyderManToo

    SpyderManToo

    Joined:
    Dec 8, 2020
    Posts:
    387
    im not entirely sure how it works...
    i did this
    Code (CSharp):
    1.  NavMeshHit hit;
    2.             if (NavMesh.SamplePosition(groundCheck.position, out hit, groundDistance, NavMesh.AllAreas))
    3.             {
    4.                 canJump = true;
    5.             }
    but everything is kinda laggy and you can still walk up walls

    i dont think im doing it correctly, could you teach me how to do it?
     
  10. vargata

    vargata

    Joined:
    Nov 26, 2013
    Posts:
    120
    I just wrote this out of my head, never tried it, so don't just copy paste, but this is how you have to think. when the player press the jump button, you fetch the nearest position on the navmesh to the player. then you have to check the returned position that is stored in the "hit" (that's why its marked "out", it has the position coming out...), if its the same as the player position, then you are on the ground. It works the same way as raycast. Also, instead of the "==" you might will have to check for a very tiny distance as Im not sure it will return the exact value, but you have to debug and play with these...

    Code (CSharp):
    1. if(input.getmousebuttondown(jump)){
    2.    NavMesh.SamplePosition(player.position, out hit, 0.01f, NavMesh.Walkable);
    3.    if(hit.position == player.position)
    4.       jump
    5. }
    this will help even if you will have the idea to have different terrains, like concrete, sand, swamp, you can set different jump forces, or forbid jumping even where there is a valid navmesh, just use the right area mask
     
  11. vargata

    vargata

    Joined:
    Nov 26, 2013
    Posts:
    120
    Or you can similarly use NavMesh.Raycast, but then you have to cast a navmesh ray from the feet of the player and if the distance for the hit is zero, you are on the ground... it can also help with giving orders to your teammates (if there will be any) as you can send them to the position where your crosshair hits the navmesh (then you start the ray from the camera position)