protected override void OnConfigureAI()
    {
        base.OnConfigureAI();

        GameObject topLeft     = GameObject.Find(s_TopLeft_Corner);
        GameObject bottomRight = GameObject.Find(s_BottomRight_Corner);

        GameObject midfield = GameObject.Find(s_Midfield);

        GameObject goalTop    = GameObject.Find(s_GoalTop);
        GameObject goalBottom = GameObject.Find(s_GoalBottom);

        GameObject areaTop    = GameObject.Find(s_AreaTop);
        GameObject areaBottom = GameObject.Find(s_AreaBottom);

        for (int aiTeamIndex = 0; aiTeamIndex < teamsCount; ++aiTeamIndex)
        {
            int aiCount = GetAICount(aiTeamIndex);

            for (int aiIndex = 0; aiIndex < aiCount; ++aiIndex)
            {
                tnBaseAIInputFiller aiInputFiller = (tnBaseAIInputFiller)GetAI(aiTeamIndex, aiIndex);

                if (aiInputFiller != null)
                {
                    tnBaseAIData aiData = new tnBaseAIData();

                    // Fill teammates and opponents.

                    {
                        for (int teamIndex = 0; teamIndex < teamsCount; ++teamIndex)
                        {
                            int teamSize = GetTeamSize(teamIndex);

                            for (int characterIndex = 0; characterIndex < teamSize; ++characterIndex)
                            {
                                GameObject characterInstance = GetCharacter(teamIndex, characterIndex);
                                if (characterInstance != null)
                                {
                                    if (teamIndex == aiTeamIndex) // Teammate.
                                    {
                                        aiData.AddMyTeamCharacter(characterInstance.transform);
                                    }
                                    else // Opponent.
                                    {
                                        aiData.AddOpponentTeamCharacter(characterInstance.transform);
                                    }
                                }
                            }
                        }
                    }

                    // Fill ball.

                    if (m_Ball != null)
                    {
                        aiData.SetBall(m_Ball.transform);
                    }

                    // Fill goal.

                    if (m_Goals != null)
                    {
                        if (aiTeamIndex < m_Goals.Count)
                        {
                            tnGoal goal = m_Goals[aiTeamIndex];
                            aiData.SetGoal(goal.transform);
                        }
                    }

                    // Fill opponent goal.

                    if (m_Goals != null)
                    {
                        for (int teamIndex = 0; teamIndex < teamsCount; ++teamIndex)
                        {
                            if (teamIndex == aiTeamIndex)
                            {
                                continue;
                            }

                            if (teamIndex < m_Goals.Count)
                            {
                                tnGoal goal = m_Goals[teamIndex];
                                aiData.SetOpponentGoal(goal.transform);

                                break; // NOTE: Only the first opponent goal will be linked to the AI.
                            }
                        }
                    }

                    // Fill reference position.

                    {
                        Vector3 selfPosition = aiInputFiller.self.transform.position;
                        aiData.SetReferencePosition(selfPosition);
                    }

                    // Anchors.

                    {
                        if (topLeft != null)
                        {
                            aiData.SetTopLeftAnchor(topLeft.transform);
                        }

                        if (bottomRight != null)
                        {
                            aiData.SetBottomRightAnchor(bottomRight.transform);
                        }

                        if (midfield != null)
                        {
                            aiData.SetMidfieldAnchor(midfield.transform);
                        }

                        if (goalTop != null)
                        {
                            aiData.SetGoalTop(goalTop.transform);
                        }

                        if (goalBottom != null)
                        {
                            aiData.SetGoalBottom(goalBottom.transform);
                        }

                        if (areaTop != null)
                        {
                            aiData.SetAreaTop(areaTop.transform);
                        }

                        if (areaBottom != null)
                        {
                            aiData.SetAreaBottom(areaBottom.transform);
                        }
                    }

                    aiInputFiller.Setup(aiData);
                }
            }
        }
    }
    // BUSINESS LOGIC

    public void Setup(tnBaseAIData i_Data)
    {
        if (i_Data == null)
        {
            return;
        }

        bool errorOccurred = false;

        // Team.

        {
            int teamCharactersCount = i_Data.myTeamCharactersCount;

            for (int index = 0; index < teamCharactersCount; ++index)
            {
                Transform character = i_Data.GetMyTeamCharacter(index);

                if (character == null)
                {
                    continue;
                }

                m_Team.Add(character);
            }
        }

        // Teammates.

        {
            int teamCharactersCount = i_Data.myTeamCharactersCount;

            for (int index = 0; index < teamCharactersCount; ++index)
            {
                Transform character = i_Data.GetMyTeamCharacter(index);

                if (character == null)
                {
                    continue;
                }

                if (character.gameObject != self)
                {
                    m_Teammates.Add(character);
                }
            }
        }

        // Opponents.

        {
            int opponentsCount = i_Data.opponentTeamCharactersCount;

            for (int opponentIndex = 0; opponentIndex < opponentsCount; ++opponentIndex)
            {
                Transform opponent = i_Data.GetOpponentTeamCharacter(opponentIndex);

                if (opponent == null)
                {
                    continue;
                }

                m_Opponents.Add(opponent);
            }
        }

        // Ball.

        {
            m_Ball = i_Data.ball;

            if (m_Ball == null)
            {
                errorOccurred |= true;
            }
            else
            {
                // Init ball radius.

                /*
                 *
                 * CircleCollider2D ballCollider = m_Ball.GetComponent<CircleCollider2D>();
                 * if (ballCollider == null)
                 * {
                 *  errorOccurred |= true;
                 * }
                 * else
                 * {
                 *  m_BallRadius = ballCollider.radius;
                 * }
                 *
                 */

                m_BallRadius = 0.25f;

                // Apply object scale, assuming that it is uniform.

                m_BallRadius *= m_Ball.transform.localScale.x;
            }
        }

        // Goal.

        {
            m_MyGoal = i_Data.goal;

            if (m_MyGoal == null)
            {
                errorOccurred |= true;
            }
        }

        // Opponent goal.

        {
            m_OpponentGoal = i_Data.opponentGoal;

            if (m_OpponentGoal == null)
            {
                errorOccurred |= true;
            }
        }

        // Reference position.

        {
            m_ReferencePosition = i_Data.referencePosition;
        }

        // Anchors.

        {
            m_TopLeft     = i_Data.topLeftAnchor;
            m_BottomRight = i_Data.bottomRightAnchor;

            if (m_TopLeft == null || m_BottomRight == null)
            {
                errorOccurred |= true;
            }
        }

        {
            m_Midfield = i_Data.midfieldAnchor;

            if (m_Midfield == null)
            {
                errorOccurred |= true;
            }
        }

        // Goal width.

        {
            Transform goalTop    = i_Data.goalTop;
            Transform goalBottom = i_Data.goalBottom;

            if (goalTop == null || goalBottom == null)
            {
                errorOccurred |= true;
            }
            else
            {
                m_GoalMinHeight = goalBottom.position.y;
                m_GoalMaxHeight = goalTop.position.y;

                m_GoalWidth = goalTop.position.y - goalBottom.position.y;
            }
        }

        // Area size.

        {
            Transform topLeftAnchor = i_Data.topLeftAnchor;

            Transform areaTop    = i_Data.areaTop;
            Transform areaBottom = i_Data.areaBottom;

            if (areaTop == null || areaBottom == null || topLeftAnchor == null)
            {
                errorOccurred |= true;
            }
            else
            {
                m_GKAreaMinHeight = areaBottom.position.y;
                m_GKAreaMaxHeight = areaTop.position.y;

                m_GKAreaWidth  = areaTop.position.x - topLeftAnchor.position.x;
                m_GKAreaHeight = areaTop.position.y - areaBottom.position.y;
            }
        }

        if (errorOccurred)
        {
            Debug.LogError("[AI]" + "[" + self.name + "]" + " " + "Initialization failed.");
        }

        m_Initialized = !errorOccurred;
    }