У меня есть игра на юнити, как сделать чтобы на гем можно было нажимать только после выполнения полной анимации(SwapGemsSmoothly) using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using Unity.VisualScripting;
using UnityEngine;

public class Gem : MonoBehaviour
{
    [SerializeField] private SceneController controller;

    private int _id;
    public int id => _id;

    // private static Gem _firstGem;
    // private static Gem _secondGem;

    private int _orderNum;


    public int orderNum
    {
        get => _orderNum;
        set => _orderNum = value;
    }

    // //Создания массива, состоящего из массивов нелегальных пар(которые не могут менятся друг с другом(так как не являются соседями)
    // private int[][] illegalPairs = new int[3][];

    public void Awake()
    {
        controller = FindObjectOfType<SceneController>();
    }


    // public void OnMouseDown()
    // {
    //     // GetComponent<SpriteRenderer>().color = Color.black;
    //     if (_firstGem == null)
    //     {
    //         _firstGem = this;
    //         GetComponent<SpriteRenderer>().color = Color.gray;
    //
    //         Debug.Log($"Order num: {_firstGem._orderNum}");
    //         Debug.Log($"Order id: {_firstGem.id}");
    //         
    //         
    //     }
    //     
    //     else 
    //     {
    //         _secondGem = this;
    //         SwapGems(_firstGem, _secondGem);
    //     
    //         _firstGem.GetComponent<SpriteRenderer>().color = Color.white;
    //         
    //         _firstGem = null;
    //         _secondGem = null;
    //         
    //         
    //     
    //     }
    // }

    public void OnMouseDown()
    {
        controller.ClickOnGem(this);
        Debug.Log($"Click! id: {this.id}, orderNum: {this.orderNum}");
        Debug.Log(controller.IsGameWon());
    }


    public void SetGem(int startPosition, Sprite image)
    {
        _id = startPosition;
        _orderNum = startPosition;
        GetComponent<SpriteRenderer>().sprite = image;
    }


    // private void SwapGems(Gem gem1, Gem gem2)
    // {
    //     if (gem1.id == 15 || gem2.id == 15)
    //     {
    //         if (Math.Abs(_firstGem.orderNum - _secondGem.orderNum) == 1 ||
    //             Math.Abs(_firstGem.orderNum - _secondGem.orderNum) == 4)
    //         {
    //             int[] orderNumArray = { _firstGem.orderNum, _secondGem.orderNum };
    //             Array.Sort(orderNumArray);
    //
    //             if (!illegalPairs.Any(pair => pair.SequenceEqual(orderNumArray)))
    //             {
    //                 SwapGemsWithOrder(gem1, gem2);
    //                 // Vector3 firstPos = gem1.transform.position;
    //                 // Vector2 secondPos = gem2.transform.position;
    //                 //
    //                 //
    //                 // int tempOrderNum = _firstGem.orderNum;
    //                 // int secondTilePrevOrderNum = _secondGem.orderNum;
    //                 //
    //                 //
    //                 // gem1.transform.position = secondPos;
    //                 // gem2.transform.position = firstPos;
    //                 //
    //                 // // Обновить значения orderNum после переставления gems
    //                 // _firstGem.orderNum = secondTilePrevOrderNum;
    //                 // _secondGem.orderNum = tempOrderNum;
    //                 
    //             }
    //
    //         }
    //         
    //     }
    // }
    //
    // public void SwapGemsWithOrder(Gem firstGem, Gem secondGem)
    // {
    //     Vector3 firstPos = firstGem.transform.position;
    //     Vector2 secondPos = secondGem.transform.position;
    //
    //     int tempOrderNum = _firstGem.orderNum;
    //     int secondTilePrevOrderNum = _secondGem.orderNum;
    //
    //     firstGem.transform.position = secondPos;
    //     secondGem.transform.position = firstPos;
    //                 
    //     // Обновить значения orderNum после переставления gems
    //     _firstGem.orderNum = secondTilePrevOrderNum;
    //     _secondGem.orderNum = tempOrderNum;
    // }
    //
    // // public bool IsGameWon(Gem[] gems)
    // // {
    // //     return gems.All(gem => gem.id == gem.orderNum);
    // // }
}using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using Unity.VisualScripting;
using UnityEngine;
using Random = UnityEngine.Random;


public class ShuffleScript : MonoBehaviour
{
    [SerializeField] private SceneController controller;
    
    
    [SerializeField] private float delay;
    [SerializeField] private int numOfIterations;
        
    private Gem[] _gems;

    private readonly Dictionary<int, int[]> _puzzleGraph = new Dictionary<int, int[]>();


    public void Start()
    {
        _gems = controller.GetGemsArray();
        FillPuzzleGraph();
    }

    private void OnMouseDown()
    {
        // Debug.Log((GetGemById(15, _gems).id));

        // Debug.Log($"Соседи 15: {string.Join(" ", _puzzleGraph[15])} ");
        // Debug.Log($"16-ая ячейка: orderNum:{_gems[15].orderNum} / id:{_gems[15].id}");

        Debug.Log($"Id: {_gems[15].id}\n" +
                  $"OrderNum: {_gems[15].orderNum}");

        StartCoroutine(ShuffleGemsWithDelay(delay, numOfIterations));
        
        Debug.Log(controller.IsGameWon());
    }
    


    private void ShuffleGems()
    {
        Gem gem16 = _gems[15];
        int gemCurrentOrder = gem16.orderNum;
        

        //Находим соседние клетки, после чего выбираем случайную соседнюю клетку
        int[] gemNeighbors = _puzzleGraph[gemCurrentOrder];
        int randomOrder = Random.Range(0, gemNeighbors.Length);
        int randomNeighborOrder = gemNeighbors[randomOrder];
        Gem randomGem = GetGemByOrder(randomNeighborOrder);
       
     
        // Debug.Log($"Random Neighbor: {randomNeighbor}");

        
        Vector3 firstPos = gem16.transform.position;
        Vector2 secondPos = randomGem.transform.position;
        
        int tempOrderNum = gem16.orderNum;
        int secondTilePrevOrderNum = randomGem.orderNum;
        
        gem16.transform.position = secondPos;
        randomGem.transform.position = firstPos;
        
        // Обновить значения orderNum после перестановки gems

        gem16.orderNum = secondTilePrevOrderNum;
        randomGem.orderNum = tempOrderNum;
        
        


        // Debug.Log($"Черный гем id: {gem16.id}\n " +
        //           $"orderNum: {gem16.orderNum}\n" +
        //           $"id: {_gems[15].id}" +
        //           $"orderNum {_gems[15].orderNum}"
        //
        // );
    }

    private IEnumerator ShuffleGemsWithDelay(float delayNum, int num)
    {
        // yield return new WaitForSeconds(delay);

        for (int i = 0; i < num; i++)
        {
            ShuffleGems();
            yield return new WaitForSeconds(delayNum);
        }
    }


    private Gem GetGemByOrder(int orderNum)
    {
        Gem gemWithOrder = _gems.FirstOrDefault(gem => gem.orderNum == orderNum);

        return gemWithOrder;
    }


    //Функция, для заполнения словаря.
    void FillPuzzleGraph()
    {
        _puzzleGraph.Add(0, new[] { 1, 4 });
        _puzzleGraph.Add(1, new[] { 0, 2, 5 });
        _puzzleGraph.Add(2, new[] { 1, 3, 6 });
        _puzzleGraph.Add(3, new[] { 2, 7 });
        _puzzleGraph.Add(4, new[] { 0, 5, 8 });
        _puzzleGraph.Add(5, new[] { 1, 4, 6, 9 });
        _puzzleGraph.Add(6, new[] { 2, 5, 7, 10 });
        _puzzleGraph.Add(7, new[] { 3, 6, 11 });
        _puzzleGraph.Add(8, new[] { 4, 9, 12 });
        _puzzleGraph.Add(9, new[] { 5, 8, 10, 13 });
        _puzzleGraph.Add(10, new[] { 6, 9, 11, 14 });
        _puzzleGraph.Add(11, new[] { 7, 10, 15 });
        _puzzleGraph.Add(12, new[] { 8, 13 });
        _puzzleGraph.Add(13, new[] { 9, 12, 14 });
        _puzzleGraph.Add(14, new[] { 10, 13, 15 });
        _puzzleGraph.Add(15, new[] { 11, 14 });
    }

}using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;

public class SceneController : MonoBehaviour
{
    public const int GridRows = 4;
    public const int GridCols = 4;

    public const float OffsetX = 2f;
    public const float OffsetY = 2.5f;

    [SerializeField] private Gem originalGem;
    [SerializeField] private Sprite[] images;

    private int GemNum = 0;

    private Gem _firstGem;
    private Gem _secondGem;

    private Gem _emptyGem;

    private Gem[] _gems; // Поле класса для хранения массива гемов


    //Создания массива, состоящего из массивов нелегальных пар(которые не могут менятся друг с другом(так как не являются соседями)
    private int[][] illegalPairs = new int[3][];


    public Gem[] GemsArray
    {
        get => _gems;
        set => _gems = value;
    }


    private void Awake()
    {
        //Заполнение массива нелегальных пар
        illegalPairs[0] = new int[] { 3, 4 };
        illegalPairs[1] = new int[] { 7, 8 };
        illegalPairs[2] = new int[] { 11, 12 };


        Vector3 startPos = originalGem.transform.position;
        _gems = new Gem[GridRows * GridCols]; // Инициализируем массив гемов


        for (int i = 0; i < GridRows; i++)
        {
            for (int j = 0; j < GridCols; j++)
            {
                // Gem gem;
                Gem gem = Instantiate(originalGem) as Gem;

                gem.SetGem(GemNum, images[GemNum]);

                // gem = Instantiate(originalGem) as Gem;


                float posX = (OffsetX * j) + startPos.x;
                float posY = -(OffsetY * i) + startPos.y;
                gem.transform.position = new Vector3(posX, posY, startPos.z);

                _gems[(i * GridCols) + j] = gem; // Добавляем гем в массив


                GemNum++;
            }
        }

        _emptyGem = _gems[15];
    }

    // public Gem[] GetGemsArray()
    // {
    //     Gem[] gems = FindObjectsOfType<Gem>();
    //     return gems;
    //     
    //     // foreach (Gem gem in gems)
    //     // {
    //     //     if (gem.id == targetId)
    //     //     {
    //     //         return gem;
    //     //     }
    //     // }
    //     //
    //     // return null; // Объект с указанным id не найден
    // }

    // public void ClickOnGem(Gem gem)
    // {
    //     if (_firstGem == null)
    //     {
    //         _firstGem = gem;
    //
    //         Debug.Log("1st if");
    //
    //         // _firstGem.GetComponent<SpriteRenderer>().color = Color.gray;
    //     }
    //     else
    //     {
    //         _secondGem = gem;
    //         SwapGems(_firstGem, _secondGem);
    //
    //         // _firstGem.GetComponent<SpriteRenderer>().color = Color.white;
    //
    //         _firstGem = null;
    //         _secondGem = null;
    //
    //         Debug.Log("2st if");
    //     }
    // }

    public void ClickOnGem(Gem gem)
    {
        if (Math.Abs(gem.orderNum - _emptyGem.orderNum) == 1 ||
            Math.Abs(gem.orderNum - _emptyGem.orderNum) == 4)
        {
            int[] orderNumArray = { gem.orderNum, _emptyGem.orderNum };
            Array.Sort(orderNumArray);
            if (!illegalPairs.Any(pair => pair.SequenceEqual(orderNumArray)))
            {
                // SwapGemsWithOrder(gem, _emptyGem);
                StartCoroutine(SwapGemsSmoothly(gem, _emptyGem));

            }
        }
    }

    // private void SwapGems(Gem gem1, Gem gem2)
    // {
    //     // if (gem1.id == 15 || gem2.id == 15)
    //     // {
    //     if (Math.Abs(_firstGem.orderNum - _secondGem.orderNum) == 1 ||
    //         Math.Abs(_firstGem.orderNum - _secondGem.orderNum) == 4)
    //     {
    //         int[] orderNumArray = { _firstGem.orderNum, _secondGem.orderNum };
    //         Array.Sort(orderNumArray);
    //
    //         if (!illegalPairs.Any(pair => pair.SequenceEqual(orderNumArray)))
    //         {
    //             SwapGemsWithOrder(gem1, gem2);
    //         }
    //     }
    //
    //     // }
    // }


    public void SwapGemsWithOrder(Gem firstGem, Gem secondGem)
    {
        Vector3 firstPos = firstGem.transform.position;
        Vector2 secondPos = secondGem.transform.position;

        int tempOrderNum = firstGem.orderNum;
        int secondTilePrevOrderNum = secondGem.orderNum;

        firstGem.transform.position = secondPos;
        secondGem.transform.position = firstPos;

        // Обновить значения orderNum после переставления gems
        firstGem.orderNum = secondTilePrevOrderNum;
        secondGem.orderNum = tempOrderNum;
    }

    IEnumerator SwapGemsSmoothly(Gem firstGem, Gem secondGem)
    {
        Vector3 initialPosition1 = firstGem.transform.position;
        Vector3 initialPosition2 = secondGem.transform.position;

        Vector3 targetPosition1 = secondGem.transform.position;
        Vector3 targetPosition2 = firstGem.transform.position;
        
        int tempOrderNum = firstGem.orderNum;
        int secondTilePrevOrderNum = secondGem.orderNum;

        float duration = 0.5f; // Время, которое займет анимация (можете настроить под свои предпочтения)

        float elapsedTime = 0f;

        while (elapsedTime < duration)
        {
            firstGem.transform.position = Vector3.Lerp(initialPosition1, targetPosition1, elapsedTime / duration);
            secondGem.transform.position = Vector3.Lerp(initialPosition2, targetPosition2, elapsedTime / duration);

            elapsedTime += Time.deltaTime;

            yield return null;
        }

        // Убедитесь, что обе позиции точно установлены на конечные значения, чтобы избежать погрешностей.
        firstGem.transform.position = targetPosition1;
        secondGem.transform.position = targetPosition2;

        // Обновить значения orderNum после переставления gems
        firstGem.orderNum = secondTilePrevOrderNum;
        secondGem.orderNum = tempOrderNum;

        
    }


    public Gem[] GetGemsArray()
    {
        return _gems; // Возвращаем сохраненный массив гемов
    }


    public bool IsGameWon()
    {
        return _gems.All(gem => gem.id == gem.orderNum);
    }
}