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

public class WeaponSway : MonoBehaviour
{
    [SerializeField] private FirstPersonController firstPersonController;
    [SerializeField] private GameObject shotgun;
    [SerializeField] private Transform cameraTransform;
    [SerializeField] private float rotationAmount;
    [SerializeField] private float maxRotationAmount;
    [SerializeField] private float smooth;
    [SerializeField] private float tiltAmount;

    [Header("Bobbing Parameters")]
    [SerializeField] private float sprintingBobSpeed;
    [SerializeField] private float sprintingBobAmount;
    [SerializeField] private float crouchingBobSpeed;
    [SerializeField] private float crouchingBobAmount;
    [SerializeField] private float walkingBobSpeed;
    [SerializeField] private float walkingBobAmount;
    [SerializeField] private float smoothLerpSpeed;

    [Header("Camera Recoil Parameters")]
    [SerializeField] private float recoilAmount;
    [SerializeField] private float recoilSpeed;
    [SerializeField] private float recoilRecoverySpeed;

    private Quaternion initialRotation;
    private float currentRecoil = 0f;
    private float recoilVelocity = 0f;   

    private float defaultXPos = 0f;
    private float defaultYPos = 0f;
    private float timer = 0f;


    private void Start() {
        initialRotation = transform.localRotation;
        firstPersonController = FindAnyObjectByType<FirstPersonController>();
    
        defaultXPos = shotgun.transform.localPosition.x;
        defaultYPos = shotgun.transform.localPosition.y; 
    }
    private void Update() {
        ShotgunBobbing();
        ApplySway();
        ApplyRecoilEffect();        
    }

    private void ApplySway() {
        float moveX = Input.GetAxis("Horizontal");
        float moveY = Input.GetAxis("Vertical");

        Quaternion moveTilt = Quaternion.Euler(
            moveY * tiltAmount,
            moveX * -tiltAmount,
            moveX * -tiltAmount
        );

        float rotationX = Input.GetAxis("Mouse Y") * -rotationAmount;      
        rotationX = Mathf.Clamp(rotationX, -maxRotationAmount, maxRotationAmount);

        float rotationY = Input.GetAxis("Mouse X") * rotationAmount;
        rotationY = Mathf.Clamp(rotationY, -maxRotationAmount, maxRotationAmount);

        Quaternion swayRotation = Quaternion.Euler(rotationX, rotationY, 0);

        transform.localRotation = Quaternion.Slerp(transform.localRotation, initialRotation * moveTilt * swayRotation, Time.deltaTime * smooth);
    }
    private void ShotgunBobbing() {
        if (!firstPersonController.characterController.isGrounded) return;

        float speed = firstPersonController.characterController.velocity.magnitude;
        bool isCrouching = firstPersonController.isPlayerCrouching;
        bool isSprinting = firstPersonController.isSprinting;

        if (Mathf.Abs(speed) > 1.5f) {
            timer += Time.deltaTime * (isCrouching ? crouchingBobSpeed : isSprinting ? sprintingBobSpeed : walkingBobSpeed);

            float bobAmount = isCrouching ? crouchingBobAmount : isSprinting ? sprintingBobAmount : walkingBobAmount;

            float bobbingX =  defaultXPos + Mathf.Sin(timer) * bobAmount;
            float bobbingY = defaultYPos + Mathf.Sin(timer) * (bobAmount * 0.25f);

            shotgun.transform.localPosition = new Vector3(bobbingX, bobbingY, shotgun.transform.localPosition.z);
        }
        else {
            Vector3 originalPosition = new Vector3(defaultXPos, defaultYPos, shotgun.transform.localPosition.z);
            shotgun.transform.localPosition = Vector3.Lerp(shotgun.transform.localPosition, originalPosition, smoothLerpSpeed * Time.deltaTime);
        }
    }
    private void ApplyRecoilEffect() {
        currentRecoil = Mathf.SmoothDamp(currentRecoil, 0f, ref recoilVelocity, recoilRecoverySpeed);
        cameraTransform.localRotation = Quaternion.Euler(-currentRecoil, 0f, 0f) * cameraTransform.localRotation;
    }
    public void ApplyCameraRecoil() {
        currentRecoil += recoilAmount;
        recoilVelocity = recoilSpeed;
    }
}
Объясни мне весь код, подробно. Я примерно понимаю, что к чему, но хотелось бы полного понимания