<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>trofch1k</title><author><name>trofch1k</name></author><id>https://teletype.in/atom/trofchik</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/trofchik?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@trofchik?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=trofchik"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/trofchik?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-06-18T03:09:46.953Z</updated><entry><id>trofchik:hhfWfIu2Y</id><link rel="alternate" type="text/html" href="https://teletype.in/@trofchik/hhfWfIu2Y?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=trofchik"></link><title>Ассинхронная загрузка ассетов.</title><published>2020-08-10T11:22:51.452Z</published><updated>2020-08-10T18:48:20.653Z</updated><summary type="html">Оригинал: https://docs.unrealengine.com/en-US/Programming/Assets/AsyncLoading/index.html</summary><content type="html">
  &lt;p&gt;Оригинал: &lt;a href=&quot;https://docs.unrealengine.com/en-US/Programming/Assets/AsyncLoading/index.html&quot; target=&quot;_blank&quot;&gt;https://docs.unrealengine.com/en-US/Programming/Assets/AsyncLoading/index.html&lt;/a&gt;&lt;/p&gt;
  &lt;p&gt;Unreal Engine 4.9&lt;/p&gt;
  &lt;p&gt;В  UE4  появилось несколько новых систем, сильно упрощающих ассинхронную загрузку ассетных данных. Они заменяют большую часть функционала &amp;quot;seekfree&amp;quot; пакетов в UE3. Новые методы работают одинаково, как при разработке так и с подготовленными данными уже на устройстве пользователя. Такми образом, вам не нужно поддерживать две ветви кода. Существуют два основных метода для загрузки и ссылания на данные.&lt;/p&gt;
  &lt;h3&gt;FSofObjectPaths и TSoftObjectPtr&lt;/h3&gt;
  &lt;p&gt;Самый простой способ сослаться на ассет для дизайнера или художника — это создать строгий указатель на UProperty и присвоить ему категорию. В UE4 если у вас есть строгий указатель на UObject, который верно ссылается на ассет, то этот ассет будет загружен вместе с объектом, содержащим этот ассет путём размещения объекта на карте или ссылание на ассет из чего-то наподобие gameinfo. Если вы не будете соблюдать осторожность, то можете загрузить сразу все 100% ваших ассетов во время загрузки вашей игры. Если вы хотите, чтобы дизайнеры могли создавать ссылки на конкретные ассеты, используя тот же интерфейс, что и в случае со строгим указателем, используйте FSofObjectPaths и TSoftObjectPtr.&lt;/p&gt;
  &lt;p&gt;FSofObjectPaths — это простая структура, содержащая строку с полным именем ассета. Если вы создадите поле этого типа в классе, то оно появится в редакторе, как если бы это было поле типа UObject*. Также, она корректно поддерживает кукинг и редиректы, так что если у вас есть SoftObjectPath, то она гарантировано будет работать на устройстве пользователя. TSoftObjectPath — это практически TWeakObjectPtr, который является враппером FSoftObjectPath и будет шаблоном конкретного класса, чтобы можно было разрешить выбирать в редакторе только конкретные классы. Если ассет на который ссылаются существует в памяти, TSoftObjectPtr.Get() вернёт его. Если нет, то вы можете вызвать TSoftObjectPath(), чтобы найти ассет на который он ссылается, загрузить его, используя метод ниже, а затем снова вызвать TSoftObjectPtr.Get(), чтобы разыменовать его.&lt;/p&gt;
  &lt;p&gt;TSoftObjectPtrs и нестрогие пути к объекту прекрасны, если художник или дизайнер настраивают ссылки вручную, но если вы хотите сделать что-то наподобие запроса, чтобы найти ассет, удовлетворяющий определённым требованиям, без загрузки всех ассетов, вам придётся использовать регистр ассетов или библиотеки объектов. &lt;/p&gt;
  &lt;h3&gt;Реестр ассетов и Библиотеки объектов&lt;/h3&gt;
  &lt;p&gt;Реестр ассетов — это система, которая хранит матаданные об ассетах и позволяет создавать запросы об этих ассетах. Она используется в редакторе для вывода информации в браузере контента, но ещё её можно использовать из геймплейного кода для создания запросов метаданных о незагруженных ассетах. Чтобы метаданные ассета отображались при поиске, нужно дабавить тег AssetRegistrySearchable в свойства. Запросы к реестру ассетов возвращают объекты типа FAssetData, содержащие информацию об объекте и карту с парами формата ключ-&amp;gt;значение, содержащими свойства, помеченные как доступные для поиска.&lt;/p&gt;
  &lt;p&gt;Самый простой способ работы с группами незагруженных ассетов — это использование Object Library. Object Library — это объект, содержащий список загруженных объектов или FAssetData для незагруженных объектов, который наследует от общего класса. Для загрузки библиотеки объектов нужно дать ей путь, по которому она будет искать, что в свою очередь добавит все ассеты по этому пути. Это может быть очень полезно, потому что так можно назначать отдельные части вашей контентной папки для разных видов контента, и ходожники и дизайнеры смогут доавлять ассеты без необходимости редактировать список ассетов. Ниже приведён пример загрузки данных ассетов с диска, используя библиотеку объектов.&lt;/p&gt;
  &lt;pre&gt;if (!ObjectLibrary)
{
        ObjectLibrary = UObjectLibrary::CreateLibrary(BaseClass, false, GIsEditor);
        ObjectLibrary-&amp;gt;AddToRoot();
}
ObjectLibrary-&amp;gt;LoadAssetDataFromPathy(TEXT(&amp;quot;/Game/PathWithAllObjectOfSameType&amp;quot;));
if (bFullyLoad)
{
        ObjectLibrary-&amp;gt;LoadAssetsFromAssetData();
}&lt;/pre&gt;
  &lt;p&gt;В этом примере создаётся новая библиотека объектов, связывается с базовым классом и загружает все данные ассетов, найденные по указаннному пути. Затем опционально загружаются сами ассеты. Следует полностью загружать ассеты либо если они лёгкие, либо если вы занимаетесь кукингом и вам нужно убедиться, что все ассеты действительно &amp;quot;кукнулись&amp;quot;. Пока вы выполняете запрос реестру ассетов во время кукинга и загружаете возвращённые ассеты, библиотека объектов будет работать с &amp;quot;кукнутыми&amp;quot; данными на устройстве пользователя в точности, как при разработке. С момента, как у вас есть данные ассетов в ObjectLibrary, вы можете создавать запросы и выборочно загружать определённые ассеты. Ниже приведён пример создания запроса.&lt;/p&gt;
  &lt;pre&gt;TArray&amp;lt;FAssetData&amp;gt; AssetDatas;
ObjectLibrary-&amp;gt;GetAssetDataList(AssetDatas);

for (int32 i = 0; i &amp;lt; AssetData.Num(); ++i)
{
        FAssetData&amp;amp; AssetData = AssetDatas[i];

        const FString* FoundTypeNameString = AssetData.TagsAndValues.Find(GET_MEMBER_NAME_CHECKED(uaSSEToBJECT, tYPEnAME));

        if (FoundTypeNameString &amp;amp;&amp;amp; FoiundTypeNameString-&amp;gt;Contains(TEXT(&amp;quot;FooType&amp;quot;)))
        {
                return AssetData;
        }
}&lt;/pre&gt;
  &lt;p&gt;В этом примере происходит поиск по библиотеке объектов чего либо, где поле TypeName содержит &amp;quot;FooType&amp;quot;. Возвращается первый найденный экземпляр. После получения AssetData, можно вызвать ToStringReferece() чтобы конвертировать её в FSoftObjectPath, который можно будет загружать ассинхронно.&lt;/p&gt;
  &lt;h3&gt;StreamableManager и Асинхронная загрузка &lt;/h3&gt;
  &lt;p&gt;Теперь когда у вас есть FSoftObjectPath, который ссылается на ассет на диске, как его можно загрузить асинхронно? Использование FStreamableManager — простейший способ сделать это. Для начала вам нужно будет создать FStreamableManager. Я бы советовал поместить его во что-то на подобие глобального для игры синглтон объекта, например определённого с помощью GameSingletonClassName в DefaultEngine.ini. Затем ему можно передать FSoftObjectPath и начать загрузку. SynchronousLoad произведёт обычную блокирующую загрузку (игра остановиться до завершения загрузки) и вернёт ассет. Этот метод может подойти для легковесных объектов, однако в некоторых случаях может остановить главный поток слишком надолго. В таком случае нужно будет использовать ReqestAsynchLoad, который асинхронно загрузит группу ассетов и вызовет делегата по завершению. Ниже приведён пример.&lt;/p&gt;
  &lt;pre&gt;void UGameCheatManager::GrantItems()
{
        TArray&amp;lt;FSoftObjectpath&amp;gt; ItemsToStream;
        FStreamManager&amp;amp; Streamable = UGameGlobals::Get().StreamManager;
        for (int32 i = 0; i &amp;lt; ItemList.Num(); ++i)
        {
                ItemsToStream.AddUnique(ItemList[i].ToStringReference());
        }
        Streamable.RequestAsynchLoad(ItemsToStream, FStreamableDelegate::CreateUObject(this, &amp;amp;UGameCheatManager::GrantItemsDeffered));
}

void UGameCheatManager::GrantItemsDeffered()
{
        for (int32 i = 0; i &amp;lt; ItemList.Num(); ++i)
        {
                UGameData* ItemData = ItemList[i].Get()
                if (ItemData)
                {
                        MyPc-&amp;gt;GrantItems(ItemData);
                }
}&lt;/pre&gt;
  &lt;p&gt;В этом примере ItemList является TArray&amp;amp;lt, который содержит TSoftObjectPath&amp;lt;UGameItem&amp;gt;, который был модифицирован дизайнерами в редакторе. Код итерирует список и конвертирует TSoftObjectPath&amp;lt;UGameItem&amp;gt; в StringReference и ставит их в очередь на загрузку. Когда все эти предметы загружены (или отсутствуют и не могли быть загружены), вызывается переданный ранее делегат. Этот делегат затем итерирует тот же список предметов, разыменовывает их и передаёт игроку. StreamableManager хранит строгие ссылки на любой загруженный им ассет, пока не будет вызван делегат, чтобы вы могли быть уверены, что ни один из объектов, которых вы хотели асинхронно загрузить не будут удалены сборщиком мусора до того как будет вызван делегат. StreamableManager перестаёт хранить ссылки после вызова делегата, так что вам нужно строго ссылаться на объекты где-нибудь в другом месте, чтобы удостовериться, что они остануться под рукой.&lt;/p&gt;
  &lt;p&gt;Вы можете использовать тот же самый метод для загрузки FAssetData, просто вызовите для них (FAssetData) ToStringReference и поместите их в массив, затем вызовите RequestAsynchLoad вместе с делегатом. Делегат может быть чем угодно, так что вы можете передать информацию о пейлоэде, если это необходимо. Путём комбинирования выше описанных методов вы можете создать систему, позволяющую эффективно загружать любые ассеты в вашу игру. Переписывание геймплейного кода, использующего прямые обращения к памяти под использование асинхронной загрузки займёт время, но в итоге ваша игра будет иметь меньше простоев и будет использовать намного меньше памяти.&lt;/p&gt;

</content></entry><entry><id>trofchik:Va80a5cer</id><link rel="alternate" type="text/html" href="https://teletype.in/@trofchik/Va80a5cer?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=trofchik"></link><title>Что такое стабилизация отдачи в Call of Duty: Modern Warfare 2019</title><published>2020-07-20T20:38:27.579Z</published><updated>2020-07-20T20:38:27.579Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://teletype.in/files/7b/97/7b9779d8-044a-4db1-a278-4b06a9147513.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://teletype.in/files/11/a1/11a1a137-dcfd-4953-88f9-58ac8973c78b.png&quot;&gt;Данная статья является сценарием к видео, которое я не смею просто так кидать кому-то в комменты. Тем не менее, мне всё так же хочется повысить осведомлённость игроков по поднятому вопросу.</summary><content type="html">
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/11/a1/11a1a137-dcfd-4953-88f9-58ac8973c78b.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;blockquote&gt;&lt;em&gt;Данная статья является сценарием к видео, которое я не смею просто так кидать кому-то в комменты. Тем не менее, мне всё так же хочется повысить осведомлённость игроков по поднятому вопросу.&lt;/em&gt;&lt;/blockquote&gt;
  &lt;h3&gt;Введение&lt;/h3&gt;
  &lt;p&gt;Привет. Как вы наверное поняли из названия речь пойдёт о том, что такое стабилизация отдачи (recoil stabilization в английской версии) в CoD:MW19 и как она работает. Написанное в этой статье идёт в разрез с общепринятым мнением в англоязычном сообществе, будто бы стабилизация влияет на горизонтальную отдачу, хотя на самом деле она влияет на вертикальную отдачу и не только на неё. В начале будет небольшая теоретическая часть и описание методов тестирования, а потом мы перейдём к делу.&lt;/p&gt;
  &lt;h3&gt;Теория&lt;/h3&gt;
  &lt;p&gt;В большинстве современных шутеров используется модель отдачи подразумевающая наличие подброса ствола согласно паттерну отдачи, прописаному гейм-дизайнером, и разлёта пуль. Как вы могли заметить оружие в Modern Warfare ведёт себя немного по-другому, каждый раз, когда вы из него стреляете.&lt;/p&gt;
  &lt;p&gt;Проще всего это описывается так. Представьте паттерн отдачи (красный на картинке ниже). Точки на этом паттерне (синие), мы назовём эталонными точками попаданий. Оружие бросает от одной точки к следующей. Теперь представьте круг вокруг каждой из точек (зелёный). Размер такого круга будет показывать как сильно может отклониться пуля от своей эталонной точки. Наконец, главная особенность этой модели — это влияние разброса на отдачу оружия. Если пуля решит отклониться влево от своей эталонной точки, то и ствол оружия бросит немного левее эталонной точки. Если пуля уйдёт ниже, тогда вы почувствуйте меньше вертикальной отдачи и наоборот. (фиолетовый - пример одного из паттернов который может получиться). Такая модель используется в Insurgency: Sandstorm, Rainbow Six: Seige, Valorant и даже разработчики Battlefield 5 отказались от модели с &amp;quot;прокликом&amp;quot; оружия в её пользу. В серии Call of Duty —  это Modern Warfare 2019, Black Ops 4 и WW2, но на счёт последней я не уверен.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/dd/ba/ddbae482-e3d4-4221-b227-268dbe2cc71c.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Методы тестирования&lt;/h3&gt;
  &lt;p&gt;Перед тем как я покажу результаты я должен описать методы тестирования, чтобы избежать недопонимания в будущем.&lt;/p&gt;
  &lt;p&gt;Для тестов я использовал следующие сборки. Три АК в 7.62х39, каждый из которых имеет &amp;quot;бубен&amp;quot; на 75 патронов, демонтированный приклад и ствол длинной 8.1 дюйма. Первй АК был оставлен как есть. Второй получил компенсатор и рукоять наёмника. На третий были установлены дульный тормоз и рукоять угловая рукоятка.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/29/85/2985308a-3bf6-432a-857b-29f1ba54e814.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Стоя перед стеной, я выстрелил столько очередей, сколько мог на ней уместить. Затем я сделал скриншот стены и перенёс его в Фотошоп, где отметил первую и пятую пулю в каждой очереди. Затем я совместил пометки для каждой очереди наложив друг их друг на друга, выровняв по первой пуле.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/3f/bf/3fbf3332-ad26-49a1-8967-b8b11c3e0c46.png&quot; width=&quot;1366&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Все тесты были проведены с помощью одной и той же стены. Все выстрелы были сделаны с одинакового расстояния от точки прицеливания. Для каждый сборки в стену было выпущено порядка тридцати очередей.&lt;/p&gt;
  &lt;h3&gt;Результаты&lt;/h3&gt;
  &lt;p&gt;Ниже вы можете видеть группы каждого из трёх АК.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/0d/ae/0daef624-20c9-4014-a949-812103cd07db.png&quot; width=&quot;1366&quot; /&gt;
  &lt;/figure&gt;
  &lt;p&gt;Как и ожидалась базовая версия показала себя хуже всех. Между первой и пятой пулей присутствует огромный разрыв, что говорит о сильной отдаче. Пули случайным образом разбросаны по бесформенной зоне.&lt;/p&gt;
  &lt;p&gt;Версия с рукояткой наёмника и компенсатором имеет меньшую вертикальную отдачу, однако разброс оставляет желать лучшего.&lt;/p&gt;
  &lt;p&gt;Наконец, версия с угловой рукояткой и дульным тормозом имеет вертикальную отдачу равную &amp;quot;control&amp;quot; версии. Хорошо видно, что пули как бы &amp;quot;сжимаются&amp;quot; к определённой точке (синия точка по центру, хорошо видно, что края группы более прозрачные т.к. там меньше пуль наслаивается друг на друга). Я очень сомневаюсь, что такое поведение случайно, ведь мы протестировали аж три сборки и взяли по тридцать образцов для каждой, но такие результаты показала только одна. Таким образом можно сделать вывод, что стабилизация отдачи влияет на фактор случайности в отдаче. Простым языком, стабилизация уменьшает размер зелёных кругов (т.е. разброс) из теоретической части и заставляет пулю &amp;quot;стремиться&amp;quot; к центру своего круга.&lt;/p&gt;
  &lt;h3&gt;Дополнение&lt;/h3&gt;
  &lt;p&gt;Очевидно, что случайность отдачи было бы куда лучшим названием для того, что Infinity Ward нарекли стабилизацией. Тем не менее нам всё ещё интересно, почему уменьшая случайность мы так же уменьшаем вертикальную отдачу.&lt;/p&gt;
  &lt;p&gt;Уменьшая разброс, мы делаем те самые круги меньше, как по горизонтали так и, что более важно, по вертикали. Иногда бывает так, что очень много пуль в очереди отклоняются выше своих эталонных точек. Уменьшая разброс пуль по вертикали, мы уменьшаем вероятности таких случаев, а, заставляя пули стремиться к центру, так же ущерб от таких случаев вертикальной отдаче оружия.&lt;/p&gt;
  &lt;h3&gt;На практике&lt;/h3&gt;
  &lt;p&gt;После прочтения прошлых разделов, может показаться, что стабилизация во всём лучше контроля, но на практике всё немного по-другому. В этот раз я исаользовал два АК в 7.62х39 с треугольным рамочным прикладом. Первый имел компенсатор и рукоять наёмника (слева на картинке), второй — дульный тормоз и угловую рукоятку (справа). Из каждого я выстрели по две очереди по 15 патронов, и результаты оказались неотличимы.&lt;/p&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/7b/91/7b911f5d-631c-47fc-a5d4-8ea06e80d2d2.png&quot; width=&quot;1280&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3&gt;Заключение&lt;/h3&gt;
  &lt;p&gt;Я протестировал лишь один ствол с всего лишь двумя наборами улучшений. Такая небольшая выборка говорит лишь о том, что вложение в стабилизацию при создании сборки не является плохим решением. Однако, мой метод тестирования может вдохновить безумцев в сообществе Call of Duty на проведение более масштабных тестов. Так же мой метод может помочь ютюберам, делающим обзоры оружия, при добавление в игру новых образцов.&lt;/p&gt;
  &lt;p&gt;Как уже подметил u/&lt;a href=&quot;https://www.reddit.com/user/CanadianTuero/&quot; target=&quot;_blank&quot;&gt;CanadianTuero&lt;/a&gt; на Редите, метод не совсем правильный. Хоть стрельбы и ведётся всегда перпендикулярно стене, но положение обзор &amp;quot;камеры при скриншоте не перпендикулярен каждой очереди, а потому может возникнуть искажение перспективы в случае с образцами на боковых границах стены, что в конечном итоге приведёт к неточности тестирования. Насколько велика эта неточность мне неизвестно, но я пологаю, что она не настолько большая чтобы невелировать результаты моих тестов.&lt;/p&gt;
  &lt;p&gt;Спасибо, что дочитали до сюда. Всем добра.&lt;/p&gt;

</content></entry><entry><id>trofchik:VD1zjbOhV</id><link rel="alternate" type="text/html" href="https://teletype.in/@trofchik/VD1zjbOhV?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=trofchik"></link><title>Лабораторная работа #2 Проектирование БД</title><published>2020-04-16T19:43:30.184Z</published><updated>2020-04-18T15:35:45.075Z</updated><summary type="html">&lt;img src=&quot;https://teletype.in/files/67/9a/679a05a7-3030-4741-a867-abc946a9aff1.png&quot;&gt;Склад импортёра, где хранятся различные виды тканей, откуда потом отправляются производителям продукции из этой ткани. </summary><content type="html">
  &lt;h3&gt;Предметная область&lt;/h3&gt;
  &lt;p&gt;Склад импортёра, где хранятся различные виды тканей, откуда потом отправляются производителям продукции из этой ткани. &lt;/p&gt;
  &lt;h3&gt;Словестное описание&lt;/h3&gt;
  &lt;p&gt;На складе бывают несколько видов тканей. Каждая сущность такой ткани содержит: код, название, площадь в одном рулоне, код &lt;u&gt;фабрики&lt;/u&gt; - производителя.&lt;/p&gt;
  &lt;p&gt;Ткани хранятся на складе: код ткани, количество рулонов на складе.&lt;/p&gt;
  &lt;p&gt;Каждый вид ткани производит одна или несколько &lt;u&gt;фабрик&lt;/u&gt;: код, название, страна. &lt;/p&gt;
  &lt;p&gt;В каждом виде ткани испытывает потребность закупщики - предприятия из России: код, название, город. &lt;/p&gt;
  &lt;p&gt;На основании данных со склады и запросов производящих предприятий составляется список запросов на ткань по каждому предприятию: код запроса, код предприятия, код запрашиваемой ткани, количество в рулонах, статус заказа (ожидется поступление на склад импортёра, отправлен, подтверждено получение).&lt;/p&gt;
  &lt;h3&gt;Инфологическая модель&lt;/h3&gt;
  &lt;figure class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://teletype.in/files/67/9a/679a05a7-3030-4741-a867-abc946a9aff1.png&quot; width=&quot;728&quot; /&gt;
  &lt;/figure&gt;

</content></entry></feed>