Войти
UnityФорумОбщее

Unity (проблемы, решения, перспективы) (124 стр)

Страницы: 1123 124 125 126129 Следующая »
#1845
14:22, 31 мая 2020

alexzzzz
> В смысле?
В прямом.

Дело было так.  Нужно было мне установить кубы по поверхности локации определяя высоту сверху рейкастами.
Но в итоге некоторые висели в воздухе, а некоторые оказывались в глубине склонов. Сначала подумал что что-то не понимая в рейкастах. Потом начал ковыряться с коллайдерами.
Все объекты у меня  сделаны дочерними "пустых" объектов. Так вот, я эти склоны добавлял к объекту и потом уже дочерними поворачивал в нужную сторону.
Вот получилось что получилось.
А когда повернул именно родительские объекты, то все кубы встали на свои места. Никто теперь не висит и не проваливается в склоны.


#1846
(Правка: 16:09) 16:09, 31 мая 2020

DemiosFantasimo
Ну, в этом описании достаточно мест, где можно накосячить самому. Для проверки лучше воспроизвести на примитивном примере.

--
А правда что ли ограничение не использовать ссылочные типы в джобах действует всегда, а не только если используется Burst-компиляция? Так всегда было?

Я думал, это Burst-компилятор их не поддерживает.

#1847
16:35, 31 мая 2020

alexzzzz
ну я собственно ставил опыт поставив 4 моих склона повернув в разные стороны. Только на соответствующий дефолту нормально стаяли кубы. Фишка в том, что кубы висели в воздухе именно по полосе с сечением примерно как у непосредственно подъема.
Это скрин подъема. Но здесь уже норм. Чот возвращать всё назад уже не хочется чтобы делать скрин парящих кубов.
Screenshot_1 | Unity (проблемы, решения, перспективы)

По крайней мере это возможно  для статики, не ригибоди.

#1848
(Правка: 13:27) 13:12, 6 июня 2020

2019.3.9f1
Пытаюсь освоиться в unsafe code

Создаю 50 кубов  на которых висит скрипт. В результате через пару секунд Юнити подвисает крашится с предложением баг репорта.

Ошибку вызывает собственно

addrs[i]->a = Random.Range(1f, 50f);
 

Но дело не в цикле, для одного элемента  тот же эффект

Что я понял не так или может проблема в Юнити?

public unsafe class MemoryScript : MonoBehaviour
{
    // Start is called before the first frame update
   
    unsafe Crasher*[] addrs;   

    void Start()
    {
        unsafe
        {
            addrs = new Crasher*[100];
            Crasher[] c = new Crasher[100];
            for(int i=0; i<=99; i++)
            {
                fixed (Crasher* f = &c[i])
                {
                    addrs[i] = f;
                }
            }
        }
    }

   
    void Update()
    {      
        unsafe
        {            
            for (int i = 0; i <= 100-1; i++)
            {   
                addrs[i]->a = Random.Range(1f, 50f);
            }
        }
    }

    struct Crasher
    {
       unsafe public  float a;        
    }
}

#1849
16:32, 6 июня 2020

DemiosFantasimo
> Что я понял не так или может проблема в Юнити?
По ходу всё таки Юнити кривит. Попробовал на 2 подверсиях 2019 - повторилось. А вот на 2020 - нормально работает.

#1850
(Правка: 11:56) 11:51, 8 июня 2020

DemiosFantasimo
> По ходу всё таки Юнити кривит. Попробовал на 2 подверсиях 2019 - повторилось. А
> вот на 2020 - нормально работает.

1. Это ничего не значит. Повреждения памяти приводят к непредсказуемым эффектам. Всё может работать или не работать в зависимости от фазы Луны.

2. Когда ты пишешь unsafe и что-то начинает крашиться, проблема на 100% у тебя в unsafe. Допускать другие варианты непродуктивно.

3. Так нельзя:

fixed (Crasher* f = &c[i])
{
  addrs[i] = f;
}
Ты зафиксировал массив c в памяти (100 раз подряд) и записал в массив addrs адреса его элементов для будущего использования. Но за пределами блока fixed массив c больше не зафиксирован и волен перемещаться по памяти как будет угодно сборщику мусора.

Когда ты потом по этим адресам что-то пишешь:

addrs[i]->a = Random.Range(1f, 50f);
по ним уже может располагаться что-то другое.

Менеджер памяти в Unity вроде раньше не перемещал объекты в управляемой куче и такое могло прокатывать (не уверен). Но в NET Framework/Core так точно нельзя.

Два решения:

а) Фиксировать массив c в памяти пожизненно и потом не забыть освободить:

GCHandle h = GCHandle.Alloc(c, GCHandleType.Pinned);
IntPtr p = h.AddrOfPinnedObject();
...
h.Free();
б) Выделять массив структур сразу в неуправляемой памяти:
IntPtr p = Marshal.AllocHGlobal(100 * sizeof(Crasher));
...
Marshal.FreeHGlobal(p);
или просто использовать NativeArray<T>, что по сути то же самое, но удобнее.

#1851
16:34, 8 июня 2020

И ещё, ошибок вроде нет, но в контексте использования unsafe очень опасно обращаешься с верхней границей массивов:

1. Два раза повторяется константа 100
2. В одном цикле ещё она же, но в виде i<=99
3. В другом цикле опять она же, но в виде i<=100-1

Объяви как константу один раз в одном месте. Если нужно будет изменить значение, очень легко забыть поменять его везде, а потом Unity начнёт изредка падать без видимых причин, а почему ― пойди найди.

#1852
18:50, 8 июня 2020

alexzzzz
Спасибо.  Узнал много интересного.

> Marshal
а вот этого поцана не гугл вообще не показывал.

Пока остановился на NativArray (хотя  увидел что там целый пласт по распаралеливанию)
Побенчмаркил. Чисто через кучу оказывается гораздо менее производительно. Не думал что на столько))). Видимо придется балансировать между удушием уборщика мусора и скоростью стека.
С одной стороны рад что не придется сидеть в 2020. Там криво открывается  IDE, но с другой стороны там производительность вроде по лучше. в 2019  100 моих мобов в редакторе показывала 30-40 фпс. В 2020 таже сцена до 80 фпс. А когда пофиксил ошибку так вообще за 100 улетала.

#1853
19:10, 8 июня 2020

DemiosFantasimo
> > Marshal
> а вот этого поцана не гугл вообще не показывал.

В этом классе много разного обычно ненужного, но Marshal.AllocHGlobal / Marshal.FreeHGlobal ― это стандартный в NET способ выделять/освобождать память в неуправляемой куче.

В Unity есть ещё свои способы: UnsafeUtility.Malloc / UnsafeUtility.Free
https://docs.unity3d.com/ScriptReference/Unity.Collections.LowLev… eUtility.html

#1854
19:24, 8 июня 2020

Ой, блин, был уверен, что кроме fixed наверняка есть ещё ошибка в unsafe-коде, но в упор не видел.

Массив c локальный, за пределами Start на него не остаётся ссылок, сборщик мусора его убивает при первой возможности, и адреса в массиве addrs начинают ссылаться на что-угодно, только не на элементы уже не существующего массива c.

#1855
19:45, 8 июня 2020

alexzzzz
> Ой, блин, был уверен, что кроме fixed наверняка есть ещё ошибка в unsafe-коде,
> но в упор не видел.
>
> Массив c локальный, за пределами Start на него не остаётся ссылок, сборщик
> мусора его убивает при первой возможности, и адреса в массиве addrs начинают
> ссылаться на что-угодно, только не на элементы уже не существующего массива c.
Да, дело для меня пока темное))))

#1856
20:48, 8 июня 2020

Если массив c из локальной переменной переделать в поле класса, то Unity падать перестанет, скорее всего. Ссылка на массив будет храниться внутри экземпляра класса MemoryScript и у сборщика мусора не будет права такой массив удалять.

Но если совсем по-хорошему, то массив перед вычислением адресов всё-таки надо зафиксировать в памяти через GCHandle.Alloc(c, GCHandleType.Pinned), чтобы даже теоретически не мог по ней перемещаться.

#1857
21:26, 8 июня 2020

Есть еще буферы фиксированного размера.
Выделяют память внутри структуры.

Плюс -  еще один способ выделить память, которая не подвергается сборке мусора и перемещениям.
stackallocвыделяет память в стеке.

Плюсы - быстрое выделение и доступ. Автоматическое освобождение.
Минус - действительно только в том методе, где выделяется.

#1858
12:53, 9 июня 2020

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

#1859
14:27, 9 июня 2020

Я просто не правильно понял как правильно выделять память. От туда и понеслось. Ну это не за один день доходит учитывая что потуги осмысливания отягощены послерабочей прострацией

Страницы: 1123 124 125 126129 Следующая »
UnityФорумОбщее