Привет, будущий гений игровых миров!
Ты когда-нибудь задумывался, как в играх получается так, что ты видишь своего друга, бегаешь с ним и сражаешься с монстрами, хотя он сидит у себя дома? Это всё магия программирования, и называется она Netcode.
Давай вместе разберемся, как эта магия работает, на примере специального инструмента Unity Netcode for GameObjects. Представь, что это набор волшебных раций и инструментов для твоих игровых персонажей.
Что такое Unity Netcode for GameObjects?
Unity — это огромный конструктор, где создаются игры.
GameObjects (Игровые Объекты) — это всё, что есть в игре: твой герой, враги, сундуки, пули, машинки.
Netcode (Неткод) — это специальный язык, на котором игровые объекты из разных компьютеров "разговаривают" друг с другом через интернет.
Получается, Unity Netcode for GameObjects — это набор правил и инструментов, который помогает объектам в игре, созданной на Unity, общаться между собой по сети.
Главные волшебные инструменты
Чтобы наши игровые объекты научились общаться, у них должны быть специальные "детали". Давай посмотрим на самые главные.
1. Волшебная метка: NetworkObject (Сетевой Объект)
Что это? Это самая первая и главная метка, которую ты должен "приклеить" к своему игроку, монстру или любому другому предмету, который должны видеть все игроки.
Зачем она? Эта метка говорит игре: "Внимание! Этот объект — участник сетевой игры. Его нужно показывать всем!" Без этой метки твой персонаж будет виден только на твоем экране.
2. Волшебное Зеркало: NetworkTransform (Сетевая Трансформация)
Что это? Это как волшебное зеркало, которое постоянно следит за тем, где находится твой объект и куда он повернут.
Зачем оно? Оно автоматически сообщает всем игрокам координаты и поворот твоего персонажа. Когда ты бежишь вперед,
NetworkTransform
говорит всем: "Герой Вася побежал вперед!" И все видят на своих экранах, как твой герой бежит. Это самый простой способ синхронизировать движение.
3. Общая Доска для Записей: NetworkVariable (Сетевая Переменная)
Что это? Представь себе волшебную доску, на которой можно написать что-то важное, и это увидят все игроки. Например, количество здоровья, очков или цвет твоего персонажа.
Зачем она? Если ты подобрал монетку и у тебя стало 10 очков, игра записывает "10" в эту переменную. И все остальные игроки сразу видят: "Ага, у него 10 очков!"
NetworkVariable
— это общая память для всех.
Пример кода с NetworkVariable
Давай представим, что у нашего игрока есть здоровье.
// Подключаем библиотеку Netcode
using Unity.Netcode;
using UnityEngine;
public class PlayerStats : NetworkBehaviour
{
// Создаем "сетевую переменную" для здоровья.
// Она будет хранить целое число (int) и будет видна всем (ReadPermission.Everyone).
// Начальное значение - 100.
public NetworkVariable<int> health = new NetworkVariable<int>(100, NetworkVariableReadPermission.Everyone);
// Эта функция вызывается, когда наш игрок появляется в сетевой игре
public override void OnNetworkSpawn()
{
// Мы "подписываемся" на изменения.
// Если значение health изменится, игра вызовет нашу функцию OnHealthChanged.
health.OnValueChanged += OnHealthChanged;
}
// Эта функция будет вызвана автоматически при изменении здоровья
private void OnHealthChanged(int previousValue, int newValue)
{
Debug.Log($"Здоровье игрока {OwnerClientId} изменилось с {previousValue} на {newValue}");
// Здесь можно добавить эффект ранения или обновить полоску здоровья на экране.
}
// Когда объект удаляется из сети, нужно отписаться от событий
public override void OnNetworkDespawn()
{
health.OnValueChanged -= OnHealthChanged;
}
}
Что происходит в коде?
public NetworkVariable<int> health = new ...
— мы создаем специальную сетевую переменнуюhealth
, в которой будет храниться здоровье. Все игроки могут видеть ее значение.health.OnValueChanged += OnHealthChanged;
— мы даем игре команду: "Когда значениеhealth
изменится, пожалуйста, выполни код из функцииOnHealthChanged
".OnHealthChanged(...)
— в этой функции мы можем написать логику, которая должна сработать при изменении здоровья. Например, вывести сообщение в консоль или обновить интерфейс.
4. Громкий Крик Главному: ServerRpc (Вызов на сервере)
Что это? В сетевых играх есть "главный" — сервер. Он следит за порядком и принимает важные решения.
ServerRpc
— это как громкий крик твоего персонажа серверу: "Эй, главный, я хочу что-то сделать!"Зачем оно? Для важных действий, которые должны быть честными для всех. Например, ты хочешь открыть сундук. Ты не можешь сделать это сам (вдруг другой игрок успел раньше?). Ты отправляешь серверу запрос
ServerRpc
: "Прошу открыть этот сундук!" Сервер проверяет, можно ли это сделать, и если да, то открывает его для всех. Это защищает игру от читерства.
Пример кода с ServerRpc
Игрок хочет поменять свой цвет и просит об этом сервер.
// Подключаем библиотеку Netcode
using Unity.Netcode;
using UnityEngine;
public class PlayerActions : NetworkBehaviour
{
// Эта переменная будет хранить цвет и синхронизироваться между всеми
public NetworkVariable<Color> playerColor = new NetworkVariable<Color>(Color.white);
private MeshRenderer _meshRenderer;
void Awake()
{
// Находим компонент один раз и "запоминаем" его
_meshRenderer = GetComponent<MeshRenderer>();
}
void Update()
{
// Проверяем, что это наш собственный персонаж, которым мы управляем
if (!IsOwner)
{
return;
}
// Если мы нажали на кнопку "R"
if (Input.GetKeyDown(KeyCode.R))
{
// Мы вызываем функцию, которая отправит запрос на сервер
RequestRandomColorServerRpc();
}
}
// Это специальная метка, которая говорит, что функция выполняется на СЕРВЕРЕ
[ServerRpc]
private void RequestRandomColorServerRpc()
{
// Этот код выполнится на сервере!
// Сервер генерирует случайный цвет и меняет его в сетевой переменной
Color randomColor = new Color(Random.value, Random.value, Random.value);
playerColor.Value = randomColor;
}
// Эта функция будет постоянно обновлять цвет модельки у всех игроков
void LateUpdate()
{
// Используем уже найденный компонент
_meshRenderer.material.color = playerColor.Value;
}
}
Что происходит в коде?
if (Input.GetKeyDown(KeyCode.R))
— игрок нажимает клавишу.RequestRandomColorServerRpc();
— он вызывает у себя функцию с меткой[ServerRpc]
. Но на самом деле эта команда "улетает" по сети на сервер.[ServerRpc] private void RequestRandomColorServerRpc()
— сервер получает команду и выполняет код внутри этой функции: генерирует случайный цвет и кладет его в сетевую переменнуюplayerColor.Value
.Поскольку
playerColor
— этоNetworkVariable
, все остальные игроки тут же узнают о новом цвете, и ихLateUpdate
покрасит нужную модельку.
5. Объявление от Главного Всем: ClientRpc (Вызов на клиентах)
Что это? Это когда сервер, наоборот, хочет что-то объявить всем игрокам (их называют клиентами). Например: "Внимание! Через 10 секунд начнется буря!" или "Игра окончена! Победила команда синих!".
Зачем оно? Чтобы все игроки одновременно узнали о каком-то важном событии, которое решил устроить сервер. Это позволяет синхронизировать эффекты, звуки и события на всех компьютерах.
Пример кода с ClientRpc
Сервер решил, что игра окончена, и объявляет об этом всем.
// Подключаем библиотеку Netcode
using Unity.Netcode;
using UnityEngine;
public class GameEvents : NetworkBehaviour
{
// Представим, что сервер вызывает эту функцию, когда игра заканчивается
public void EndGame()
{
// Только сервер может объявлять такие вещи
if (!IsServer) return;
// Сервер вызывает команду, которая "улетит" ко всем клиентам
AnnounceWinnerClientRpc("Красная команда");
}
// Это специальная метка, которая говорит, что функция выполняется на КАЖДОM КЛИЕНТЕ
[ClientRpc]
private void AnnounceWinnerClientRpc(string winnerName)
{
// Этот код выполнится на компьютере каждого игрока!
Debug.Log($"Игра окончена! Победитель: {winnerName}");
// Здесь можно показать красивый экран победы
}
}
Что происходит в коде?
Сервер по какой-то причине решает закончить игру и вызывает
EndGame()
.Внутри он вызывает функцию
AnnounceWinnerClientRpc("Красная команда")
с меткой[ClientRpc]
.Эта команда улетает всем подключенным игрокам.
На компьютере каждого игрока выполняется код из
AnnounceWinnerClientRpc
, и все видят сообщение о победителе.
Как все это собрать вместе?
Представь простого игрока, который может двигаться и менять цвет.
Ты создаешь объект игрока в Unity.
Добавляешь ему компонент
NetworkObject
, чтобы он стал сетевым.Добавляешь
NetworkTransform
, чтобы его движение автоматически синхронизировалось.-
Пишешь скрипт, похожий на
PlayerActions
из примера выше. В нем:В функции
Update
ты проверяешьif (IsOwner)
и считываешь нажатия клавиш (W, A, S, D), чтобы двигать персонажа. Так как на нем естьNetworkTransform
, его позиция сама улетит другим игрокам.Там же ты проверяешь нажатие другой клавиши (например, "R") и вызываешь
ServerRpc
, чтобы попросить сервер поменять твой цвет.Сервер меняет цвет в
NetworkVariable
.Все игроки видят изменение цвета, потому что
NetworkVariable
для всех общая.
Вот так, шаг за шагом, используя эти волшебные инструменты, ты можешь создавать свои собственные миры, в которые можно будет пригласить друзей!
max-daniels
А как подключаться друг к другу?
TatianaZo Автор
Если у игры есть выделенный сервер, то все игроки подключаются к этому серверу как клиенты.
Если сервера нет, то один игрок становится хостом(и сервером, и игроком одновременно), а все остальные подключаются к нему как клиенты.
// Запустить как Хост
Unity.Netcode.NetworkManager.Singleton.StartHost();
// Запустить как Клиент
Unity.Netcode.NetworkManager.Singleton.StartClient();