/// <summary>
        /// запустить взрыв шаров одного и того же типа
        /// </summary>
        /// <param name="startBall"></param>
        public void StartPopSequence(BallConnected startBall)
        {
            HashSet <BallConnected> ballsToPop = new HashSet <BallConnected>();

            //находим все шары, которые надо лопнуть
            foreach (var ball in GetConnectedBlockSameType(startBall, null))
            {
                ballsToPop.Add(ball);
            }

            if (ballsToPop.Count > 1)
            {
                //лопаем шары
                foreach (var ball in ballsToPop)
                {
                    if (allBalls.Values.Contains(ball))
                    {
                        ball.PopBall();
                        RemoveBall(ball);
                    }
                }
                DropUnHangBalls();
            }
            else
            {
                startBall.HangUp();
            }
        }
        /// <summary>
        /// Все шары того же типа, что и стартовый, до которых можно дойти.
        /// </summary>
        /// <param name="startBall">Начальный шар</param>
        /// <param name="checkedBalls"></param>
        /// <returns></returns>
        private HashSet <BallConnected> GetConnectedBlockSameType(BallConnected startBall, List <BallConnected> checkedBalls)
        {
            if (checkedBalls == null)
            {
                checkedBalls = new List <BallConnected>();
            }
            var connected = new HashSet <BallConnected>();

            checkedBalls.Add(startBall);

            foreach (var checkBall in FindNeighboors(startBall.GridPos))
            {
                if (checkedBalls.Contains(checkBall))
                {
                    continue;
                }
                if (checkBall.Type == startBall.Type)
                {
                    var subconnected = GetConnectedBlockSameType(checkBall, checkedBalls);
                    foreach (var ball in subconnected)
                    {
                        connected.Add(ball);
                    }
                }
                checkedBalls.Add(checkBall);
            }

            connected.Add(startBall);

            return(connected);
        }
        /// <summary>
        /// поставить шар на поле
        /// </summary>
        /// <param name="toBall"></param>
        /// <param name="atPosition"></param>
        /// <param name="type"></param>
        public void ConnectBall(BallConnected toBall, Vector2 atPosition, BallType type)
        {
            Vector2       ballPosition = toBall.transform.position;
            float         hitAngle     = Vector2.SignedAngle(Vector2.up, (ballPosition - atPosition).normalized);
            Vector2Int    gridPos      = GetNeighboorGridCellByAngle(toBall.GridPos, hitAngle);
            BallConnected newBall      = Instantiate(ballPref, GetOffsetByGridPos(gridPos),
                                                     Quaternion.identity, startSpawn);

            newBall.ChangeType(type);
            newBall.SetOnGrid(gridPos);
            allBalls.Add(gridPos, newBall);
            StartPopSequence(newBall);
            _gameController.LoadBall();
        }
        /// <summary>
        /// Пробить шар насквозь и занять его место
        /// </summary>
        /// <param name="ballConnected"></param>
        public void SmackBall(BallConnected ballConnected, BallType newType)
        {
            ballConnected.PopBall();
            RemoveBall(ballConnected);

            BallConnected newBall = Instantiate(ballPref, GetOffsetByGridPos(ballConnected.GridPos),
                                                Quaternion.identity, startSpawn);

            newBall.ChangeType(newType);
            newBall.SetOnGrid(ballConnected.GridPos);
            allBalls.Add(ballConnected.GridPos, newBall);

            StartPopSequence(newBall);
            _gameController.LoadBall();
        }
        /// <summary>
        /// Создать поле шаров
        /// </summary>
        /// <returns></returns>
        public Dictionary <Vector2Int, BallConnected> GenerateBalls()
        {
            allBalls = new Dictionary <Vector2Int, BallConnected>();
            var           textFile = Resources.Load <TextAsset>(levelName);
            List <string> lines    = new List <string>(textFile.text.Split('\n'));

            for (int l = 0; l < lines.Count; l++)
            {
                string line = lines[l];
                for (int i = 0; i < line.Length; i++)
                {
                    if (Char.GetNumericValue(line[i]) >= 0)
                    {
                        BallConnected newBall = Instantiate(ballPref, GetOffsetByGridPos(new Vector2Int(i, l)), Quaternion.identity, startSpawn);
                        newBall.name = i + "," + l;
                        Vector2Int gridPos = new Vector2Int(i, l);
                        newBall.SetOnGrid(gridPos);
                        if (l == 0)
                        {
                            newBall.HangUp();
                            minHangBalls++;
                        }
                        newBall.ChangeType(loadBallTypes[Int32.Parse(line[i].ToString())]);
                        allBalls.Add(gridPos, newBall);
                    }
                }
            }

            foreach (var ball in allBalls)
            {
                if (FindNeighboors(ball.Value.GridPos).Any(b => b.Hanging))
                {
                    ball.Value.HangUp();
                }
            }

            minHangBalls *= 0.3f;
            return(allBalls);
        }
 private void RemoveBall(BallConnected theBall)
 {
     allBalls.Remove(theBall.GridPos);
 }