Как работать со ссылочными типами в DOTS

Вопрос по поводу работы в Unity с использованием DOTS. Пример:

У меня есть игровой объект - скажем космический корабль. Моя задача состоит в том чтобы заставить его курсировать между двумя планетами, на которые он мог бы приземляться и с которых он мог бы взлетать.

По сути я реализовал для планеты следующее:

public class Planet : IPlanet
    {
        public SpaceshipsDock SpaceshipsDock { get; set; }

        private void Start()
        {
            SpaceshipsDock = new SpaceshipsDock();
        }

        private void Update()
        {
            
        }
    }

где SpaceshipsDock:

public class SpaceshipsDock
    {
        public int Tier { get; private set; }
        public int DockSize { get; set; }
        public List<ISpaceship> Spaceships { get; private set; } = new List<ISpaceship>();
        public Queue<ISpaceship> LandingQueue { get; private set; } = new Queue<ISpaceship>();

        public SpaceshipsDock()
        {
            DockSize = 1;
            Tier = 1;
        }

        public void AcceptLandingRequest(ISpaceship spaceship) {
            if (Spaceships.Count < DockSize) {
                Spaceships.Add(spaceship);
                spaceship.Land();

                return;
            }

            LandingQueue.Enqueue(spaceship);
        }

        public void SendToFlight(ISpaceship spaceship) {
            Spaceships.Remove(spaceship);
            spaceship.Fly();

            if (LandingQueue.Count > 0)
            {
                var pendingShip = LandingQueue.Dequeue();
                Spaceships.Add(pendingShip);
                pendingShip.Land();
            }
        }

        public void TierUp() {
            DockSize += ++Tier * BalanceSettings.DockCapacityMultiplier;
        }
    }

Однако если планета - игровой объект, и я хочу использовать DOTS, то я должен сделать её struct. Но я не могу сделать этого не погрешив против здравого смысла, т.к. в этой структуре будут жить ссылочные типы, и что ещё хуже - концепция DOTS как я её понимаю состоит в том что сущности могут содержать компоненты, которые содержат в себе данные для обработки системы. И при этом компоненты не должны содержать никакой логики. Просто данные и желательно только типы значения. Если представить что SpaceshipDock это компонент, то возникает вопрос - а как мне избежать логики в нём?

Я могу конечно вынести методы из него в какой ни будь SpaceshipDockService, передавать в него данные, таким образом обойти это ограничение. Это уже выглядит глупо, но ещё глупее то, что не List не Queue в структуре жить не могут.

Мне кажется мой подход в корне неверен. Возможно ООП вообще не следует применять с DOTS, но я не понимаю как лучше это организовать.

А теперь для полноты картины корабль:

    public interface ISpaceship
    {
        SpaceshipFlightPlan FlightPlan { get; }

        public void Land();
        public void Fly();
    }
public enum FlightPlanState { 
        InProcess,
        Finished,
        Suspended
    }
    public class SpaceshipFlightPlan
    {
        public bool IsLooped { get; set; }
        public FlightPlanState PlanState { get; private set; }
        public Queue<WayPoint> FlightWaypoints { get; private set; } = new Queue<WayPoint>();
        private Queue<WayPoint> FlightWaypointsSaved { get; set; } = new Queue<WayPoint>();
        public WayPoint CurrentTargetWaypoint { get; private set; }
        public WayPoint HomeWaypoint { get; set; }

        public void AddWaypoint(WayPoint wayPoint) {
            FlightWaypoints.Enqueue(wayPoint);
            FlightWaypointsSaved.Enqueue(wayPoint);
        }

        public void RemoveWaypoint(WayPoint wayPoint) {
            FlightWaypoints = new Queue<WayPoint>(FlightWaypoints.Where(i => i != wayPoint));
            FlightWaypointsSaved = new Queue<WayPoint>(FlightWaypoints);
        }

        public void ClearWaypoints() {
            FlightWaypoints.Clear();
            FlightWaypointsSaved.Clear();
        }

        public void OnWayPointReached() {
            if(PlanState != FlightPlanState.Finished)
                CurrentTargetWaypoint = GetNextWaypoint();
        }

        public void OnSuspendFlight() {
            PlanState = FlightPlanState.Suspended;
            CurrentTargetWaypoint = HomeWaypoint;
        }

        private WayPoint GetNextWaypoint() {
            if (!IsLooped) {
                if(FlightWaypoints.Count > 0)
                    return FlightWaypoints.Dequeue();

                FlightWaypoints = new Queue<WayPoint>(FlightWaypointsSaved);
                return HomeWaypoint;
            }

            PlanState = FlightPlanState.Finished;
            return HomeWaypoint;
        }
    }

И опять эти данные не могут считаться структурой в полной мере. Я надеялся сделать так:

Есть две планеты. Я задаю кораблю FlightPlan, допустим слетать туда и обратно. После того как я вызываю у планеты метод SendToFlight вызывается нереализованный, но представим что реализованный метод Fly у корабля, который просто должен выставить PlanState - InProcess.

Далее, некая система, которая отвечает за полёты кораблей, FlightSystem, видит при следующем обходе кораблей что этот должен взлететь. Она спавнит его модель рядом с планетой и начинает фрейм за фреймом двигать в сторону CurrentTargetWaypoint, проверяя оставшуюся до пункта назначения дистанцию.

По достижении пункта назначения, когда дистанция становится меньше некоторой минимальной, корабль (опустим для простоты что он может попасть в очередь на посадку), садится на планету. Его модель диспавнится, он появляется в доке. Происходит процесс его разгрузки, после чего он снова взлетает, и летит обратно.

И вот у меня получается смешение подходов. С одной стороны, когда я буду двигать корабль туда сюда, я просто буду менять его LocalToWorld компонент. Но потом у меня остаётся логика взлёта-посадки, и тут вообще не ясно как не сделать глупую реализацию. Ведь на сколько я понимаю механизм работы DOTS - созданный мною объект нивелирует преимущество перед MonoBehaviour, т.к. не возможно сказать какого размера он будет, и жить он будет в куче.

Может кто-то поделится наработками? Что я делаю не так? Может у кого есть проект в котором можно подглядеть? Заранее спасибо!


Ответы (0 шт):