Класс для респаума мобов
SelectiveSpawnPoint.cs

Код:
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.ComponentModel;
using System.Drawing.Design;
using System.IO;
using Engine;
using Engine.EntitySystem;
using Engine.MapSystem;
using Engine.MathEx;
using Engine.PhysicsSystem;
using Engine.SoundSystem;
using Engine.Renderer;
using Engine.Utils;
using Engine.FileSystem;
using ProjectEntities;

namespace ProjectEntities
{    /// <summary>
    /// Defines the <see cref="SpawnPoint"/> entity type.
    /// </summary>
    public class SelectiveSpawnPointType : MapObjectType
    {
    }
 
    public class SelectiveSpawnPoint : MapObject
    {
        [FieldSerialize]
     bool triggerFromCode; 
        public class SelectiveSpawnPointItem
        {
            [FieldSerialize]
            private AIType aiType;
            [FieldSerialize]
            private UnitType unitType;

            public AIType AIType
            {
                get { return aiType; }
                set { aiType = value; }
            }

            public UnitType UnitType
            {
                get { return unitType; }
                set { unitType = value; }
            }
        }

         [Description("Список UnitTypes, которые будут порождены")]
        [FieldSerialize]
        private List<SelectiveSpawnPointItem> spawnerItems = new List<SelectiveSpawnPointItem>();

        public List<SelectiveSpawnPointItem> SpawnerItems
        {
            get { return spawnerItems; }
        }

        [FieldSerialize]
        private FactionType faction;
        public FactionType Faction
        {
            get { return faction; }
            set { faction = value; }
        }
 
        [FieldSerialize]
        float spawnTime;
        [FieldSerialize]
        float spawnRadius;
        [FieldSerialize]
        int popNumber;
        [FieldSerialize]
        float closeToEvent;
        //counter for remaining time
        float spawnCounter;
        //the amount of entities left to spawn
        int popAmount;
        bool TFC;


        SelectiveSpawnPointType _type = null; public new SelectiveSpawnPointType Type { get { return _type; } }

        [Description("Время в секундах между порождениями")]
        [DefaultValue(20.0f)]
        public float SpawnTime
        {
            get { return spawnTime; }
            set { spawnTime = value; }
        }
        [Description("Радиус появления, который должен быть свободен от других юнитов")]
        [DefaultValue(10.0f)]
        public float SpawnRadius
        {
            get { return spawnRadius; }
            set { spawnRadius = value; }
        }

        [Description("Количество объектов, которые будут созданы")]
        public int PopNumber
        {
            get { return popNumber; }
            set { popNumber = value; }

        }
        [Description("Когда игрок входит в этот радиус, объекты будут появляться")]
        [DefaultValueAttribute(10.0f)]
        public float CloseToEvent
        {
            get { return closeToEvent; }
            set { closeToEvent = value; }
        }
        [Description("Должен быть вызван из кода")]
        [DefaultValueAttribute(false)]
        public bool TriggerFromCode
        {
            get { return triggerFromCode; }
            set { triggerFromCode = value; }
        }



        protected override void OnPostCreate(bool loaded)
        {
            base.OnPostCreate(loaded);
            spawnCounter = 0.0f;
            SubscribeToTickEvent();
            TFC = TriggerFromCode;
        }
        protected override void OnTick()
        {
            base.OnTick();
            spawnCounter += TickDelta;
            if (spawnCounter >= SpawnTime) //time to do it
            {
                triggerFromCode = TriggerFromCode;
                if (triggerFromCode == true) return;
                spawnCounter = 0.0f;
                if (!isSpawnPositionFree()) return;
                if (!isCloseToPoint()) return;
                popAmount++;
                if (popAmount <= PopNumber)
                {
                    int next = World.Instance.Random.Next(0, spawnerItems.Count);
                    Unit newUnit = (Unit)Entities.Instance.Create(spawnerItems[next].UnitType, Parent);

                    if (spawnerItems[next].AIType != null)
                        newUnit.InitialAI = spawnerItems[next].AIType;

                    if (faction != null)
                        newUnit.InitialFaction = faction;

                    newUnit.Position = Position;
                    newUnit.Rotation = Rotation;
                    newUnit.PostCreate();
                }

                // Reset so can be retriggered from code. 
                if (popAmount == PopNumber && TFC==true)
                {
                    TriggerFromCode = true;
                    popAmount = 0;
                }

            }
        }
        Vec3 FindFreePositionForUnit(Unit unit, Vec3 center)
        {
            Vec3 volumeSize = unit.MapBounds.GetSize() + new Vec3(2, 2, 0);
            for (float zOffset = 0; ; zOffset += .3f)
            {
                for (float radius = 3; radius < 8; radius += .6f)
                {
                    for (float angle = 0; angle < MathFunctions.PI * 2; angle += MathFunctions.PI / 32)
                    {
                        Vec3 pos = center + new Vec3(MathFunctions.Cos(angle),
                             MathFunctions.Sin(angle), 0) * radius + new Vec3(0, 0, zOffset);
                        Bounds volume = new Bounds(pos);
                        volume.Expand(volumeSize * .5f);
                        Body[] bodies = PhysicsWorld.Instance.VolumeCast(
                            volume, (int)ContactGroup.CastOnlyContact);
                        if (bodies.Length == 0)
                            return pos;
                    }
                }
            }
        }
        bool isCloseToPoint()
        {
            bool returnValue = false;
            if (CloseToEvent <= 0)
            {
                returnValue = true;
            }
            else
            {
                Map.Instance.GetObjects(new Sphere(Position, CloseToEvent),
                  MapObjectSceneGraphGroups.UnitGroupMask, delegate(MapObject mapObject)
                    {
                        PlayerCharacter pchar = mapObject as PlayerCharacter;
                        if (pchar != null)
                        {
                            returnValue = true;
                        }
                    });

            }
            return returnValue;
        }
        bool isSpawnPositionFree()
        {
            bool returnValue = true;
            Map.Instance.GetObjects(new Sphere(Position, SpawnRadius),
           MapObjectSceneGraphGroups.UnitGroupMask, delegate(MapObject mapObject)
            {
                Unit unit = mapObject as Unit;
                //if there is atleast one then we won't spawn
                if (unit != null)
                {
                    returnValue = false;
                }
            });


            foreach (Entity obj in Entities.Instance.EntitiesCollection)
            {
                Unit un = obj as Unit;
                if (un != null)
                {
                    if ((un.Position - Position).Length() < SpawnRadius)
                    {
                        returnValue = false;
                    }
                }
            }

            return returnValue;
        }
    }
}

Описание

Автор кода: bernie