Следующая версия | Предыдущая версия |
ru:toolworks:docs:apparatus:iterating [2021/09/01 23:02] – создано + переведено jispar | ru:toolworks:docs:apparatus:iterating [2022/06/05 15:31] (текущий) – обновил в соответствии с англоязычной версией jispar |
---|
====== Итерирование ====== | ====== Итерирование ====== |
| |
Чтобы реализовать вашу реальную логику Механики, вам потребуется обработать все Сущности, удовлетворяющие [[ru:toolworks:docs:apparatus:filter|Фильтру]]. В целях эффективности и последовательности, это делается не напрямую, а через [[ru:toolworks:docs:apparatus:enchaining|Цепи]]. Итерируясь по цепям, вы итерируетесь по всем Сущностям и объектам типа Сущностный внутри них. | Чтобы реализовать вашу реальную логику Механики, вам потребуется обработать все Сущности, удовлетворяющие [[ru:toolworks:docs:apparatus:filter|Фильтру]]. В целях эффективности и последовательности это делается вручную через [[ru:toolworks:docs:apparatus:enchaining|Цепи]]. Итерируясь по цепям, вы итерируетесь по всем Сущностям и Сущностным объектам внутри конкретной цепи. |
| |
В итерации по цепям помогают Курсоры. Их семантика напоминает итераторы в стандартных контейнерах. Множественность курсоров поддерживается, но с оглядкой на мультипоточность, которая будет полноценно поддерживаться в недалёком будущем. А сейчас вам достаточно использовать только один простой Курсор. | В итерации по цепям помогают Курсоры. Их семантика напоминает итераторы в стандартных контейнерах. |
| |
===== Работа в C++ ===== | ===== Работа в C++ ===== |
| |
Пожалуйста, заметьте, что цепи утилизируются автоматически, когда все итерируемые курсоры закончили итерироваться по слотам. | Пожалуйста, заметьте, что цепи утилизируются автоматически, когда все итерируемые курсоры закончили итерироваться по слотам. |
Чтобы предотвратить такое поведение особо, можете использовать вызовы ''[[appi>struct_t_chain.html#abdde97a57f62214dff4e643287eb2fae|Retain()]]''/''[[struct_t_chain.html#a665154da00eac2bcc7760851583db281|Release()]]'', чтобы самостоятельно контролировать время жизни объектов: | Чтобы предотвратить такое поведение особо, можете использовать вызовы ''[[appi>struct_t_chain.html#abdde97a57f62214dff4e643287eb2fae|Retain()]]''/''[[appi>struct_t_chain.html#a665154da00eac2bcc7760851583db281|Release()]]'', чтобы самостоятельно контролировать время жизни объектов: |
| |
<code cpp> | <code cpp> |
==== Встроенные курсоры ==== | ==== Встроенные курсоры ==== |
| |
Аппарат предоставляет способ итерироваться по цепям встроенными (самостоятельно выделенными /* чё? */) Курсорами. В основном, эта технология используется внутри плагина для корректной работы Blueprint-ов, и вам её стоит избегать в своём C++ коде. | Аппарат предоставляет способ итерироваться по цепям встроенными Курсорами. В основном, эта технология используется внутри плагина для корректной работы Blueprint-ов, и вам её стоит избегать в своём C++ коде. |
| |
Код будет довольно прост. Он состоит из while-цикла с одним условием: | Код будет довольно прост. Он состоит из while-цикла с одним условием: |
</code> | </code> |
| |
Внутри этого цикла вы можете реализовать нужную /*нужную? в источнике actual написано, так что я не знаю... "актуальная логика"? ну уж нет, пусть лучше нужная*/ логику, используя [[appi>struct_f_subject_handle.html|Сущности]] напрямую или служебные методы [[appi>struct_f_chain.html|Цепей]]: | Внутри этого цикла вы можете реализовать нужную логику, используя [[appi>struct_f_subject_handle.html|Сущности]] напрямую или служебные методы [[appi>struct_f_chain.html|Цепей]]: |
<code cpp> | <code cpp> |
while (Chain.BeginOrAdvance()) | while (Chain.BeginOrAdvance()) |
</code> | </code> |
| |
Когда указатель-Курсор Цепи пройдёт последний доступный объект Сущности (или типа Сущностный), Цепь будет уничтожена и ранее заблокированные Чанки и Белты вновь разблокируются, все ожидаемые структурные изменения будут незамедлительно выполнены (если они вообще были). | Когда указатель-Курсор Цепи пройдёт последнюю доступную Сущность (или Сущностный объект), Цепь будет уничтожена и ранее заблокированные чанки и ремни вновь разблокируются, все ожидаемые структурные изменения будут незамедлительно выполнены (если они вообще были). |
| |
| ==== Прямое итерирование ==== |
| |
| Если вам необходимо итерироваться по чанкам напрямик, вы можете инициализировать Чанк-Прокси. |
| Обычно, вам потребуется проитерироваться по всем собранным Прокси через соответсвующий [[appi>class_a_mechanism.html#ae72188d973bed3d8484dc5ab87e5e1e1|Enchain]] метод и |
| в каждом чанке итерироваться по его Сущностям-слотам. |
| |
| Пример будет таким:<code cpp> |
| TArray<TChunkProxy<FSolidSubjectHandle, FJumpingTrait>> ChunkProxies; |
| Mechanism->Enchain(TFilter<FJumpingTrait>(), ChunkProxies); |
| for (int32 i = 0; i < ChunkProxies.Num(); ++i) // Итерируемся по всем подходящим чанкам... |
| { |
| auto& ChunkProxy = ChunkProxies[i]; |
| for (int32 j = 0; j < ChunkProxy.Num(); ++j) // Итерируемся по слотам... |
| { |
| // Perform the necessary logic... |
| ChunkProxy.TraitRefAt<FJumpingTrait>(j).Position += FVector::UpVector * DeltaTime; |
| } |
| } |
| </code> |
| |
| Заметьте, однако, что этот подход абсолютно ручной, и не выполняет какие-либо логические проверки во время итерирования, например, [[ru:toolworks:docs:apparatus:flagmark|совпадение флагов]]. |
| |
| Если вы также выполняете изменение топологии внутри ваших циклов, то ваши сущности могут произвольно изменить свои чанки или слоты, поэтому вам скорее всего потребуется проверять слоты на (не-)свежесть. |
| |
| Сделать это можно так:<code cpp> |
| for (int32 j = 0; j < ChunkProxy.Num(); ++j) // Итерируемся по всем слотам чанка... |
| { |
| if (ChunkProxy.IsStaleAt(j)) continue; // Пропустить сущность, если она была перемещена или удалена... |
| |
| ChunkProxy.SubjectAt(j).SetTrait(FSpeedBoostTrait{10.0f}); |
| } |
| </code> |
| |
| |
| Итерация чанков напрямую (через прокси) может дать определенный прирост производительности по сравнению с обычной итерацией и [[ru:toolworks:docs:apparatus:operating|оперированием]]. В основном это связано с возможностью контролировать каждый аспект итерации вручную и исключать все лишние проверки. Вам просто нужно точно знать, что вы делаете и чего пытаетесь достичь, так как этот способ менее безопасен. |