Search Unity

how do I make simple player controller?

Discussion in 'Getting Started' started by bscohen06, Apr 24, 2020.

  1. bscohen06

    bscohen06

    Joined:
    Aug 30, 2019
    Posts:
    5
    I am a beginner and having lots of trouble with making a simple first-person 3d controller could someone help me with this??? I am on version 2019.2.3f1 I also need it to use physics
     
  2. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Well the simplest way would be to use the CharacterController. You then just call its Move or SimpleMove, and transform.Rotate methods every Update based on user input. You can just child your camera to your player GameObject. Though this isn't physics based movement.

    https://docs.unity3d.com/ScriptReference/CharacterController.Move.html
    https://docs.unity3d.com/ScriptReference/CharacterController.SimpleMove.html

    For physics movement though you generally do so through adding forces. You take input in Update and apply the forces in FixedUpdate. This can be a lot more tricky to get to behave just right, though the motion looks more realistic for something like a ball rolling. You also have to deal with the object possibly knocking or falling on its side, getting pushed by other physics objects, or otherwise moving in ways the player may not expect based on their inputs. You'd probably want to use a separate camera GameObject using a camera follow script rather than making it a child, unless you want the camera to flip upside down if a physics force flips the player upside down.

    https://docs.unity3d.com/ScriptReference/Rigidbody.AddForce.html
     
  3. bscohen06

    bscohen06

    Joined:
    Aug 30, 2019
    Posts:
    5
    I mean making something from scratch the playercontroller is pretty bad
     
  4. Joe-Censored

    Joe-Censored

    Joined:
    Mar 26, 2013
    Posts:
    11,847
    Did you not see the second half of my comment?
     
  5. Fungikokoas

    Fungikokoas

    Joined:
    Aug 12, 2021
    Posts:
    2
    This script can help you. You can walk, run, jump, crouch and have footsteps.
    upload_2022-3-12_13-19-10.png
    Code (CSharp):
    1. using System.Collections;
    2. using UnityEngine;
    3.  
    4.  
    5. public class FPS_Player : MonoBehaviour
    6. {
    7.     public bool CanMove { get; private set; } = true;
    8.     private bool IsSprinting => canSprint && Input.GetKey(sprintKey);
    9.     private bool ShouldJump => Input.GetKeyDown(jumpkey) && characterController.isGrounded;
    10.     private bool ShouldCrouch => Input.GetKeyDown(crouchKey) && !duringCrouchAnimation && characterController.isGrounded;
    11.  
    12.     [Header("Functional Options")]
    13.     [SerializeField] private bool canSprint = true;
    14.     [SerializeField] private bool canJump = true;
    15.     [SerializeField] private bool canCrouch = true;
    16.     [SerializeField] private bool canUseHeadbob = true;
    17.  
    18.     [Header("Controls")]
    19.     [SerializeField] private KeyCode sprintKey = KeyCode.LeftShift;
    20.     [SerializeField] private KeyCode jumpkey = KeyCode.Space;
    21.     [SerializeField] private KeyCode crouchKey = KeyCode.LeftControl;
    22.  
    23.     [Header("Movement Parameters")]
    24.     [SerializeField] private float walkSpeed = 3.0f;
    25.     [SerializeField] private float sprintSpeed = 6.0f;
    26.     [SerializeField] private float crouchSpeed = 1.5f;
    27.  
    28.     [Header("Look Parameters")]
    29.     [SerializeField, Range(1, 10)] private float lookSpeedX = 2.0f;
    30.     [SerializeField, Range(1, 10)] private float lookSpeedY = 2.0f;
    31.     [SerializeField, Range(1, 180)] private float upperLookLimit = 80.0f;
    32.     [SerializeField, Range(1, 180)] private float lowerLookLimit = 80.0f;
    33.  
    34.     [Header("Jumping Parameters")]
    35.     [SerializeField] private float jumpForce = 8.0f;
    36.     [SerializeField] private float gravity = 30.0f;
    37.  
    38.     [Header("Crouch Parameters")]
    39.     [SerializeField] private float crouchHeight = 0.5f;
    40.     [SerializeField] private float standingHeight = 2f;
    41.     [SerializeField] private float timeToCrouch = 0.25f;
    42.     [SerializeField] private Vector3 crouchingCenter = new Vector3(0, 0.5f, 0);
    43.     [SerializeField] private Vector3 standingCenter = new Vector3(0, 0, 0);
    44.     private bool isCrouching;
    45.     private bool duringCrouchAnimation;
    46.  
    47.     [Header("Headbob Parameters")]
    48.     [SerializeField] private float walkBobSpeed = 14f;
    49.     [SerializeField] private float walkBobAmount = 0.05f;
    50.     [SerializeField] private float sprintBobSpeed = 18f;
    51.     [SerializeField] private float sprintBobAmount = 0.11f;
    52.     [SerializeField] private float crouchBobSpeed = 8f;
    53.     [SerializeField] private float crouchBobAmount = 0.025f;
    54.     private float defaultYPos = 0;
    55.     private float timer;
    56.  
    57.     //private Vector3 hitPointNormal;
    58.     private Camera playerCamera;
    59.     private CharacterController characterController;
    60.  
    61.     private Vector3 moveDirection;
    62.     private Vector2 currentInput;
    63.  
    64.     private float rotationX = 0;
    65.  
    66.     [Header("Footsteps objects")]
    67.     AudioSource audioSource;
    68.    
    69.  
    70.     [Header("Etiqueta Madera")]
    71.     public AudioClip[] Pasosmadera;
    72.     //public Texture madera;
    73.  
    74.     [Header("Etiqueta Pasto")]
    75.     public AudioClip[] Pasospasto;
    76.     //public Texture pasto;
    77.  
    78.     [Header("Etiqueta Piedra")]
    79.     public AudioClip[] Pasospiedra;
    80.     //public Texture piedra;
    81.  
    82.     [Header("Intervalo de pasos")]
    83.     public float TimeBetweenSteps;
    84.     float tiempo;
    85.     int soundControl;
    86.     public bool isMoving;
    87.     public bool isSpriting;
    88.     public bool isAgachado;
    89.     float airTime;
    90.  
    91.     void Awake()
    92.     {
    93.         playerCamera = GetComponentInChildren<Camera>();
    94.         characterController = GetComponent<CharacterController>();
    95.         defaultYPos = playerCamera.transform.localPosition.y;
    96.         Cursor.lockState = CursorLockMode.Locked;
    97.         Cursor.visible = false;
    98.  
    99.         audioSource = GetComponent<AudioSource>();
    100.        
    101.     }
    102.  
    103.     //Identifica la etiqueta para reproducir un sonido
    104.    private void OnControllerColliderHit(ControllerColliderHit hit)
    105.     {
    106.         switch (hit.transform.tag)
    107.         {
    108.             case  "Madera":
    109.                 soundControl = 0;
    110.                 break;
    111.             case "Pasto":
    112.                 soundControl = 1;
    113.                 break;
    114.             case "Piedra":
    115.                 soundControl = 2;
    116.                 break;
    117.         }
    118.     }
    119.  
    120.     //Los movimientos son identificados
    121.     void Update()
    122.     {
    123.         if (CanMove)
    124.         {
    125.             HandleMovementInput();
    126.             HandleMouseLook();
    127.            
    128.  
    129.             if (canJump)
    130.                 HandleJump();
    131.  
    132.             if (canCrouch)
    133.                 HandleCrouch();
    134.  
    135.             if (canUseHeadbob)
    136.                 HandleHeadbob();
    137.  
    138.             ApplyFinalMovements();
    139.  
    140.         }
    141.         //Llamada al Salto
    142.         PlaySoundFalling();
    143.  
    144.         //Condiciones para los sonidos de pasos(footsteps objects)
    145.          float horizontal = Input.GetAxis("Horizontal");
    146.          float vertical = Input.GetAxis("Vertical");
    147.  
    148.          if (horizontal != 0 || vertical != 0 && characterController.isGrounded)
    149.          {
    150.              isMoving = true;
    151.              tiempo -= Time.deltaTime;
    152.              if (tiempo <= 0)
    153.              {
    154.                  switch (soundControl)
    155.                  {
    156.                      case 0: audioSource.clip = Pasosmadera[Random.Range(0, Pasosmadera.Length)]; break;
    157.                      case 1: audioSource.clip = Pasospasto[Random.Range(0, Pasospasto.Length)]; break;
    158.                      case 2: audioSource.clip = Pasospiedra[Random.Range(0, Pasospiedra.Length)]; break;
    159.                  }
    160.                  tiempo = TimeBetweenSteps;
    161.                  audioSource.pitch = Random.Range(0.65f, 1f);
    162.                  audioSource.volume = Random.Range(0.85f, 1f);
    163.                  audioSource.Play();
    164.              }
    165.          }
    166.          else
    167.          {
    168.              isMoving = false;
    169.              tiempo = Time.deltaTime;
    170.          }
    171.  
    172.          if (IsSprinting)
    173.          {
    174.              isSpriting = true;
    175.              TimeBetweenSteps = 0.5f;
    176.          }
    177.          else
    178.          {
    179.              isSpriting = false;
    180.              TimeBetweenSteps = 1f;
    181.          }
    182.  
    183.          if (isCrouching)
    184.          {
    185.              isAgachado = true;
    186.              TimeBetweenSteps = 1.5f;
    187.          }
    188.          else
    189.          {
    190.              isAgachado = false;
    191.          }
    192.  
    193.          //Sonido del salto solo al entrar en contacto con el objeto
    194.          void PlaySoundFalling()
    195.          {
    196.             if (!characterController.isGrounded) {
    197.                 airTime += Time.deltaTime;
    198.             } else
    199.             {
    200.                 if(airTime > 0.2f)
    201.                 {
    202.                     switch (soundControl)
    203.                     {
    204.                         case 0: audioSource.clip = Pasosmadera[Random.Range(0, Pasosmadera.Length)]; break;
    205.                         case 1: audioSource.clip = Pasospasto[Random.Range(0, Pasospasto.Length)]; break;
    206.                         case 2: audioSource.clip = Pasospiedra[Random.Range(0, Pasospiedra.Length)]; break;
    207.                     }
    208.                     tiempo = TimeBetweenSteps;
    209.                     audioSource.pitch = Random.Range(0.65f, 0.70f);
    210.                     audioSource.volume = Random.Range(0.65f, 0.75f);
    211.                     audioSource.Play();
    212.                     airTime = 0;
    213.                 }
    214.             }
    215.  
    216.          }
    217.  
    218.     }
    219.  
    220.     //Se detecta los botones del teclado para ejecutar acciones
    221.     private void HandleMovementInput()
    222.     {
    223.  
    224.         currentInput = new Vector2((IsSprinting ? sprintSpeed : isCrouching ? crouchSpeed : walkSpeed) * Input.GetAxis("Vertical"), (IsSprinting ? sprintSpeed : isCrouching ? crouchSpeed : walkSpeed) * Input.GetAxis("Horizontal"));
    225.  
    226.         float moveDirectionY = moveDirection.y;
    227.         moveDirection = (transform.TransformDirection(Vector3.forward) * currentInput.x) + (transform.TransformDirection(Vector3.right) * currentInput.y);
    228.         moveDirection.y = moveDirectionY;
    229.  
    230.     }
    231.  
    232.     //Movimiento del Mouse
    233.     private void HandleMouseLook()
    234.     {
    235.         rotationX -= Input.GetAxis("Mouse Y") * lookSpeedY;
    236.         rotationX = Mathf.Clamp(rotationX, -upperLookLimit, lowerLookLimit);
    237.         playerCamera.transform.localRotation = Quaternion.Euler(rotationX, 0, 0);
    238.         transform.rotation *= Quaternion.Euler(0, Input.GetAxis("Mouse X") * lookSpeedX, 0);
    239.  
    240.     }
    241.  
    242.     //Si saltamos
    243.     private void HandleJump()
    244.     {
    245.         if (ShouldJump)
    246.             moveDirection.y = jumpForce;
    247.     }
    248.  
    249.     //Si nos agachamos
    250.     private void HandleCrouch()
    251.     {
    252.         if (ShouldCrouch)
    253.             StartCoroutine(CrouchStand());
    254.     }
    255.  
    256.     //Movimiento de la cabeza(cámara) dependiendo de nuestro estado
    257.     private void HandleHeadbob()
    258.     {
    259.         if (!characterController.isGrounded) return;
    260.  
    261.         if (Mathf.Abs(moveDirection.x) > 0.1f || Mathf.Abs(moveDirection.z) > 0.1f)
    262.         {
    263.             timer += Time.deltaTime * (isCrouching ? crouchBobSpeed : IsSprinting ? sprintBobSpeed : walkBobSpeed);
    264.             playerCamera.transform.localPosition = new Vector3(
    265.                  playerCamera.transform.localPosition.x,
    266.                  defaultYPos + Mathf.Sin(timer) * (isCrouching ? crouchBobAmount : IsSprinting ? sprintBobAmount : walkBobAmount),
    267.                  playerCamera.transform.localPosition.z);
    268.         }
    269.     }
    270.  
    271.     //Movimiento y gravedad incluyendo si nuestro jugador esta o no esta pisando
    272.     private void ApplyFinalMovements()
    273.     {
    274.  
    275.         if (!characterController.isGrounded)
    276.             moveDirection.y -= gravity * Time.deltaTime;
    277.         characterController.Move(moveDirection * Time.deltaTime);
    278.  
    279.     }
    280.  
    281.     //Al agacharse identifica si tenemos un objeto encima para no atravesarlo si nos erguimos
    282.     //Al agacharse se realiza suavemente y viceversa
    283.     //Al agacharse no podemos correr y saltar
    284.     private IEnumerator CrouchStand()
    285.     {
    286.         if (isCrouching && Physics.Raycast(playerCamera.transform.position, Vector3.up, 1f))
    287.             yield break;
    288.  
    289.         duringCrouchAnimation = true;
    290.        
    291.  
    292.         float timeElapsed = 0;
    293.         float targetHeight = isCrouching ? standingHeight : crouchHeight;
    294.         float currentHeight = characterController.height;
    295.         Vector3 targetCenter = isCrouching ? standingCenter : crouchingCenter;
    296.         Vector3 currentCenter = characterController.center;
    297.  
    298.         while (timeElapsed < timeToCrouch)
    299.         {
    300.             characterController.height = Mathf.Lerp(currentHeight, targetHeight, timeElapsed / timeToCrouch);
    301.             characterController.center = Vector3.Lerp(currentCenter, targetCenter, timeElapsed / timeToCrouch);
    302.             timeElapsed += Time.deltaTime;
    303.             yield return null;
    304.         }
    305.  
    306.         characterController.height = targetHeight;
    307.         characterController.center = targetCenter;
    308.  
    309.         isCrouching = !isCrouching;
    310.  
    311.         duringCrouchAnimation = false;
    312.         canJump = !canJump;
    313.         canSprint = !canSprint;
    314.     }
    315.  
    316. }
     
  6. Rahi28_062008

    Rahi28_062008

    Joined:
    Dec 14, 2022
    Posts:
    1
    Thank You
     
  7. SixSlice

    SixSlice

    Joined:
    May 27, 2023
    Posts:
    1
    DOES ANYONE KNOW HOW TO MAKE A 3RD PERSON CONTROLLER?
     
  8. Burgercat67

    Burgercat67

    Joined:
    Feb 2, 2023
    Posts:
    1
    you just use the same script but move the camera behind it a bit
     
  9. dman2013

    dman2013

    Joined:
    Jan 12, 2024
    Posts:
    1
    all of that WORKED i spent weeks trying to figure out this thank you