private void OnTriggerEnter(Collider otherCollider)
        {
            if (otherCollider.As <IUnitProperties>() == null)
            {
                return;
            }

            var unit = otherCollider.GetUnitFacade();

            if (unit == null)
            {
                return;
            }

            var grp = unit.transientGroup as DefaultSteeringTransientUnitGroup;

            float currentTime = Time.time;

            if (currentTime - _startTime < this.groupCreationTime)
            {
                if (grp == null)
                {
                    if (_group == null)
                    {
                        _group = new DefaultSteeringTransientUnitGroup(1);
                    }

                    _group.Add(unit);
                    StartCoroutine(DelayedMove());
                }
            }
            else
            {
                if (grp != null)
                {
                    if (++_groupCount >= grp.count + 1)
                    {
                        grp.MoveTo(moveToTarget, false);
                        _groupCount = 0;
                    }
                }
            }
        }
        private void Start()
        {
            for (int i = 0; i < spawnPoints.Length; i++)
            {
                var randomColor = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value);
                var grp         = new DefaultSteeringTransientUnitGroup(this.groupSize);
                for (int j = 0; j < this.groupSize; j++)
                {
                    var agent = Instantiate(this.agentMold, spawnPoints[i], Quaternion.identity) as GameObject;
                    agent.SetActive(true);
                    grp.Add(agent.GetUnitFacade());

                    var renderer = agent.GetComponent <Renderer>();
                    renderer.material.color = randomColor;
                }

                Vector3 lastPOI = _poiSource.GetPOI(Vector3.zero);
                for (int j = 0; j < waypointIterations; j++)
                {
                    grp.MoveTo(lastPOI, true);
                    lastPOI = _poiSource.GetPOI(lastPOI);
                }
            }
        }
        /// <summary>
        /// Handles portalling.
        /// </summary>
        /// <param name="unitData">This unit's UnitFacade.</param>
        /// <param name="group">This unit's current/old group.</param>
        /// <param name="vectorField">The vector field.</param>
        /// <param name="pathPortalIndex">Index of the portal in the current path.</param>
        /// <param name="grid">The grid.</param>
        private void HandlePortal(IUnitFacade unitData, DefaultSteeringTransientUnitGroup group, IVectorField vectorField, int pathPortalIndex, IGrid grid)
        {
            var portal = _currentPath[pathPortalIndex] as IPortalNode;

            if (portal == null)
            {
                // if the path node that was reported as a portal turns out not to be - return
                return;
            }

            if (object.ReferenceEquals(unitData, group.modelUnit))
            {
                // don't ever let model unit jump portal
                return;
            }

            int groupCount = group.count;
            var to         = _currentPath[pathPortalIndex + 1];

            // we consider a portal a "far portal" when the distance between it and its partner is more than the diagonal cell size
            // 'far portal' means that it is NOT considered a grid stitching connector portal
            // Requires that grid stitching portals are always placed adjacent to each other
            float portalNewGroupThreshold = (grid.cellSize * Consts.SquareRootTwo) + 0.1f;
            bool  isFarPortal             = (portal.position - portal.partner.position).sqrMagnitude > (portalNewGroupThreshold * portalNewGroupThreshold);

            if (isFarPortal)
            {
                // if it is a far portal, we need to make or use the next group
                if (group.nextGroup == null)
                {
                    // new group does not exist yet, so create it and tell the old group about it
                    var groupStrat = GroupingManager.GetGroupingStrategy <IUnitFacade>();
                    if (groupStrat == null)
                    {
                        Debug.Log("No Grouping Strategy has been registered for IUnitFacade");
                        return;
                    }

                    var newGroup = groupStrat.CreateGroup(groupCount) as DefaultSteeringTransientUnitGroup;
                    if (newGroup == null)
                    {
                        return;
                    }

                    group.nextGroup = newGroup;
                    _nextGroup      = newGroup;
                }
                else
                {
                    // new group exists, so just use it
                    _nextGroup = group.nextGroup;
                }

                // make sure to remove the unit from the old group
                group.Remove(unitData);
            }

            _isPortalling = true;
            // actually execute the portal
            portal.Execute(
                unitData.transform,
                to,
                () =>
            {
                _isPortalling = false;

                if (isFarPortal)
                {
                    // if it is a far portal, we are supposed to join up with the new group
                    _nextGroup.Add(unitData);
                    unitData.transientGroup = _nextGroup;

                    if (_nextGroup.count == 1)
                    {
                        // let the first unit in the new group be responsible for setting the new group up
                        if (vectorField.destination != null)
                        {
                            // the new group's path starts on the other side of the portal...
                            int pathCount = _currentPath.count;
                            var newPath   = new Path(pathCount - (pathPortalIndex + 2));
                            for (int i = pathCount - 1; i >= pathPortalIndex + 2; i--)
                            {
                                newPath.Push(_currentPath[i]);
                            }

                            // the first member that joins the new group tells the new group to move along the path of the old group
                            Vector3 destination = vectorField.destination.position;
                            if ((to.position - destination).sqrMagnitude > 1f)
                            {
                                // check though that the destination is not the same as the starting position
                                _nextGroup.MoveAlong(newPath);
                            }

                            // pass along old group's waypoints to new group
                            if (group.currentWaypoints.count > 0)
                            {
                                _nextGroup.SetWaypoints(group.currentWaypoints);
                            }

                            // pass along old group's formation to the new group
                            if (group.currentFormation != null)
                            {
                                _nextGroup.TransferFormation(group.currentFormation, groupCount, group);
                            }
                        }
                    }
                }
            });
        }