Search Unity

Make my character crouch using the First Person Character from Unity Standard Assets

Discussion in 'Scripting' started by matiasges, May 17, 2021.

  1. matiasges

    matiasges

    Joined:
    Jan 24, 2021
    Posts:
    142
    Hi. I'm trying to code so my character can crouch using the first person character from Unity Standard Assets, but with no success. Have someone manage how to do it?

    Here is the script:

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityStandardAssets.CrossPlatformInput;
    4. using UnityStandardAssets.Utility;
    5. using Random = UnityEngine.Random;
    6.  
    7. namespace UnityStandardAssets.Characters.FirstPerson
    8. {
    9.     [RequireComponent(typeof (CharacterController))]
    10.     [RequireComponent(typeof (AudioSource))]
    11.     public class FirstPersonController : MonoBehaviour
    12.     {
    13.         [SerializeField] private bool m_IsWalking = true;
    14.         [SerializeField] private float m_WalkSpeed = 0f;
    15.         [SerializeField] private float m_RunSpeed = 0f;
    16.         [SerializeField] [Range(0f, 1f)] private float m_RunstepLenghten = 0f;
    17.         [SerializeField] private float m_JumpSpeed = 0f;
    18.         [SerializeField] private float m_StickToGroundForce = 0f;
    19.         [SerializeField] private float m_GravityMultiplier = 0f;
    20.         [SerializeField] private MouseLook m_MouseLook = new MouseLook();
    21.         [SerializeField] private bool m_UseFovKick = true;
    22.         [SerializeField] private FOVKick m_FovKick = new FOVKick();
    23.         [SerializeField] private bool m_UseHeadBob = true;
    24.         [SerializeField] private CurveControlledBob m_HeadBob = new CurveControlledBob();
    25.         [SerializeField] private LerpControlledBob m_JumpBob = new LerpControlledBob();
    26.         [SerializeField] private float m_StepInterval = 0f;
    27.         [SerializeField] private AudioClip[] m_FootstepSounds = new AudioClip[0];    // an array of footstep sounds that will be randomly selected from.
    28.         [SerializeField] private AudioClip m_JumpSound = null;           // the sound played when character leaves the ground.
    29.         [SerializeField] private AudioClip m_LandSound = null;           // the sound played when character touches back on ground.
    30.  
    31.         private Camera m_Camera;
    32.         private bool m_Jump = true;
    33.         private float m_YRotation;
    34.         private Vector2 m_Input = new Vector2();
    35.         private Vector3 m_MoveDir = Vector3.zero;
    36.         private CharacterController m_CharacterController = new CharacterController();
    37.         private CollisionFlags m_CollisionFlags = CollisionFlags.None;
    38.         private bool m_PreviouslyGrounded = false;
    39.         private Vector3 m_OriginalCameraPosition = Vector3.zero;
    40.         private float m_StepCycle = 0f;
    41.         private float m_NextStep = 0f;
    42.         private bool m_Jumping = false;
    43.         private AudioSource m_AudioSource = new AudioSource();
    44.         private Animator anim;
    45.        
    46.  
    47.         // Use this for initialization
    48.         private void Start()
    49.         {
    50.             m_CharacterController = GetComponent<CharacterController>();
    51.             m_Camera = Camera.main;
    52.             m_OriginalCameraPosition = m_Camera.transform.localPosition;
    53.             m_FovKick.Setup(m_Camera);
    54.             m_HeadBob.Setup(m_Camera, m_StepInterval);
    55.             m_StepCycle = 0f;
    56.             m_NextStep = m_StepCycle/2f;
    57.             m_Jumping = false;
    58.             m_AudioSource = GetComponent<AudioSource>();
    59.             m_MouseLook.Init(transform , m_Camera.transform);
    60.             anim = GetComponentInChildren<Animator>();
    61.         }
    62.  
    63.  
    64.         // Update is called once per frame
    65.         private void Update()
    66.         {
    67.             RotateView();
    68.             // the jump state needs to read here to make sure it is not missed
    69.             if (!m_Jump)
    70.             {
    71.                 m_Jump = CrossPlatformInputManager.GetButtonDown("Jump");
    72.             }
    73.  
    74.             if (!m_PreviouslyGrounded && m_CharacterController.isGrounded)
    75.             {
    76.                
    77.                 StartCoroutine(m_JumpBob.DoBobCycle());
    78.                 PlayLandingSound();
    79.                 m_MoveDir.y = 0f;
    80.                 m_Jumping = false;
    81.             }
    82.          
    83.             if (!m_CharacterController.isGrounded && !m_Jumping && m_PreviouslyGrounded)
    84.             {
    85.                 m_MoveDir.y = 0f;
    86.             }
    87.  
    88.             m_PreviouslyGrounded = m_CharacterController.isGrounded;
    89.  
    90.          
    91.         }
    92.  
    93.  
    94.         private void PlayLandingSound()
    95.         {
    96.             m_AudioSource.clip = m_LandSound;
    97.             m_AudioSource.Play();
    98.             m_NextStep = m_StepCycle + .5f;
    99.         }
    100.  
    101.  
    102.         private void FixedUpdate()
    103.         {
    104.             float speed;
    105.             GetInput(out speed);
    106.             // always move along the camera forward as it is the direction that it being aimed at
    107.             Vector3 desiredMove = transform.forward*m_Input.y + transform.right*m_Input.x;
    108.  
    109.             // get a normal for the surface that is being touched to move along it
    110.             RaycastHit hitInfo;
    111.             Physics.SphereCast(transform.position, m_CharacterController.radius, Vector3.down, out hitInfo,
    112.                                m_CharacterController.height/2f, Physics.AllLayers, QueryTriggerInteraction.Ignore);
    113.             desiredMove = Vector3.ProjectOnPlane(desiredMove, hitInfo.normal).normalized;
    114.  
    115.             m_MoveDir.x = desiredMove.x*speed;
    116.             m_MoveDir.z = desiredMove.z*speed;
    117.  
    118.  
    119.             if (m_CharacterController.isGrounded)
    120.             {
    121.                
    122.                 m_MoveDir.y = -m_StickToGroundForce;
    123.                
    124.                 if (m_Jump)
    125.                 {
    126.                     m_MoveDir.y = m_JumpSpeed;
    127.                     PlayJumpSound();
    128.                     m_Jump = false;
    129.                     m_Jumping = true;
    130.                 }
    131.             }
    132.             else
    133.             {
    134.                 m_MoveDir += Physics.gravity*m_GravityMultiplier*Time.fixedDeltaTime;
    135.             }
    136.             m_CollisionFlags = m_CharacterController.Move(m_MoveDir*Time.fixedDeltaTime);
    137.  
    138.             ProgressStepCycle(speed);
    139.             UpdateCameraPosition(speed);
    140.  
    141.             m_MouseLook.UpdateCursorLock();
    142.  
    143.             anim.SetBool("OnGround", m_CharacterController.isGrounded);
    144.  
    145.             anim.SetFloat("Forward", CrossPlatformInputManager.GetAxis("Vertical"), 0.1f, Time.deltaTime);
    146.             anim.SetFloat("Turn", CrossPlatformInputManager.GetAxis("Horizontal"), 0.1f, Time.deltaTime);
    147.            
    148.             if (m_CharacterController.isGrounded)
    149.             {
    150.                
    151.                 anim.SetFloat("Jump", m_CharacterController.velocity.y);
    152.             }
    153.            
    154.         }
    155.  
    156.  
    157.         private void PlayJumpSound()
    158.         {
    159.             m_AudioSource.clip = m_JumpSound;
    160.             m_AudioSource.Play();
    161.         }
    162.  
    163.  
    164.         private void ProgressStepCycle(float speed)
    165.         {
    166.             if (m_CharacterController.velocity.sqrMagnitude > 0 && (m_Input.x != 0 || m_Input.y != 0))
    167.             {
    168.                 m_StepCycle += (m_CharacterController.velocity.magnitude + (speed*(m_IsWalking ? 1f : m_RunstepLenghten)))*
    169.                              Time.fixedDeltaTime;
    170.             }
    171.  
    172.             if (!(m_StepCycle > m_NextStep))
    173.             {
    174.                 return;
    175.             }
    176.  
    177.             m_NextStep = m_StepCycle + m_StepInterval;
    178.  
    179.             PlayFootStepAudio();
    180.         }
    181.  
    182.  
    183.         private void PlayFootStepAudio()
    184.         {
    185.             if (!m_CharacterController.isGrounded)
    186.             {
    187.                 return;
    188.             }
    189.             // pick & play a random footstep sound from the array,
    190.             // excluding sound at index 0
    191.             int n = Random.Range(1, m_FootstepSounds.Length);
    192.             m_AudioSource.clip = m_FootstepSounds[n];
    193.             m_AudioSource.PlayOneShot(m_AudioSource.clip);
    194.             // move picked sound to index 0 so it's not picked next time
    195.             m_FootstepSounds[n] = m_FootstepSounds[0];
    196.             m_FootstepSounds[0] = m_AudioSource.clip;
    197.         }
    198.  
    199.  
    200.         private void UpdateCameraPosition(float speed)
    201.         {
    202.             Vector3 newCameraPosition;
    203.             if (!m_UseHeadBob)
    204.             {
    205.                 return;
    206.             }
    207.             if (m_CharacterController.velocity.magnitude > 0 && m_CharacterController.isGrounded)
    208.             {
    209.                 m_Camera.transform.localPosition =
    210.                     m_HeadBob.DoHeadBob(m_CharacterController.velocity.magnitude +
    211.                                       (speed*(m_IsWalking ? 1f : m_RunstepLenghten)));
    212.                 newCameraPosition = m_Camera.transform.localPosition;
    213.                 newCameraPosition.y = m_Camera.transform.localPosition.y - m_JumpBob.Offset();
    214.             }
    215.             else
    216.             {
    217.                 newCameraPosition = m_Camera.transform.localPosition;
    218.                 newCameraPosition.y = m_OriginalCameraPosition.y - m_JumpBob.Offset();
    219.             }
    220.             m_Camera.transform.localPosition = newCameraPosition;
    221.         }
    222.  
    223.  
    224.         private void GetInput(out float speed)
    225.         {
    226.             // Read input
    227.             float horizontal = CrossPlatformInputManager.GetAxis("Horizontal");
    228.             float vertical = CrossPlatformInputManager.GetAxis("Vertical");
    229.  
    230.             bool waswalking = m_IsWalking;
    231.  
    232. #if !MOBILE_INPUT
    233.             // On standalone builds, walk/run speed is modified by a key press.
    234.             // keep track of whether or not the character is walking or running
    235.             m_IsWalking = !Input.GetKey(KeyCode.LeftShift);
    236. #endif
    237.             // set the desired speed to be walking or running
    238.             speed = m_IsWalking ? m_WalkSpeed : m_RunSpeed;
    239.             m_Input = new Vector2(horizontal, vertical);
    240.  
    241.             // normalize input if it exceeds 1 in combined length:
    242.             if (m_Input.sqrMagnitude > 1)
    243.             {
    244.                 m_Input.Normalize();
    245.             }
    246.  
    247.             // handle speed change to give an fov kick
    248.             // only if the player is going to a run, is running and the fovkick is to be used
    249.             if (m_IsWalking != waswalking && m_UseFovKick && m_CharacterController.velocity.sqrMagnitude > 0)
    250.             {
    251.                 StopAllCoroutines();
    252.                 StartCoroutine(!m_IsWalking ? m_FovKick.FOVKickUp() : m_FovKick.FOVKickDown());
    253.             }
    254.         }
    255.  
    256.  
    257.         private void RotateView()
    258.         {
    259.             m_MouseLook.LookRotation (transform, m_Camera.transform);
    260.         }
    261.  
    262.  
    263.         private void OnControllerColliderHit(ControllerColliderHit hit)
    264.         {
    265.             Rigidbody body = hit.collider.attachedRigidbody;
    266.             //dont move the rigidbody if the character is on top of it
    267.             if (m_CollisionFlags == CollisionFlags.Below)
    268.             {
    269.                 return;
    270.             }
    271.  
    272.             if (body == null || body.isKinematic)
    273.             {
    274.                 return;
    275.             }
    276.             body.AddForceAtPosition(m_CharacterController.velocity*0.1f, hit.point, ForceMode.Impulse);
    277.         }
    278.     }
    279. }
    280.  
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    It won't just be code: there will be more animations necessary for crouching: transition in, transition out, crab walk, idle while crouched... once you have those plumbed into the MecAnim state machine, then set up properties and drive them at the appropriate places in the above script.

    I also don't know what the colliders look like on that figure, but odds are they would need to be adjusted to something smaller if you want to be able to pass under low objects that block you when standing.
     
  3. matiasges

    matiasges

    Joined:
    Jan 24, 2021
    Posts:
    142
    Yes, I have the animations. But the problem is that the camera will not lower down as for example is already set for the jump state to go up
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,674
    Looks like the two-state if block at line 207-219 above would have to be adapted to whatever states you are using to decide if you are crouched or not.

    The actual tested condition is two fold: speed magnitude and also groounded... probably want to break that up so you can decide what mode the camera should be in.

    Or else replace the camera with Cinemachine control (a package from Unity)... it seems to do a lot of useful stuff.
     
    matiasges likes this.