Очень много крутой жизненной информации. Спасибо что оставляешь свои ошибки - это очень важно. Я долгое время думал, что хороший программист не ошибается и пишет крутой код, но по факту хороший программист умеет справляться с ошибками. Сложно учиться глядя на идеальный кодинг, здорово, что у тебя не так.
Когда что-то делается впервой - без ошибок не обойтись. Хотя, будем честны, даже не в первой - достаточно много времени должно пройти, когда ты сможешь делать, зная все подводные камни наперёд.
Очень рад, что ты возобновил выпуск роликов)) хотелось бы увидеть ролик про multiplayer в unity, возможно серию роликов как про фотон в своё время была))
Одни из лучших видосов на ютубе по юнити имхо. Недавно закончил смотреть курс Сакутина по шарпу и вот переключился на твои туториалы по юнити - это просто нечто, все круто и что самое главное, можно учиться и на твоих ошибках 🔥
Также код террейн генератора В ChunkRenderer в строках private const int ChunkWidth = 10; private const int ChunkHeight = 128; замените private на public. И строки Blocks[0, 0, 0] = 1; Blocks[1, 0, 0] = 1; замените на Blocks = TerrainGenerator.GenerateTerrain((int)transform.position.x, (int)transform.position.z); Код TerrainGenerator: using UnityEngine; public static class TerrainGenerator { public static int[,,] GenerateTerrain(int xOffset, int zOffset) { var result = new int[ChunkRenderer.ChunkWidth, ChunkRenderer.ChunkHeight, ChunkRenderer.ChunkWidth]; for (int x = 0; x < ChunkRenderer.ChunkWidth; x++) { for (int z = 0; z < ChunkRenderer.ChunkWidth; z++) { float height = Mathf.PerlinNoise((x + xOffset) * .2f, (z + zOffset) * .2f) * 5 + 10; for (int y = 0; y < height; y++) { result[x, y, z] = 1; } } } return result; } }
Было бы интересно посмотреть на создание плюс-минус реалистичного генератора рек в этом проекте, с местами вытекания и впадения. Отличная подача, удачи в проекте!
Ещё один крутой момент, избавление от дублирования в коде. Вещь понятная, важная, полезная, но к ней приходится приучиваться. Большинство учаться на задачах очень далёких и по структуре и по объёму от реальных, и такой острой необходимости в этой практике нет. В итоге всю важность осознаёшь когда видишь кашу из кода в проекте.
Спасибо за видео. Я сейчас делаю игру не майн-подобную, но там всё равно есть генерация из кода. И твой пример генерации меша и т.д. хорошо поясняет как это удобно и не сложно делать.)
Как это целую неделю ждать?????????? Давай хотя бы через день или 2, ну много неделя, оочень много, с таким наслождением я давно не смотрел ролик в ютубе!
Разрешите слегка прикопаться ) 15:39 - можно сразу без else return ) А так клево, прям тоже хотел сесть разбираться с майном, для меня очень востребовано) По генерации я так понял уже все записано, но если интересно в Онигири вроде видел генерацию.
Спасибо за отличное видео! Впр пока все достаточно просто, но когда я пытался сделать свой кубический клон, испытал кучу проблем именно с материалами, эх, сколько убитых нервных клеток было(* Даже вспоминать страшно. С нетерпением жду продолжение
Все получилось, спасибо автору. Много чего не понятно, потому что я не настолько искушен в программировании, да и С# осваиваю самостоятельно. Однако, кто из новичков столкнется с проблемами в данном видео (ввиде неправильной генерации блоков) попробуйте поменять лево и право, скорее всего как и у автора у вас будет такая же проблема.)
Капееец, какая крутая тема и какая крутая реализация, я просто в афиге, открыл чтобы просто посмотреть как это всё делается, но чёт сейчас хочется повторить.
Ну реализация на самом деле фиговая. Если использовать преимущества ООП, а именно создание класса для блока, полигона и прочего, а также использовать энумераторы, то будет всё выглядеть намного проще и понятнее. Сейчас же его код выглядит как каша из функций, в которую постоянно могут добавляться новые и ты таким образом просто запутаешься в этом всём.
@@NeznamoAnonimovich создавать класс под каждый логический примитив это верный путь увести производительность в ноль. Когда надо обрабатывать блоки миллионами, приходится отсекать лишние абстракции и работать с чистыми массивами и структурами. Абстракции можно расположить уровнем выше, на сущностях и чанках
Респект за панель справа :). Такая же фигня. Заметил когда переключал рабочие столы и напоролся на твою панель, и почему-то там были не те программы что у меня. Не сразу понял в чем дело. Ахаха.
блин... крутой контент, я не так давно работаю с юнити, и искал чтобы еще новенького придумать и тут залетает эмеральд со своим четким контентом, один словом ждем продолжения)
0:00 - наверное очередное проходное видео для просмотров. 0:05 - а это уже интересно 0:20 - таааак 0:26 - таааааааак 0:30 - ну, это я уже видел. 4:17 ну тут я бы сделал 0, 1, 2. 0 - воздух, 1 - земля, а 2 - камень, что бы потом не переписывать код с высотами. (тут я могу быть не прав, просто сказал свой личный ход мысли)
Начал делать похожий проект, но на другом языке и движке. До этого особо не вдавался в подробности отрисовки графики. По началу не понял почему полигоны видно с разных сторон, поэтому видео помогло.
6:42 . Кстати лайфхак, для того чтобы изменить положение строки в райдере нужно нажать Ctrl+Alt+Shift+Up или Ctrl+Alt+Shift+Down, а если стоят хоткеи как в VS то Alt+Down или Alt+Up
Очень много меняешь строчки местами, так что вот лайфхак для райдера - Ctrl + alt + up arrow/down arrow чтобы переместить строку. Очень удобно) еще можно целые функции перемещать, вроде еще шифт тогда надо зажать P.s. за лайфхак с константами (Ctrl+alt+f) - отдельное спасибо)
Ролик хороший, но хотелось бы добавить, я сам начал делать еще год назад по популярным видеоурокам зарубежного автора, идея моей игры не майнкрафт но игра в воксельном стиле, поэтому примерно на средине я отвалился от автора и ушел в собственное написание движка. Что хочу заметить, старайтесь использовать и хранить воксели в Dictionary списках по uint ключу, это во много раз ускорит обращение к вокселю по координатам и упростит работу алгоритму поиска, вектор в данном случае будет лишним для хранения плавающих значений которые здесь не исользуються, а вот преобразование получаемой позиции в uint ключ "битовые операции" это уже правильно, к тому же не создавайте массивы формата 16х255х16 как имеет чанк, этот массив будет иметь так же и пустые блоки которые для обработки не нужны, но при этом занимают память в ОЗУ, Dictionary здесь лучшее решение.
Ну и второй момент, это mesh, здесь могу добавить только что старайтесь сразу сделать greedy mesh так как это: 1. увеличивает фпс и снижает нагрузку на устройство в 70%, 2. экономит кучу системной памяти, ведь в простом алгоритме отбраковки на каждый "квадратик" приходиться по 4 вершины и по 2 треугольника, если более по простому то на один полноценный куб висящий в воздухе приходиться 24 вершины место 8-ми как должно. Поэтому советую изучить материал Mikola Lysenko который уже реализовал подобное, даже есть исходники на github от других людей которые реализовали правильную uv развёртку. У меня игра после данной оптимизации стала потреблять раза так в 2.5 меньше ОЗУ чем это было до оптимизации. Ну и перерасчёты стали быстрее
Спасибо за советы! Да, я там уже в одной из следующих серий записал как откажусь от 3д массива, чтобы всё это ускорить. И на greedy meshing натыкался, но его пока не реализовал, спсибо за наводку
Весь ролик идёт разговор об оптимизации, но упускается несколько интересных вещей. В юнити (как и в других движках) есть статик батчинг и гпу инстансинг. Работает это крайне просто - геймобджекты с одинаковой моделью (идентичным мешем/геометрией) и с одинаковым материалом (который кстати может использоваться на все сотни блоков майна с одной текстурой и ещё рендериться с двух сторон) объединяются в один объект что значительно сокращает дроу коллы. Сам в этом убедился когда создавал дизайн локации. Сначала сделал несколько модулей и из нескольких сотен собрал одну локацию. После завершения прототипа в юнити собрал всю локацию одним мешем в блендере. И сюрприз сюрприз - вызовов отрисовки было ровно столько же, сколько и с несколькими сотнями модулей при статик батчинге. Так что смело предположу что все танцы с бубнами про генерацию меша ради оптимизации не сильно нужны. Для справки: статик батчинг работает на объектах с включённой галочкой "Static" и за счёт галочки объекты не смогут двигаться. ГПУ инстансинг работает только на динамических моделях. Советую ознакомиться с этими фичами если слышите о них впервые
А как же ломание/добавление блоков? Получится ли при включенном "Static" менять меш? Также с сохранением, как сохранить и потом загрузить то, что понастроил игрок? Static было бы удобно использовать, если бы окружение нельзя было изменить
@@mdlka_ Так а в чём проблема? Ты просто наплодишь лярды кубов, а потом будешь их отключать/удалять. Отдельными геймобджектами. И статик остаётся, и изменяемость будет. Типа оно тупо все кубики на сцене слепит в один большой меш и всё
@@dareskull6541 При таком решении билд раздуется до слишком большого размера, тк будет хранить очень большой меш. + как с этим работать в юнити? Если я правильно тебя понял, то сцена будет забита кубами. И скорее всего такая сцена будет жутко лагать Вообще много проблем с этим решением придет, но это первое, что в голову пришло
Статик батчинг можно использовать, но на десятках тысяч кубов он всё равно будет плохо работать. Из-за того что там более общий и сложный алгоритм, + геймобджекты никуда не денутся, которые не самые лёгкие свами по себе. Плюс там мы не сможем отдельные грани отключать, и убирать целые кубы которые внутри чанка находятся. Кстати выключать/включать статик обьекты насколько я помню не очень хорошая практика, там тогда же весь батч будет перевычисляться, но вместо неё для игр с автогенерацией можно использовать StaticBatchingUtility, чтобы вызвать статик батчинг в рантайме, а не для заготовленной сцены Ну а gpu instancing конечно тоже поможет, но опять же, 100к кубов отрендерить будет намного сложнее чем сгенерировать один полигон и отрисовать его. Но интересно как-нибудь устроить сравнение фпс на разных размерах миров с таким подходом
@@EmeraldPowder Ещё вспомнил из оптимизации такие техники как HLODы (известны в анриле, но в юнити особо никто ничего не снимал) и импостеры. Ну так, чисто если охота будет заморочиться и сравнить все варианты оптимизации) И спасибо за ответ. Я как 3д дизайнер не особо шарю, чисто что по туторам нашёл, так что спасибо за пояснение
Если у каждого чанка свой массив blocks и свой renderer, то получается на границе чанков таки будут отрисовываться лишние грани, так как блоки рядом будут находиться уже в другом чанке, т.е. вне массива blocks.
@@exLeute и в правду, фраза "целый бок состоит из полигонов" во время первого просмотра была воспринята неверно. Получается мой комментарий почти не имеет смысла :I
для оптимизации сделай статический и динамический батчинг а ещё сделай Occlusion Culling. Так же желательно сделать свою систему света как в майнкрафте (она реализована при помощи гаммы и цветов)
Очень много крутой жизненной информации. Спасибо что оставляешь свои ошибки - это очень важно. Я долгое время думал, что хороший программист не ошибается и пишет крутой код, но по факту хороший программист умеет справляться с ошибками. Сложно учиться глядя на идеальный кодинг, здорово, что у тебя не так.
потому что любая ошибка это опыт) т.е. получаем в несколько раз больше опыта чем с идеальным кодом)
Когда что-то делается впервой - без ошибок не обойтись.
Хотя, будем честны, даже не в первой - достаточно много времени должно пройти, когда ты сможешь делать, зная все подводные камни наперёд.
Я понял такую вещь, хороший программист тот, кто быстро может нагуглить решение своей проблемы.
Классс. Твои уроки одни из лучших. А такая серия вероятно окажется брилиантом на твоём канале.
Очень рад, что ты возобновил выпуск роликов)) хотелось бы увидеть ролик про multiplayer в unity, возможно серию роликов как про фотон в своё время была))
Зачем фотон если есть уже мультик от юнитеков. Netcode.
Одни из лучших видосов на ютубе по юнити имхо. Недавно закончил смотреть курс Сакутина по шарпу и вот переключился на твои туториалы по юнити - это просто нечто, все круто и что самое главное, можно учиться и на твоих ошибках 🔥
Спасибо за видос и что вернулся и живой! Продолжай выпускать видосы!
Ты вернулся! Ура
Совершенно не занимаюсь юнити разработкой, но видео посмотрел с удовольствием) Спасибо)
Отличная идея для серии видео, будет безумно интересно посмотреть/послушать о реализации!
Спасибо, что вернулся. Твои видосы самые крутые. Уже давно юнити не занимаюсь, но все равно смотрю этот видос, потому что кайф
Код из видео(без ошибок):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
public class ChunkRenderer : MonoBehaviour
{
private const int ChunkWidth = 10;
private const int ChunkHeight = 128;
public int[,,] Blocks = new int[ChunkWidth, ChunkHeight, ChunkWidth];
private List verticies = new List();
private List triangles = new List();
void Start()
{
Mesh chunkMesh = new Mesh();
Blocks[0, 0, 0] = 1;
Blocks[1, 0, 0] = 1;
for (int y = 0; y < ChunkHeight; y++)
{
for (int x = 0; x < ChunkWidth; x++)
{
for (int z = 0; z < ChunkWidth; z++)
{
GenerateBlock(x, y, z);
}
}
}
chunkMesh.vertices = verticies.ToArray();
chunkMesh.triangles = triangles.ToArray();
chunkMesh.RecalculateNormals();
chunkMesh.RecalculateBounds();
GetComponent().mesh = chunkMesh;
}
private void GenerateBlock(int x, int y, int z)
{
var blockPosition = new Vector3Int(x, y, z);
if (GetBlockAtPosition(blockPosition) == 0) return;
if (GetBlockAtPosition(blockPosition + Vector3Int.right) == 0) GenerateRightSide(blockPosition);
if (GetBlockAtPosition(blockPosition + Vector3Int.left) == 0) GenerateLeftSide(blockPosition);
if (GetBlockAtPosition(blockPosition + Vector3Int.forward) == 0) GenerateFrontSide(blockPosition);
if (GetBlockAtPosition(blockPosition + Vector3Int.back) == 0) GenerateBackSide(blockPosition);
if (GetBlockAtPosition(blockPosition + Vector3Int.up) == 0) GenerateTopSide(blockPosition);
if (GetBlockAtPosition(blockPosition + Vector3Int.down) == 0) GenerateBottomSide(blockPosition);
}
private int GetBlockAtPosition(Vector3Int blockPosition)
{
if (blockPosition.x >= 0 && blockPosition.x < ChunkWidth &&
blockPosition.y >= 0 && blockPosition.y < ChunkHeight &&
blockPosition.z >= 0 && blockPosition.z < ChunkWidth)
{
return Blocks[blockPosition.x, blockPosition.y, blockPosition.z];
}
else
{
return 0;
}
}
private void GenerateRightSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(1, 0, 0) + blockPosition);
verticies.Add(new Vector3(1, 1, 0) + blockPosition);
verticies.Add(new Vector3(1, 0, 1) + blockPosition);
verticies.Add(new Vector3(1, 1, 1) + blockPosition);
AddLastVerticiesSquare();
}
private void GenerateLeftSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(0, 0, 0) + blockPosition);
verticies.Add(new Vector3(0, 0, 1) + blockPosition);
verticies.Add(new Vector3(0, 1, 0) + blockPosition);
verticies.Add(new Vector3(0, 1, 1) + blockPosition);
AddLastVerticiesSquare();
}
private void GenerateFrontSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(0, 0, 1) + blockPosition);
verticies.Add(new Vector3(1, 0, 1) + blockPosition);
verticies.Add(new Vector3(0, 1, 1) + blockPosition);
verticies.Add(new Vector3(1, 1, 1) + blockPosition);
AddLastVerticiesSquare();
}
private void GenerateBackSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(0, 0, 0) + blockPosition);
verticies.Add(new Vector3(0, 1, 0) + blockPosition);
verticies.Add(new Vector3(1, 0, 0) + blockPosition);
verticies.Add(new Vector3(1, 1, 0) + blockPosition);
AddLastVerticiesSquare();
}
private void GenerateTopSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(0, 1, 0) + blockPosition);
verticies.Add(new Vector3(0, 1, 1) + blockPosition);
verticies.Add(new Vector3(1, 1, 0) + blockPosition);
verticies.Add(new Vector3(1, 1, 1) + blockPosition);
AddLastVerticiesSquare();
}
private void GenerateBottomSide(Vector3Int blockPosition)
{
verticies.Add(new Vector3(0, 0, 0) + blockPosition);
verticies.Add(new Vector3(1, 0, 0) + blockPosition);
verticies.Add(new Vector3(0, 0, 1) + blockPosition);
verticies.Add(new Vector3(1, 0, 1) + blockPosition);
AddLastVerticiesSquare();
}
private void AddLastVerticiesSquare()
{
triangles.Add(verticies.Count - 4);
triangles.Add(verticies.Count - 3);
triangles.Add(verticies.Count - 2);
triangles.Add(verticies.Count - 3);
triangles.Add(verticies.Count - 1);
triangles.Add(verticies.Count - 2);
}
}
Также код террейн генератора
В ChunkRenderer в строках
private const int ChunkWidth = 10;
private const int ChunkHeight = 128;
замените private на public.
И строки
Blocks[0, 0, 0] = 1;
Blocks[1, 0, 0] = 1;
замените на
Blocks = TerrainGenerator.GenerateTerrain((int)transform.position.x, (int)transform.position.z);
Код TerrainGenerator:
using UnityEngine;
public static class TerrainGenerator
{
public static int[,,] GenerateTerrain(int xOffset, int zOffset)
{
var result = new int[ChunkRenderer.ChunkWidth, ChunkRenderer.ChunkHeight, ChunkRenderer.ChunkWidth];
for (int x = 0; x < ChunkRenderer.ChunkWidth; x++)
{
for (int z = 0; z < ChunkRenderer.ChunkWidth; z++)
{
float height = Mathf.PerlinNoise((x + xOffset) * .2f, (z + zOffset) * .2f) * 5 + 10;
for (int y = 0; y < height; y++)
{
result[x, y, z] = 1;
}
}
}
return result;
}
}
Лучший
здоровье тебе и близким
Очень интересно, продолжай в том же духе!
Было бы интересно посмотреть на создание плюс-минус реалистичного генератора рек в этом проекте, с местами вытекания и впадения. Отличная подача, удачи в проекте!
Не смотрел сразу лайк, чувак твои видео всегда в радость)
Ещё один крутой момент, избавление от дублирования в коде. Вещь понятная, важная, полезная, но к ней приходится приучиваться. Большинство учаться на задачах очень далёких и по структуре и по объёму от реальных, и такой острой необходимости в этой практике нет. В итоге всю важность осознаёшь когда видишь кашу из кода в проекте.
Не знаю, почему надо приучиваться, если достаточно ленивый, то изначально харит переписывать строчки, которые уже писал и хочется вынести в функцию)
Надо же
Собирался как раз делать свой майнкрафт и бац) Новый ролик
Спасибо
Очень круто, ждал какого-то ролика и не думал о таком, но с твоей подачей даже это интересно смотреть и слушать!
Спасибо за видео. Я сейчас делаю игру не майн-подобную, но там всё равно есть генерация из кода. И твой пример генерации меша и т.д. хорошо поясняет как это удобно и не сложно делать.)
Интересно, жду следующие видосы из цикла!
Как это целую неделю ждать??????????
Давай хотя бы через день или 2, ну много неделя, оочень много, с таким наслождением я давно не смотрел ролик в ютубе!
Ты не представляешь как я ждал что-то подобное
Кажется мы наблюдаем начало долгого путешествия длиною в десятки тысяч чанков
Очень круто продолжай
Разрешите слегка прикопаться )
15:39 - можно сразу без else return )
А так клево, прям тоже хотел сесть разбираться с майном, для меня очень востребовано)
По генерации я так понял уже все записано, но если интересно в Онигири вроде видел генерацию.
Круто что продолжаешь делать видива!
Отлично, класс, спасибо. Хорошо, что ты вернулся.
Спасибо за отличное видео! Впр пока все достаточно просто, но когда я пытался сделать свой кубический клон, испытал кучу проблем именно с материалами, эх, сколько убитых нервных клеток было(* Даже вспоминать страшно. С нетерпением жду продолжение
Вот это нереально полезно! Спасибо! Лучше серию уроков и представить сложно
Нужная механика и самый классный Unity разработчик на Ютубе 😍
Отличный канал, Ты можешь.
Привет!
Круто делаешь, очень интересно наблюдать)
Вау, проект очень сложный и интересный. Давно слежу за тобой, ты красавчик 💪
Спасибо огромное за подсказки лайк автоматом, а за идею и другие ролики подписка))
классный видос. Планирую когда-нибудь добавить строительство кастомных домиков, скорее всего придётся пользоваться генерацией мешей по координатам
Все получилось, спасибо автору. Много чего не понятно, потому что я не настолько искушен в программировании, да и С# осваиваю самостоятельно. Однако, кто из новичков столкнется с проблемами в данном видео (ввиде неправильной генерации блоков) попробуйте поменять лево и право, скорее всего как и у автора у вас будет такая же проблема.)
Мы сейчас увидим чертовски мощную оптимизацию 3д мира из миллиарда деталек (в данном случае блоков)? Вот это по мне, нравится.
Такая оптимизация используеться во всех вокссельных мирах, если тебе это интересно посмотри про greed meshing это уже посложнее
Но и рендер чанка ускоряеться в несколько раз
ооо, прикольный проэкт, хорошая идея!)
Капееец, какая крутая тема и какая крутая реализация, я просто в афиге, открыл чтобы просто посмотреть как это всё делается, но чёт сейчас хочется повторить.
Ну реализация на самом деле фиговая. Если использовать преимущества ООП, а именно создание класса для блока, полигона и прочего, а также использовать энумераторы, то будет всё выглядеть намного проще и понятнее. Сейчас же его код выглядит как каша из функций, в которую постоянно могут добавляться новые и ты таким образом просто запутаешься в этом всём.
@@NeznamoAnonimovich создавать класс под каждый логический примитив это верный путь увести производительность в ноль. Когда надо обрабатывать блоки миллионами, приходится отсекать лишние абстракции и работать с чистыми массивами и структурами.
Абстракции можно расположить уровнем выше, на сущностях и чанках
Спасибо, что сделал этот видос, как раз хочу начать разрабатывать игру с графикой похожей на Майнкрафт
Очень круто! Жду следующих видео.
Да это полезно знать, что можно делать с мешь сеткой на низком уровне. Очень интересно. Хотелось по подробнее немного
Это. Просто. Охрененно.
Респект за панель справа :). Такая же фигня. Заметил когда переключал рабочие столы и напоролся на твою панель, и почему-то там были не те программы что у меня. Не сразу понял в чем дело. Ахаха.
Выглядит максимально щикорно
Про материалы очень интересно будет послушать!
Да и в целом ролик очень крутой.
Очень интересно, будем посмотреть.
Наконец-то ты вернулся
Очень интересное видео. Я в предвкушении что будет дальше. Действительно круто, автор молодец.
Очень жду продолжения, автор продолжай пожалуйста)😃
блин... крутой контент, я не так давно работаю с юнити, и искал чтобы еще новенького придумать и тут залетает эмеральд со своим четким контентом, один словом ждем продолжения)
Годнота, очень полезно для прокачки навыков!
Великолепный обучающий видос
Вижу новый ролик ставлю сразу лайк)
0:00 - наверное очередное проходное видео для просмотров.
0:05 - а это уже интересно
0:20 - таааак
0:26 - таааааааак
0:30 - ну, это я уже видел.
4:17 ну тут я бы сделал 0, 1, 2. 0 - воздух, 1 - земля, а 2 - камень, что бы потом не переписывать код с высотами. (тут я могу быть не прав, просто сказал свой личный ход мысли)
Круть, лучший канал по программированию !
Топ контент, как всегда
Отличный урок.Спасибо большое,давно хотел сделать нечто подобное,но не сильно понимал,как работает генерация меша .
Начал делать похожий проект, но на другом языке и движке. До этого особо не вдавался в подробности отрисовки графики. По началу не понял почему полигоны видно с разных сторон, поэтому видео помогло.
делай что угодно. буду ставить лайки комментарии писать, что бы видео продвигалось )
Класс. Спасибо тебе за такие классные ролики
Магия за 20 минут. Жду продолжения))
6:42 . Кстати лайфхак, для того чтобы изменить положение строки в райдере нужно нажать Ctrl+Alt+Shift+Up или Ctrl+Alt+Shift+Down, а если стоят хоткеи как в VS то Alt+Down или Alt+Up
Как всегда информативно и с простой подачей
Продолжайте было интересно
Выглядит легко и лаконично, спасибо.
Очень круто, хотим продолжения!
Топ 👍👍👍
Очень много меняешь строчки местами, так что вот лайфхак для райдера - Ctrl + alt + up arrow/down arrow чтобы переместить строку. Очень удобно) еще можно целые функции перемещать, вроде еще шифт тогда надо зажать
P.s. за лайфхак с константами (Ctrl+alt+f) - отдельное спасибо)
По размеру блоков больше похоже на терарию чем на майн, но красиво вышло
Найс! Спасибо за видео :)
*Прикольно получилось*
Видео очень хорошее,узнал много чего нового,спасибо) очень надеюсь что ты будешь учить делать файтинг:)
Вот это доброе утро😳
Ролик хороший, но хотелось бы добавить, я сам начал делать еще год назад по популярным видеоурокам зарубежного автора, идея моей игры не майнкрафт но игра в воксельном стиле, поэтому примерно на средине я отвалился от автора и ушел в собственное написание движка. Что хочу заметить, старайтесь использовать и хранить воксели в Dictionary списках по uint ключу, это во много раз ускорит обращение к вокселю по координатам и упростит работу алгоритму поиска, вектор в данном случае будет лишним для хранения плавающих значений которые здесь не исользуються, а вот преобразование получаемой позиции в uint ключ "битовые операции" это уже правильно, к тому же не создавайте массивы формата 16х255х16 как имеет чанк, этот массив будет иметь так же и пустые блоки которые для обработки не нужны, но при этом занимают память в ОЗУ, Dictionary здесь лучшее решение.
Ну и второй момент, это mesh, здесь могу добавить только что старайтесь сразу сделать greedy mesh так как это: 1. увеличивает фпс и снижает нагрузку на устройство в 70%, 2. экономит кучу системной памяти, ведь в простом алгоритме отбраковки на каждый "квадратик" приходиться по 4 вершины и по 2 треугольника, если более по простому то на один полноценный куб висящий в воздухе приходиться 24 вершины место 8-ми как должно. Поэтому советую изучить материал Mikola Lysenko который уже реализовал подобное, даже есть исходники на github от других людей которые реализовали правильную uv развёртку. У меня игра после данной оптимизации стала потреблять раза так в 2.5 меньше ОЗУ чем это было до оптимизации. Ну и перерасчёты стали быстрее
Спасибо за советы! Да, я там уже в одной из следующих серий записал как откажусь от 3д массива, чтобы всё это ускорить. И на greedy meshing натыкался, но его пока не реализовал, спсибо за наводку
о теперь хоть знаю как сделать не плоский уровень, для какой нибудь 2д игры))
Класс, копатель онлайн своими руками!
Очень жду такое видео под Unreal Engine :D
Спасибо! очень интересно тебя слушать
Лучший !
Жду следующие видео!!!!
Очень буду ждать от автора видео по DOTS, когда выйдет релиз.
Комментарий для продвижения канала
Удачи тебе (:
Ваааааай, классно
Великолепно
Класс, побольше бы физики рассмотреть в уроках)
Удачи
Просто лучший
продолжай снимать про Майнкрафт
Cool )
Top👍
Весь ролик идёт разговор об оптимизации, но упускается несколько интересных вещей. В юнити (как и в других движках) есть статик батчинг и гпу инстансинг. Работает это крайне просто - геймобджекты с одинаковой моделью (идентичным мешем/геометрией) и с одинаковым материалом (который кстати может использоваться на все сотни блоков майна с одной текстурой и ещё рендериться с двух сторон) объединяются в один объект что значительно сокращает дроу коллы.
Сам в этом убедился когда создавал дизайн локации. Сначала сделал несколько модулей и из нескольких сотен собрал одну локацию. После завершения прототипа в юнити собрал всю локацию одним мешем в блендере. И сюрприз сюрприз - вызовов отрисовки было ровно столько же, сколько и с несколькими сотнями модулей при статик батчинге. Так что смело предположу что все танцы с бубнами про генерацию меша ради оптимизации не сильно нужны.
Для справки: статик батчинг работает на объектах с включённой галочкой "Static" и за счёт галочки объекты не смогут двигаться. ГПУ инстансинг работает только на динамических моделях. Советую ознакомиться с этими фичами если слышите о них впервые
А как же ломание/добавление блоков? Получится ли при включенном "Static" менять меш? Также с сохранением, как сохранить и потом загрузить то, что понастроил игрок?
Static было бы удобно использовать, если бы окружение нельзя было изменить
@@mdlka_ Так а в чём проблема? Ты просто наплодишь лярды кубов, а потом будешь их отключать/удалять. Отдельными геймобджектами. И статик остаётся, и изменяемость будет. Типа оно тупо все кубики на сцене слепит в один большой меш и всё
@@dareskull6541 При таком решении билд раздуется до слишком большого размера, тк будет хранить очень большой меш. + как с этим работать в юнити? Если я правильно тебя понял, то сцена будет забита кубами. И скорее всего такая сцена будет жутко лагать
Вообще много проблем с этим решением придет, но это первое, что в голову пришло
Статик батчинг можно использовать, но на десятках тысяч кубов он всё равно будет плохо работать. Из-за того что там более общий и сложный алгоритм, + геймобджекты никуда не денутся, которые не самые лёгкие свами по себе. Плюс там мы не сможем отдельные грани отключать, и убирать целые кубы которые внутри чанка находятся. Кстати выключать/включать статик обьекты насколько я помню не очень хорошая практика, там тогда же весь батч будет перевычисляться, но вместо неё для игр с автогенерацией можно использовать StaticBatchingUtility, чтобы вызвать статик батчинг в рантайме, а не для заготовленной сцены
Ну а gpu instancing конечно тоже поможет, но опять же, 100к кубов отрендерить будет намного сложнее чем сгенерировать один полигон и отрисовать его. Но интересно как-нибудь устроить сравнение фпс на разных размерах миров с таким подходом
@@EmeraldPowder Ещё вспомнил из оптимизации такие техники как HLODы (известны в анриле, но в юнити особо никто ничего не снимал) и импостеры. Ну так, чисто если охота будет заморочиться и сравнить все варианты оптимизации)
И спасибо за ответ. Я как 3д дизайнер не особо шарю, чисто что по туторам нашёл, так что спасибо за пояснение
прекрасно, а теперь это всё надо запаковать в compute shader шобы летало и не отвлекало процессор
Убедительная просьба к автору в начале видео указывать версии ПО которым он пользуется. Это облегчит работу подписчикам а вам их прибавит)
Больше спасибо за урок
Если у каждого чанка свой массив blocks и свой renderer, то получается на границе чанков таки будут отрисовываться лишние грани, так как блоки рядом будут находиться уже в другом чанке, т.е. вне массива blocks.
Думаю, он пофиксит это :)
17:42
@@exLeute и в правду, фраза "целый бок состоит из полигонов" во время первого просмотра была воспринята неверно. Получается мой комментарий почти не имеет смысла :I
Да, всё правильно, на границах чанках с полигонами есть проблемы. Но во 2 части в том числе и это пофиксим :)
@@EmeraldPowderвопрос, у меня юнити пишет что на строке if(Blocks[x,y,z] == 0) return;
Оно выходит за пределы массива.
для оптимизации сделай статический и динамический батчинг а ещё сделай Occlusion Culling. Так же желательно сделать свою систему света как в майнкрафте (она реализована при помощи гаммы и цветов)
Оклюжин кулинг работает только на статике, а её тут нет от слова совсем!
@@DarkDGG так а в чём проблема сделать все блоки и чанки статичными?)
@@DarkDGG так же само и про статический батчинг он тоже только на статичное работает
@@SchlachtschiffBismarck-gf3fi в том, что нужна вероятно ГЕНЕРАЦИЯ и наверное, такая же возможность СЛОМАТЬ ВСЁ, что угодно - как в майнкрафте.
чуствую будто делаю игру без движка)
А будет часть с переписыванием кода на GPU? И стоит ли вообще переделывать генерацию такого меша под GPU?
присоединяюсь
очень понравилось повествование
Спасибо за видео. Интересно как систему строительства реализуешь