Siento que este código esta desordenado, que tiene varias cosas que se pueden simplificar y que su lectura es dificil, podrías mejorarlo?


using System.Collections.Generic;
using MoreMountains.Feedbacks;
using UnityEngine;
using UnityEngine.Serialization;

namespace Cards
{
    public class HandController : MonoBehaviour 
    {
        [Header("Card Settings")] 
        [SerializeField] private bool cardUprightWhenSelected = true;
        [SerializeField] private bool cardTilt = true;
        [SerializeField] private Canvas canvas;
        [SerializeField] private GameObject notEnoughResources;
        
        
        [Header("Hand Settings")]
        [SerializeField] [Range(0, 5)] private float selectionSpacing = 1;
        [SerializeField] private Vector3 curveStart = new Vector3(2f, -0.7f, 0);
        [SerializeField] private Vector3 curveEnd = new Vector3(-2f, -0.7f, 0);
        [SerializeField] private RectTransform targetRectTransform;



        [Header("References")] 
        public RectTransform canvasCenter;
        public RectTransform discardTransform;
        public RectTransform drawTransform;
        public List<CardBase> hand; // Cards currently in hand
        public bool isDragging;
        public bool Active { get; set; }
        
        [Header("Sounds")] 
        [SerializeField] MMF_Player hoverSound;

        #region Cache
        
        private Vector3 _a, _b, _c; // Used for shaping hand into curve
       
        private int selectedCardIndex = -1; // Card index that is nearest to mouse
        private int draggedCardInsideHandIndex = -1; // Card index that is held by mouse (inside of hand)
        private CardBase draggedCardOutsideHand; // Card that is held by mouse (when outside of hand)
        private int draggedCardOutsideHandIndex;
        private Vector3 _heldCardOffset;
        private Vector2 _heldCardTilt;
        private Vector2 _force;
        private Vector3 _mouseWorldPos;
        private Vector2 _prevMousePos;
        private Vector2 _mousePosDelta;

        private RectTransform rectTransform;
        private Vector3 rectCenter;

        private Rect _handBounds;
        private bool _mouseInsideHand;
        
        private bool updateHierarchyOrder = true;
        private bool showDebugGizmos = true;
        
        private bool isClick; // Variable to determine if it’s a click or drag

        private Vector3 initialMousePosition; // Position of mouse when button is first pressed
        private readonly float dragThreshold = 10f; // Threshold to determine drag vs click
        
        RectTransform canvasRectTransform;
        
        public bool IsDraggingActive { get; private set; } = true;

        #endregion

        #region Setup
        
        
        private void Start()
        {
            InitHand();
        }

        private void InitHand()
        {
            rectTransform = GetComponent<RectTransform>();
            rectCenter = new Vector3(rectTransform.rect.center.x, rectTransform.rect.center.y);
            _a = rectCenter + curveStart;
            _b = rectCenter;
            _c = rectCenter + curveEnd;
            _prevMousePos = Input.mousePosition;
            canvasRectTransform = canvas.GetComponent<RectTransform>();
            Active = true;
        }

        public Vector3 GetCurvePointByIndex(int i, int cardCount)
        {
            var t = (cardCount > 1 ? (float)i / (cardCount - 1) : 0.5f);
            var p = GetCurvePoint(_a, _b, _c, t);
            return p;
        }

        public void SetCardParent(RectTransform cardTransform)
        {
            cardTransform.SetAsLastSibling();
        }

        #endregion

        #region Process
        private void Update()
        {
            HandleMouseInput();
            HandleCardsInHand();
            HandleDraggedCardOutsideHand();
            HandleDraggedCardInsideHand();
        }
        #endregion
        
        #region Methods


        private void HandleMouseInput()
        {
            // Mouse movement velocity
            //if (cardTilt) TiltCard();

            // Check if mouse is inside hand bounds
            CheckMouseInsideHandBounds();
            
            if (Input.GetMouseButtonDown(0))
            {
                initialMousePosition = Input.mousePosition;
                isClick = true; // Reset isClick state at the start of a new input
            }
        }

        private async void HandleCardsInHand()
        {
            if(!Active) return;
            
            var cardCount = hand.Count;
            for (var i = 0; i < cardCount; i++)
            {
                var card = hand[i];
                var cardTransform = card.GetComponent<RectTransform>();
                var isCardSelected = selectedCardIndex == i;
                
                var noDraggedCardOutsideHand = draggedCardOutsideHand == null; // Whether a card is "held" (outside of hand)
                var onSelectedCard = noDraggedCardOutsideHand && selectedCardIndex == i;
                var onDraggedInsideHand = noDraggedCardOutsideHand && draggedCardInsideHandIndex == i;

                var t = (cardCount > 1 ? (float)i / (cardCount - 1) : 0.5f);
                var p = GetCurvePoint(_a, _b, _c, t);
                
                var isMouseHoveringOnSelected =
                    isCardSelected && card.mouseHovering && _mouseInsideHand; //  && mouseInsideHand

                // Handle Card Position & Rotation
                //Vector3 cardUp = p - (transform.position + Vector3.down * 7);
                var cardUp = GetCurveNormal(_a, _b, _c, t);
                //var cardPos = p + (mouseHoveringOnSelected ? cardTransform.up * 0.3f : Vector3.zero);
                var cardForward = Vector3.forward;

                var cardPos = p;

                if (isMouseHoveringOnSelected)
                {
                    cardTransform.localScale = Vector3.one * 1.2f;
                    cardPos.y = 120f;
                    
                    if (!card.hoverSoundPlayed)
                    {
                        hoverSound?.PlayFeedbacks(); // Activar el sonido de hover
                        card.hoverSoundPlayed = true; // Marcar como sonido de hover reproducido
                    }
                    
                }
                else
                {
                    cardTransform.localScale = Vector3.one;
                    card.hoverSoundPlayed = false;
                }

                if (isMouseHoveringOnSelected)
                {
                    // When selected bring card to front
                    if (cardUprightWhenSelected) cardUp = Vector3.up;
                    cardTransform.SetAsLastSibling();
                }
                else
                {
                    cardTransform.SetSiblingIndex(i);
                }
                // Rotation
                cardTransform.rotation = Quaternion.RotateTowards(cardTransform.rotation,
                    Quaternion.LookRotation(cardForward, cardUp), 80f * Time.unscaledDeltaTime);
                
                
                RectTransformUtility.ScreenPointToLocalPointInRectangle(
                    canvasRectTransform,
                    Input.mousePosition,
                    null,
                    out Vector2 canvasPosition);
                
                // Handle Start Dragging
                if (isMouseHoveringOnSelected)
                {
                    
                    if (Input.GetMouseButtonUp(0) && !card.Disabled)
                    {
                        if (IsClick())
                        {
                            Active = false;
                            RemoveCardFromHand(i);
                            await card.ActivateCard();
                            card.Discard();
                            break;
                        }
                    }
                    else if (Input.GetMouseButtonDown(0) && !card.Disabled)
                    {
                        draggedCardInsideHandIndex = i;
                        isDragging = true;
                        _heldCardOffset = cardTransform.localPosition - new Vector3(canvasPosition.x, canvasPosition.y);
                    }
                    else if (Input.GetMouseButtonUp(0) && card.Disabled)
                    {
                        notEnoughResources.GetComponent<UIDisableAfterTime>().ActivateAndDisableAfterTime();
                    }
                
                }


                if (onDraggedInsideHand && Input.GetMouseButton(0) && !card.Disabled)
                {
                    if (GetMouseDragDistance() > dragThreshold)
                    {
                        isClick = false;
                    }
                    
                    // Held by mouse / dragging
                    cardPos = new Vector3(canvasPosition.x, canvasPosition.y) + _heldCardOffset;
                    cardTransform.localPosition = cardPos;
                }
                else if(noDraggedCardOutsideHand)
                {
                    cardPos = Vector3.MoveTowards(cardTransform.localPosition, cardPos, 1500f * Time.unscaledDeltaTime);
                    cardTransform.localPosition = cardPos;
                }
                
                

                if (_mouseInsideHand)
                {
                    if (card.mouseHovering)
                    {
                        selectedCardIndex = i;
                    }
                }
                else
                {
                    selectedCardIndex = -1;
                }

                
            }
        }
        
        private float GetMouseDragDistance()
        {
            return Vector3.Distance(initialMousePosition, Input.mousePosition);
        }
        
        private bool IsClick()
        {
            return GetMouseDragDistance() <= dragThreshold;
        }

        private async void HandleDraggedCardOutsideHand()
        {
            if (draggedCardOutsideHand != null)
            {
                var cardTransform = draggedCardOutsideHand.GetComponent<RectTransform>();
                var cardUp = Vector3.up;

                RectTransformUtility.ScreenPointToLocalPointInRectangle(
                    canvasRectTransform,
                    Input.mousePosition,
                    null,
                    out Vector2 canvasPosition);

                var cardPos = new Vector3(canvasPosition.x, canvasPosition.y) + _heldCardOffset;
                var cardForward = Vector3.forward;

                // Bring card to front
                cardPos.z = transform.position.z - 0.2f;

                // Handle Position & Rotation
                cardTransform.rotation = Quaternion.RotateTowards(cardTransform.rotation,
                    Quaternion.LookRotation(cardForward, cardUp), 80f * Time.deltaTime);
                cardTransform.localPosition = cardPos;
                
                var mouseButtonUp = !Input.GetMouseButton(0);
                
                if (!mouseButtonUp) return;
                
                CardBase card = cardTransform.gameObject.GetComponent<CardBase>();
                draggedCardOutsideHand = null;
                isDragging = false;

                if (_mouseInsideHand)
                {
                    AddCardToHand(card, draggedCardOutsideHandIndex);
                    
                    return;
                }

                Active = false;
                await card.ActivateCard();
                card.Discard();
            }
        }

        private void HandleDraggedCardInsideHand()
        {
            var mouseButton = Input.GetMouseButton(0);
            if (!mouseButton)
            {
                // Stop dragging
                _heldCardOffset = Vector3.zero;
                draggedCardInsideHandIndex = -1;
                isDragging = false;
            }

            if (draggedCardInsideHandIndex != -1)
            {
                var card = hand[draggedCardInsideHandIndex];
                if (mouseButton && !_mouseInsideHand)
                {
                    //  && sqrDistance > 2.1f
                    //if (cardPos.y > transform.position.y + 0.5) {
                    // Card is outside of the hand, so is considered "held" ready to be used
                    // Remove from hand, so that cards in hand fill the hole that the card left
                    draggedCardOutsideHand = card;
                    RemoveCardFromHand(draggedCardInsideHandIndex);
                    draggedCardOutsideHandIndex = draggedCardInsideHandIndex;
                    draggedCardInsideHandIndex = -1;
                }
            }

            if (draggedCardOutsideHand == null && mouseButton && draggedCardInsideHandIndex != -1 && selectedCardIndex != -1 && draggedCardInsideHandIndex != selectedCardIndex)
            {
                // Move dragged card
                MoveCardToIndex(draggedCardInsideHandIndex, selectedCardIndex);
                draggedCardInsideHandIndex = selectedCardIndex;
            }
        }

        private void CheckMouseInsideHandBounds()
        {
            Vector2 mousePosition = Input.mousePosition;
            _mouseInsideHand = RectTransformUtility.RectangleContainsScreenPoint(targetRectTransform, mousePosition);
        }
        

        

        #endregion

        #region Cyan Methods

        /// <summary>
        /// Obtains a point along a curve based on 3 points. Equal to Lerp(Lerp(a, b, t), Lerp(b, c, t), t).
        /// </summary>
        public static Vector3 GetCurvePoint(Vector3 a, Vector3 b, Vector3 c, float t)
        {
            t = Mathf.Clamp01(t);
            float oneMinusT = 1f - t;
            return (oneMinusT * oneMinusT * a) + (2f * oneMinusT * t * b) + (t * t * c);
        }

        /// <summary>
        /// Obtains the derivative of the curve (tangent)
        /// </summary>
        public static Vector3 GetCurveTangent(Vector3 a, Vector3 b, Vector3 c, float t)
        {
            return 2f * (1f - t) * (b - a) + 2f * t * (c - b);
        }

        /// <summary>
        /// Obtains a direction perpendicular to the tangent of the curve
        /// </summary>
        public static Vector3 GetCurveNormal(Vector3 a, Vector3 b, Vector3 c, float t)
        {
            Vector3 tangent = GetCurveTangent(a, b, c, t);
            return Vector3.Cross(tangent, Vector3.forward);
        }

        /// <summary>
        /// Moves the card in hand from the currentIndex to the toIndex. If you want to move a card that isn't in hand, use AddCardToHand
        /// </summary>
        public void MoveCardToIndex(int currentIndex, int toIndex)
        {
            if (currentIndex == toIndex) return; // Same index, do nothing
            CardBase card = hand[currentIndex];
            hand.RemoveAt(currentIndex);
            hand.Insert(toIndex, card);

            if (updateHierarchyOrder)
            {
                card.transform.SetSiblingIndex(toIndex);
            }
        }

        /// <summary>
        /// Adds a card to the hand. Optional param to insert it at a given index.
        /// </summary>
        public void AddCardToHand(CardBase card, int index = -1)
        {
            if (index < 0)
            {
                // Add to end
                hand.Add(card);
                index = hand.Count - 1;
            }
            else
            {
                // Insert at index
                hand.Insert(index, card);
            }

            if (updateHierarchyOrder)
            {
                card.transform.SetParent(transform);
                card.transform.SetSiblingIndex(index);
            }
        }

        /// <summary>
        /// Remove the card at the specified index from the hand.
        /// </summary>
        public void RemoveCardFromHand(int index)
        {
            if (updateHierarchyOrder)
            {
                CardBase card = hand[index];
                card.transform.SetSiblingIndex(transform.GetSiblingIndex() + 1);
            }

            hand.RemoveAt(index);
        }
        
        public void ClearHand()
        {
            for (int i = 0; i < hand.Count; i++)
            {
                (hand[i]).Discard();
            }
            hand.Clear();
        }

        #endregion

        #region Editor
#if UNITY_EDITOR
        private void OnDrawGizmos()
        {
            Gizmos.color = Color.blue;

            rectTransform = GetComponent<RectTransform>();

            var transformPointStart = rectTransform.TransformPoint(new Vector3(rectTransform.rect.center.x, rectTransform.rect.center.y, 0) +
                                                              curveStart);
            Gizmos.DrawSphere(transformPointStart, 20f);
            //Gizmos.DrawSphere(Vector3.zero, 0.03f);
            var transformPointEnd = rectTransform.TransformPoint(new Vector3(rectTransform.rect.center.x, rectTransform.rect.center.y, 0) +
                                                              curveEnd);
            Gizmos.DrawSphere(transformPointEnd, 20f);

            Vector3 p1 = transformPointStart;
            for (int i = 0; i < 20; i++)
            {
                float t = (i + 1) / 20f;
                Vector3 p2 = GetCurvePoint(transformPointStart,
                    rectTransform.TransformPoint(new Vector3(rectTransform.rect.center.x, rectTransform.rect.center.y,
                        0)), transformPointEnd, t);
                Gizmos.DrawLine(p1, p2);
                p1 = p2;
            }

            if (_mouseInsideHand)
            {
                Gizmos.color = Color.red;
            }

            Gizmos.DrawWireCube(
                rectTransform.TransformPoint(new Vector3(rectTransform.rect.center.x, rectTransform.rect.center.y, 0)),
                targetRectTransform.sizeDelta);
        }
#endif

        #endregion

    }
}