Задать вопрос
@Gioo12x

Как убрать проблему, из-за которой карта не возвращается в руку?

Кто-нибудь может подсказать, как исправить проблему: если карта не попадает в драг зону, она “залипает” и возвращается в руку только после того, как я беру новую карту или передвигаю её к краю стола?
Код карты:
using UnityEngine;
using UnityEngine.Rendering;

using DG.Tweening;
using NUnit.Framework;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine.Splines;
using UnityEngine.UIElements;
using TMPro;

public class Card : MonoBehaviour
{

    private HandManager handManager;
    private Collider2D col;
    private Vector3 starDragPosition;
    private Quaternion starDragRotation;
    public bool canDrag = true;
    private SortingGroup sortingGroup;
    private int defaultSorting;
  //  private bool isDragging = false;
    private Vector3 startScale;
    private int baseOrder;
    private clCard card;
    private ICardDropArea currentDropArea;
    public int Power => card != null ? card.Power : 0;



    private void Start()
    {
        col = GetComponent<Collider2D>();
        handManager = FindFirstObjectByType<HandManager>();

        // Сначала получаем компонент, потом используем
        sortingGroup = GetComponentInChildren<SortingGroup>();
        if (sortingGroup != null)
        {
            defaultSorting = sortingGroup.sortingOrder;
            baseOrder = sortingGroup.sortingOrder;
        }
    }
    private void OnMouseEnter()
    {

        transform.DOKill();

        starDragPosition = transform.position;
        starDragRotation = transform.rotation;
        startScale = transform.localScale;

        // увеличиваем
        transform.DOScale(startScale * 1.2f, 0.2f);

        // поворот в 0
        transform.DORotate(Vector3.zero, 0.2f);

        // делаем поверх всех

        sortingGroup.sortingOrder = 100;
    }

    private void OnMouseExit()
    {
        transform.DOKill();

        transform.rotation = starDragRotation;
        transform.DOScale(0.24f, 0.24f);

        sortingGroup.sortingOrder = baseOrder;


    }
    private void OnMouseDown()
    {
        if (!canDrag) return;
        starDragPosition = transform.position;
        transform.position = GetMousePositionInWorldSpace();
        starDragRotation = transform.rotation;
        transform.rotation = GetMouseRotationInWorldSpace();

    }

    private void OnMouseDrag()
    {
        if (!canDrag) return;

        transform.position = GetMousePositionInWorldSpace();
    }

    private void OnMouseUp()
    {
        if (!canDrag) return;

        Vector3 mousePos = GetMousePositionInWorldSpace();

        var hits = Physics2D.OverlapPointAll(mousePos);

        ICardDropArea foundArea = null;

        foreach (var hit in hits)
        {
            if (hit.gameObject == gameObject) continue;

            if (hit.TryGetComponent(out ICardDropArea area))
            {
                foundArea = area;
                break;
            }
        }

        if (foundArea != null)
        {
            foundArea.OnCardDrop(this);

            FieldManager field = FindFirstObjectByType<FieldManager>();
            field.fieldCards.Add(this);
            field.UpdateTotalPower();
        }
        else
        {
            // возврат в руку
            transform.position = starDragPosition;
            transform.rotation = starDragRotation;

            handManager.UpdateCardsPosition();
        }
    }


    Quaternion GetMouseRotationInWorldSpace()
    {
        Quaternion r = transform.rotation;
        r.z = 0;
        return r;
    }
    Vector3 GetMousePositionInWorldSpace()
    {
        Vector3 p = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        p.z = 0;
        return p;
    }
    public void RemoveCard()
    {
        handManager.handCards.Remove(gameObject);
        handManager.UpdateCardsPosition();
    }
    public void Init(clCard card)
    {
        this.card = card;
    }
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out ICardDropArea area))
        {
            currentDropArea = area;
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.TryGetComponent(out ICardDropArea area) && currentDropArea == area)
        {
            currentDropArea = null;
        }
    }
}

Код драг зоны:
using DG.Tweening;
using NUnit.Framework;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Splines;
using TMPro;

public class UpCardDropArea : MonoBehaviour, ICardDropArea
{
    [SerializeField] public int maxHandsSize;
    [SerializeField] public SplineContainer splineContainer;
    [SerializeField] float cardSpacing = 0.08f;
    private Collider2D col;
    private HandManager handManager;



    void Start()
    {
        col = GetComponent<Collider2D>();
    }

    // Start is called once before the first execution of Update after the MonoBehaviour is created
    public void OnCardDrop(Card card)
    {
        card.RemoveCard();

        card.transform.SetParent(transform); // ✅ лучше чем null

        handCards.Add(card.gameObject);

        card.canDrag = false;

        UpdateCardsPosition();

        if (handCards.Count >= maxHandsSize)
        {
            col.enabled = false;
        }
    }
    public List<GameObject> handCards = new();

    public void UpdateCardsPosition()

    {

        if (handCards.Count == 0) return;




        Spline spline = splineContainer.Spline;

        float start = 0.5f - (handCards.Count - 1) * cardSpacing / 2f;

        for (int i = 0; i < handCards.Count; i++)
        {
            float p = start + i * cardSpacing;

            Vector3 splinePosition = splineContainer.transform.TransformPoint(spline.EvaluatePosition(p));

            handCards[i].transform.DOMove(splinePosition, 0.4f);

            // фиксированный поворот (карта всегда ровная)
            handCards[i].transform.DORotate(Vector3.zero, 0.4f);
            SortingGroup sg = handCards[i].GetComponentInChildren<SortingGroup>();
            sg.sortingOrder = i;
        }
    }
}

Код руки:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Splines;


using DG.Tweening;


public class HandManager : MonoBehaviour
{
    [SerializeField] public int maxHandsSize;
    [SerializeField] public SplineContainer splineContainer;
    [SerializeField] public Transform spawnPoint;

    [SerializeField] public List<CardData> cardDatas;
    [SerializeField] private CardView cardViews;

    public int re = 10;

    private List<clCard> deck = new();
    public List<GameObject> handCards = new();

    void Start()
    {
        // создаём колоду
        for (int i = 0; i < re; i++)
        {
            CardData data = cardDatas[Random.Range(0, cardDatas.Count)];
            clCard card = new(data);
            deck.Add(card);
        }
    }
    void Update()
    {
      
    }

    public void DrawCard()
    {
        if (handCards.Count >= maxHandsSize) return;
        if (deck.Count == 0) return;

        // берём карту
        clCard drawnCard = deck[Random.Range(0, deck.Count)];
        deck.Remove(drawnCard);

        // создаём карту
        CardView view = Instantiate(cardViews, spawnPoint.position, spawnPoint.rotation);

        // настраиваем данные
        view.Setup(drawnCard);
       
        Card cardComponent = view.GetComponent<Card>();
        cardComponent.Init(drawnCard);

        // добавляем в руку
        handCards.Add(view.gameObject);

        UpdateCardsPosition();
    }

    public void UpdateCardsPosition()
    {
        if (handCards.Count == 0) return;

        float cardSpacing = 1f / maxHandsSize;
        float firstCardPosition = 0.5f - (handCards.Count - 1) * cardSpacing / 2;

        Spline spline = splineContainer.Spline;

        for (int i = 0; i < handCards.Count; i++)
        {
            float p = firstCardPosition + i * cardSpacing;

            Vector3 splinePosition = spline.EvaluatePosition(p);
            Vector3 forward = spline.EvaluateTangent(p);
            Vector3 up = spline.EvaluateUpVector(p);

            // Кватернион считается в мировом пространстве
            Quaternion rotation = Quaternion.LookRotation(up, Vector3.Cross(up, forward).normalized);

            // ИСПРАВЛЕНИЕ 1: используем DORotateQuaternion для мирового вращения
            handCards[i].transform.DOMove(splinePosition, 0.25f);
            handCards[i].transform.DORotateQuaternion(rotation, 0.25f);

            SortingGroup sg = handCards[i].GetComponentInChildren<SortingGroup>();
            sg.sortingOrder = i + 10;
        }
    }
}
  • Вопрос задан
  • 49 просмотров
Подписаться 1 Средний Комментировать
Помогут разобраться в теме Все курсы
  • Stepik
    PRO C#. Профессия "Backend разработчик"
    4 месяца
    Далее
  • Merion Academy
    C# разработчик с нуля
    4 месяца
    Далее
  • Skillfactory
    Профессия C#-разработчик
    12 месяцев
    Далее
Пригласить эксперта
Ответы на вопрос 1
opium
@opium
Просто люблю качественно работать
Судя по коду, у тебя во время драга стреляет OnMouseExit — курсор уходит за границу коллайдера карты, и он дёргает DOKill() плюс сбрасывает rotation и scale прямо посреди перетаскивания. Раскомментируй isDragging (он у тебя уже заготовлен), ставь true в OnMouseDown, false в OnMouseUp, а в OnMouseEnter и OnMouseExit первой строкой добавь if (isDragging) return;. Ну и если после этого всё равно не возвращается — проверь что в OnMouseUp ветка без drop зоны реально вызывает UpdateCardsPosition.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы