KoIIIeY

На Пикабу
поставил 12 плюсов и 6 минусов
Награды:
5 лет на Пикабу
522 рейтинг 2 подписчика 2 подписки 9 постов 5 в горячем

Unity UDP P2P (напрямую и через собственный релэй)

И так, вам захотелось добавить сетевуху в вашу игру, и вы не хотите фотон (например потому что нас сейчас отключают везде где могут :) )


Когда-то я сделал ставку на оклусовскую сетевуху для нашей игры, и на сегодняшний день это вылилось в переписывание половины игры (и ф*йс*ук забанен, и сетевуху свою они сворачивают), но так же наша команда написала свой собственный релэй-сервер на C# (http://gitlab.sa-wd.ru/DarkanSoince/networking/-/tree/v3).


Как писать.


Шишек набито достаточно, так что вот вам описание на пальцах как делать сетевуху:

1) Пакет из байтов для отправки делаем под 500-1200 байт (есть мнение про 500, я использую 1000)

2) В пакет влазит еще? - суем, а не отправляем отдельным пакетом
3) Не влазит? отправляем и забиваем новый пакет вне таймера
4) Отправляем по таймерам, а не по кадрам (хотя тут как хотите)

5) Поскольку все пакеты одинаковые, не пересоздаем пакет, а заменяем в нём данные перед отправкой

6) Reliable пакеты отправляем только когда надо знать что пакет дошел (например, отправить старт игры - релиэйбл, движение - не релиэйбл)

7) Если вам надо менять состояние чего-либо, что меняется часто (например владелец предмета), посылаем это состояние в каждом пакете, а не отдельной командой для смен состояния (например вместе с движением).


Простой путь - смотрите тут примеры - http://gitlab.sa-wd.ru/DarkanSoince/networking/-/tree/v3/Program

Смените IP на 127.0.0.1 тут - http://gitlab.sa-wd.ru/DarkanSoince/networking/-/blob/v3/Networking/ClientProgram.cs

Запускать сначала мастер, потом два клиента.

cd .\Program\Master\
dotnet run --framework net6.0
cd .\Program\Client\
dotnet run --framework net6.0

Сервер запустит и после отключения клиентов убьет мастер.


Сложный путь. Штош, перейдем к коду.


Мы используем гугл-протобаф для сериализации/десериализации и первым делом вам надо будет взять и понаписать файлов в /Proto/Event (смотрим код репы, читаем тут https://developers.google.com/protocol-buffers/docs/proto3#scalar) про каждый тип пакета, который вы вообще умеете отправлять.


Допустим что мы хотим что бы персонаж ходил

ProtoTransform.proto (пример названия файла в /Proto/Event)
syntax = "proto3";
package protos;
message ProtoTransform {
int32 netId = 1;  // что двигаем
float positionX = 2; 
float positionY = 3; 
float positionZ = 4;
float rotationX = 5; 
float rotationY = 6; 
float rotationZ = 7; 
float rotationW = 8; 
int32 sequence = 9; // счетчик, который всегда идет вверх
float velocityX = 10; 
float velocityY = 11; 
float velocityZ = 12; 
int32 playerId = 14; 
float angularVelocityX = 15; 
float angularVelocityY = 16; 
float angularVelocityZ = 17;
}

Зачем sequence - что бы два раза не делать одно и то же если пакет пришел позже следующего (а он может и прийти не по порядку и не прийти вовсе, просто при отправке его плюсуем)


Тыкаем build proto.bat, всё, магия готова и наш протофайл сбилжен :)


Тыкаем unity package.bat и у нас в папке /UnityPackage появится билд сетевухи


Запускаем юнити

Window -> package manager -> + -> add package from disk -> папка /UnityPackage/package.json


// Это будет наш нетворкинг. Да, весь в одном файле :)
using SAWD.Networking;
public class SAWDNet : MonoBehaviour {
public enum MessageType {
Transform = 100, // это что бы не перебивать значения из скомпилленого файла
LuboeDrudoe = 101
}
Protos.ProtoTransform protoSendTransform = new Protos.ProtoTransform();
private void Start() {
clientProgram = new ClientProgram();
clientProgram.Start();
clientProgram.Enqueue_ToMaster("default"); // http://gitlab.sa-wd.ru/DarkanSoince/networking/-/blob/v3/Program/Master/.env (этот дэфаулт - QUEUE_default= отсюда, а не из Name, обязательно законфигить под себя!)
// входящий пакет с трансформом
Net.On((int) MessageType.Transform, (point, data) => { // входящий трансформ
var protoOnReceiveTransform = ProtoTransform.Parser.ParseFrom(data.Data);
// protoOnReceiveTransform вот ваш пакет данных, делайте что хотите с ним
});
// я подключился к серверу
Net.On((int) Net.MessageType.Server_Connected, ((point, data) => {
Debug.Log("-Server_Connected- SAWDNet.localPlayerId:" + SAWDNet.localPlayerId);
var connected = Proto.Event.Connected.Parser.ParseFrom(data.Data);
Debug.Log("-Server_Connected- connected:" + connected);
foreach (var userId in connected.Ids) {
Debug.Log("-Server_Connected- userId:" + userId);
//RemoteUser.CreateUser(userId);
// создайте тут юзера (аватар и тд с ид userId). Тут могут быть дубли, создавайте один раз на юзера!
}
}));
// кто-то подключился к серверу после меня
Net.On((int) Net.MessageType.Server_AnotherUserConnected, ((point, data) => {
var connected = Proto.Event.Connected.Parser.ParseFrom(data.Data);
//RemoteUser.CreateUser(connected.Id);
Debug.Log("-Server_AnotherUserConnected- connected:" + connected);

SendTransform(); // один раз отправим трансформ новому подключившемуся

}));

}


private void Update()

{
Net.Update();
if (!Debug.isDebugBuild) return;
while (Net.Logs.TryDequeue(out var log)) {
Debug.Log(log); // у сетевухи разные треды, читаем лог в главном треде
}
}


private void SendTransform(){
// отправка один раз для примера
protoSendTransform.PositionX = lastLocalPosition.x;
protoSendTransform.PositionY = lastLocalPosition.y;
protoSendTransform.PositionZ = lastLocalPosition.z;
Net.Broadcast(GroupType.Client | GroupType.Server, (int) SAWDNet.MessageType.Transform, protoSendTransform , true); // тру значит релиэйбл, будет долбить пока не передаст, ВАМ тут тру не надо, вам надо фолс :)
}


Запускаем сервер


cd .\Program\Master\
dotnet run --framework net6.0

(проверяем что IP мастер сервера в клиенте указан верно, иначе ничего не подключится! http://gitlab.sa-wd.ru/DarkanSoince/networking/-/blob/v3/Networking/ClientProgram.cs)


Запускаем пару клиентов. После коннекта они отправят и получат protoSendTransform или через сервер или напрямую, если они смогут подключиться.


Может быть когда-нибудь я осилю написать нормальную документацию.

Показать полностью

Система локализации озвучки игр с плагином для Unity, упрощенная

На этот раз - двухмышекликовая реализация. (видео и текст +- одно и то же)

В самом конце поста суперкоротий текстовый туториал что бы очень быстро попробовать.

Что нам понадобится:

1. Unity, хоть с добавленной стандартной локализацией, хоть без неё


2. https://github.com/KoIIIeY/SAWDAudioManager.git - только вот этот урл, который мы положим в Window -> Package Manager -> + -> Add package from GIT url


3. Аккаунт на https://audio.sa-wd.ru


Если вы еще не пользовались стандартной системой локализации - создайте настройки локализации (Edit-> Project settings -> Localization)


Теперь или добавьте или выберите любой AudioSource(компонент на игровом объекте), нажмите правой кнопкой мыши и нажмите Localize.


Кроме стандартных полей локализации вы увидите два поля для логина и пароля и поле для ИД игры.


Зарегистрируйтесь на https://audio.sa-wd.ru и создайте игру.

Система локализации озвучки игр с плагином для Unity, упрощенная Gamedev, Разработка, Озвучка, Инди, Звук, Туториал, Видео, YouTube, Длиннопост

В первом окне после создания игры возьмите ID игры.

Система локализации озвучки игр с плагином для Unity, упрощенная Gamedev, Разработка, Озвучка, Инди, Звук, Туториал, Видео, YouTube, Длиннопост

Вернитесь в Unity, выберите любой GameObject на котором есть локализованный звук, введите логин и пароль, нажмите Login, после введите ID игры и нажмите установить ID игры.

Система локализации озвучки игр с плагином для Unity, упрощенная Gamedev, Разработка, Озвучка, Инди, Звук, Туториал, Видео, YouTube, Длиннопост

Если у вас уже заполнены таблицы со звуками в проекте на Unity - нажмите Create online structure - это загрузит ваши звуки на сайт вместе с переводами в том же виде, как оно уже у вас сделано, при этом таблица ассетов на сайте станет пакетом (с тем же именем), а каждый звук получит тот же тег, что присвоен ему в игре.


Дальше на сайте перейдите в Packages для вашей игры (базовым пакетом считается первый язык в списке) - вы увидите свои звуки.

Теперь зовёте вашего актёра озвучки/переводчика или другого человека, который делает вам перевод и просите его зарегистрироваться.

Добавляете его по емэйлу в доступы (внизу страницы игры)

Переводчик жмет на сайте в "пакетах" создать пакет на основе базового пакета и просто добавляет звуки рядом с оригиналом.

Система локализации озвучки игр с плагином для Unity, упрощенная Gamedev, Разработка, Озвучка, Инди, Звук, Туториал, Видео, YouTube, Длиннопост

Вы как разработчик далее в Unity возвращаетесь к любому локализованному аудиосурсу и жмете Download online structure (есть одно НО - если структура пакетов была создана из игры, звуки создадутся заново и таблицу ассетов перепишет, тут мне очень жаль, но не придумал как сделать лучше).

Система локализации озвучки игр с плагином для Unity, упрощенная Gamedev, Разработка, Озвучка, Инди, Звук, Туториал, Видео, YouTube, Длиннопост

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


Еще раз один клик - и переводы с новой озвучкой в игре :)
Пост длинный, а по факту всё работает в две кнопки.

Но про бэкап не забываем, конечно же.

=========================================================

=========================================================
Суперкороткий туториал что бы быстро попробовать (занимает около 3х минут если вы еще и пойдете попить чаю):
1) создайте пустой проект

2) https://github.com/KoIIIeY/SAWDAudioManager.git засуньте в Window -> Package Manager -> + -> Add package from GIT url

3) создайте любой AudioSource

4) ткните на аудиосурсе Localize(правой кнопкой мыши по компоненту аудиосурса),

5) авторизуйтесь, впишите game_id = 1 (это будет AirHockeyVR) и нажмите Download

6) откройте Window -> Asset management -> Localization Tables -> радуйтесь что звуки прилетели в игру, а вы ничего для этого не делали :)

Показать полностью 5

Система озвучки игр (с плагином для Unity)

Наша маленькая команда сделала игру AirHockeyVR под Oculus Quest, в ней есть обучение на английском языке, которое записал ютюбер, который сначала записал видео про игру -> мне понравился его голос -> я попросил его сделать озвучку -> он согласился и записал.


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


И теперь я представляю это решение вам :)


Вот что вам понадобится:

https://audio.sa-wd.ru/ - тут заливать звуки

https://audio.sa-wd.ru/storage/package/SAWDAudioManager.unit... - плагин для Unity


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

И не надо.


Что бы звуки грузились в игру, вы просто подписываетесь на делегат в SAWDAudioManager когда вам нужно получить звуки (делегат возвращает наборы звуков по тэгу), и отписываетесь когда они вам больше не нужны.


Для случаев, когда у вас один AudioSource с одним звуком - докидываете хелпер, в котором указываете тэг [и сабтэг, опционально] звука.

Система озвучки игр (с плагином для Unity) Unity, Звук, Gamedev, Разработка, Озвучка, Инди

Предполагается так: только тег - это набор звуков, один созданный звук на сайте может быть перезалит набором звуков (для примера - это звук удара шайбы). Если есть сабтэг - значит это один звук, который заменяется один на один (для примера - это фраза "добро пожаловать!").


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


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

В AirHockeyVR я подписался на изменения звуков обучения, написал в нашем дискорде, и нашелся француз, который записал для нас французский перевод - так что идея вполне работает :)

Так же я попросил своего друга записать перевод на русский язык.


И вообще любой человек или группа людей может записать перевод для вашей игры - и сразу же добавить его в релизную версию (разработчик всё еще должен будет заапрувить этот аудиопакет, иначе он не появится в игре).


Проект в альфа-релизе, но уже пора пробовать - я морально готов к допилам на основе комментариев :)

Показать полностью 1

AirHockeyVR теперь бесплатный на Сайдквесте! (полная игра, но без мультиплеера)

AirHockeyVR теперь бесплатный на Сайдквесте! (полная игра, но без мультиплеера) Виртуальная реальность, Борьба с пиратством, Airhockeyvr



Настал день, когда нашу игру взломали и выпустили в мир пираты.

Бороться с пиратством в нашем случае бессмысленно, поэтому теперь вы можете попробовать нашу игру, просто установив ее из сайдквеста.

Игра полная, нет никаких временных или других ограничений, кроме того, что мультиплеер по-прежнему платный (в пиратской версии он был недоступен вообще).


Надеюсь, пиратят не всё подряд, а только то, что интересно, поэтому считаю это комплиментом нашей игре.

Приглашаю вас попробовать! - https://sidequestvr.com/app/4709/airhockeyvr-physically-base... :)


Не призываю вас перестать пиратить, но наш AirHockeyVR из леваков не ставить, мультиплеера там всё равно не будет!

Показать полностью

AirHockeyVR в дополненной реальности

Смотрите что у нас тут :)

Раздаем AirHockeyVR для Oculus Quest

Раздаем AirHockeyVR для Oculus Quest Oculus Quest, Раздача игр, Airhockeyvr

Всем привет, столкнулись с проблемой маленького онлайна, так что раздаем ключи :)
Заходите на https://sa-wd.ru, вбивайте свой окулусовский никнейм и получайте код.

Или в дискорде - https://discord.gg/67DSxZgKqw, просто напишите "Please give me a key" и бот даст ключ.


Окулусовскмй никнейм я не собираюсь использовать никак, кроме подсчета количества использованных ключей, потому что генерить ключи налету нельзя, а знать что код использован надо.


Из нового: шайба больше не выпрыгивает со стола, звук потише стал... в общем, пробуйте :)

Показать полностью

Как мы сделали AirHockeyVR за один день

Добавилась самая простая фича, какую можно придумать - несколько шайб на столе :)
С двумя шайбами игра становится гораздо активнее.


В прошлый раз я получил невероятный упрек, мол всё у нас сделано из ассетов и делается за один день :D
Сегодня я приоткрою занавесу тайны и расскажу немного о разработке.


Меня зовут Павел, и представиться я решил к окончанию написания поста, потому что представил команду ниже :)

Игра делается где-то с 20 января 2021 года, практически с момента как я получил свой окулус квест.

В это же время мы с командой начали думать что бы нам сделать - хотелось что-то не сильно дизайнерское (нас 3 кодера в команде, дизайнера нет), сетевое и при этом VRное, чего еще нет в природе (а в январе мы под окулус не нашли ни одного аэрохоккея, хотя видели что есть для десктопа).

Изначально решили что это будет просто хоккей, но увы, оказалось что его уже кто-то придумал.
Рома (один из нас, разработчиков) предложил делать аэрохоккей и собственно, начали.


Начал я с того, что написал невероятно стремный питч на пропуск в официальный магазин окулусов - нам ответили

Thank for taking the time to submit your pitch.
After a thorough review of your submission, your application has not been accepted to receive Oculus Quest publishing access at this time. Your application is, however, a good candidate for the Oculus Start.
Соответственно, записались в старт, где-то в мае получили первый квест(третий шлем в команде уже), худи, носки, ручку, тетрадь и провод, все это с пересылкой из США через знакомых друзей знакомых :)

Никита (тоже один из нас, разработчиков) так же купил шлем, получил его в феврале(это второй шлем).


Начали мы с сетевой части и капли дизайна - взяли пример с сетью из окулусовских и Рома замоделил нам первый стол и шайбу с битами.

Сеть в примере была реализована напрямую, без каких-либо оберток, поэтому я лично быстренько перепутал инт и байт, запаковал/распаковал не правильно и неделю думал почему же сеть не работает.

А еще мы тогда не знали про андройд логкат, и честно дебажили все какими-то хаками, написанными собственноручно (у нас даже и в дебаггере был баг и он не работал какое-то время) :D
Никита в то время пробовал всякие разные решения для упаковки пакетов и мы пришли к гугловскому протобафу (и очень рады в итоге, очень нравится и очень удобно).

С сетевой физикой проблем практически не было, не на что пожаловаться, кроме того очевидного факта, что она сразу же не заработала (но все равно мы её очень быстро додумали, так что это изи).

Изначально в планах не было 3-4 человек в игре, поэтому делали только 1 на 1.
Что в итоге привело к тому, что пришлось все переделывать, потому что пример с 1 на 1 совершенно не подходил к реалиям комнат - во первых тем, что у нас не работал VOIP.


Во вторых, оказалось, что шайба при игре на троих периодически виснет посередине без особых на то причин. Начал искать причины - и честно не нашел, просто стер нафиг часть сетевого кода и написал заново иначе. Стало лучше, пока что не мечта, но в целом играбельно.



Время шло, подали запрос на аппрув игры в апп лаб, за 40 дней игра этот аппрув почти прошла, но закинули не правильный логотип (непрозрачный), за что получили еще 11 дней штрафа без аппрува.


После аппрува мне очень захотелось явить игру миру, что я и сделал... Люди с запада приняли тепло, наш же народ начал писать мол тени ваши говно, рука сквозь стол проходит и вообще мол настольный теннис выглядит и лучше и удобнее. Пригорел я, конечно, но виду почти не подал :D


Начал запекать свет, все запек, и оказалось, что нельзя просто взять, запечь и потом сменить статичный стол с одного на другой, потому что стол опять начинает отбрасывать реалтаймовые тени. В общем, запек три раза под три стола, тени на столах выключил, теперь переключаю лайтмапы :)

Рома тем временем сменил дизайны столов, меню и счёта, опять же потому, что люди кликали все кнопки что были, а кнопки не работали, перелопатил кучу нашего кода и вообще всяко все улучшил.

Никита тем же временем (да и прямо вот сейчас) написал нам простого скриптованного бота, а сейчас пишет бота на искусственном интеллекте, который в скором времени будет готов.


Из купленных/взятых асссетов в игре - аватары, вода и P2P от окулуса в плане трубы, куда можно кидать байтики и сама идея из реального мира. Все остальное смоделено, скодено и придумано нами. 

Сам себя не похвалишь - никто не похвалит, так что с чистой душой напишу - игра получилась отличной, она делает то что мы хотели что бы она делала :)


P.S. возможно, когда-нибудь, мы и правда сделаем так, что бы руки не проходили сквозь стол и что бы шайба не летала.

Как мы сделали AirHockeyVR за один день Виртуальная реальность, Аэрохоккей, Gamedev, Видеоигра, Видео, Длиннопост, Airhockeyvr
Показать полностью 1

Мы сделали VR Аэрохоккей для Oculus Quest

Отличная работа, все прочитано!