Примеры кода
Основы Netcode for GameObjects
Настройка базовой сетевой архитектуры и подключение клиентов.
using Unity.Netcode;
using UnityEngine;
using UnityEngine.UI;
public class NetworkManagerUI : MonoBehaviour
{
[Header("UI элементы")]
public Button hostButton;
public Button clientButton;
public Text statusText;
void Start()
{
hostButton.onClick.AddListener(StartHost);
clientButton.onClick.AddListener(StartClient);
Debug.Log("Network Manager UI инициализирован");
}
public void StartHost()
{
if (NetworkManager.Singleton.StartHost())
{
statusText.text = "Хост запущен успешно";
Debug.Log("Хост-сервер запущен");
}
else
{
statusText.text = "Ошибка запуска хоста";
}
}
public void StartClient()
{
if (NetworkManager.Singleton.StartClient())
{
statusText.text = "Подключение к серверу...";
Debug.Log("Клиент подключается");
}
else
{
statusText.text = "Ошибка подключения";
}
}
void Update()
{
if (NetworkManager.Singleton.IsHost)
{
statusText.text = $"Хост - Клиентов: {NetworkManager.Singleton.ConnectedClients.Count}";
}
else if (NetworkManager.Singleton.IsClient && NetworkManager.Singleton.IsConnectedClient)
{
statusText.text = "Подключен как клиент";
}
}
}
NetworkObjects и синхронизация
Работа с сетевыми объектами и их синхронизация между клиентами.
using Unity.Netcode;
using UnityEngine;
public class NetworkPlayer : NetworkBehaviour
{
[Header("Настройки игрока")]
public float moveSpeed = 5f;
private NetworkVariable<Vector3> networkPosition = new NetworkVariable<Vector3>();
private NetworkVariable<Color> playerColor = new NetworkVariable<Color>(
Color.white,
NetworkVariableReadPermission.Everyone,
NetworkVariableWritePermission.Owner
);
public override void OnNetworkSpawn()
{
playerColor.OnValueChanged += OnColorChanged;
networkPosition.OnValueChanged += OnPositionChanged;
if (IsOwner)
{
playerColor.Value = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
GetComponent<Renderer>().material.color = playerColor.Value;
Debug.Log($"Сетевой игрок создан. Владелец: {OwnerClientId}");
}
void Update()
{
if (IsOwner)
{
HandleMovement();
}
else
{
transform.position = Vector3.Lerp(transform.position, networkPosition.Value, Time.deltaTime * 10f);
}
}
void HandleMovement()
{
float horizontal = Input.GetAxis("Horizontal");
float vertical = Input.GetAxis("Vertical");
Vector3 movement = new Vector3(horizontal, 0, vertical) * moveSpeed * Time.deltaTime;
transform.Translate(movement);
networkPosition.Value = transform.position;
if (Input.GetKeyDown(KeyCode.C))
{
playerColor.Value = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));
}
}
void OnColorChanged(Color previousColor, Color newColor)
{
GetComponent<Renderer>().material.color = newColor;
Debug.Log($"Цвет игрока изменен на: {newColor}");
}
void OnPositionChanged(Vector3 previousPos, Vector3 newPos)
{
if (!IsOwner)
{
Debug.Log($"Позиция обновлена: {newPos}");
}
}
}
RPC и сетевая связь
Удаленные вызовы процедур для мгновенной связи между клиентами.
using Unity.Netcode;
using UnityEngine;
public class NetworkCommunication : NetworkBehaviour
{
void Update()
{
if (Input.GetKeyDown(KeyCode.T))
{
SendMessage($"Игрок {OwnerClientId}: Привет!");
}
if (Input.GetKeyDown(KeyCode.F))
{
NotifyAction("прыгнул");
}
}
public void SendMessage(string message)
{
if (IsOwner)
{
SendMessageServerRpc(message);
}
}
[ServerRpc]
void SendMessageServerRpc(string message)
{
Debug.Log($"Сервер получил: {message}");
ReceiveMessageClientRpc(message);
}
[ClientRpc]
void ReceiveMessageClientRpc(string message)
{
Debug.Log($"Сообщение: {message}");
}
public void NotifyAction(string action)
{
if (IsOwner)
{
NotifyActionServerRpc(OwnerClientId, action);
}
}
[ServerRpc]
void NotifyActionServerRpc(ulong playerId, string action)
{
NotifyActionClientRpc(playerId, action);
}
[ClientRpc]
void NotifyActionClientRpc(ulong playerId, string action)
{
Debug.Log($"Игрок {playerId} {action}");
}
}
NetworkVariables и состояние
Синхронизация состояния игры через NetworkVariables.
using Unity.Netcode;
using UnityEngine;
public class GameStateManager : NetworkBehaviour
{
private NetworkVariable<float> gameTime = new NetworkVariable<float>(300f);
private NetworkVariable<bool> gameActive = new NetworkVariable<bool>(false);
private NetworkVariable<int> playerCount = new NetworkVariable<int>(0);
public override void OnNetworkSpawn()
{
gameTime.OnValueChanged += OnTimeChanged;
gameActive.OnValueChanged += OnGameStateChanged;
playerCount.OnValueChanged += OnPlayerCountChanged;
if (IsServer)
{
UpdatePlayerCount();
}
Debug.Log("Game State Manager инициализирован");
}
void Update()
{
if (IsServer && gameActive.Value && gameTime.Value > 0)
{
gameTime.Value -= Time.deltaTime;
if (gameTime.Value <= 0)
{
EndGame();
}
}
if (Input.GetKeyDown(KeyCode.G) && IsHost)
{
if (!gameActive.Value)
StartGame();
else
EndGame();
}
}
void StartGame()
{
if (IsServer)
{
gameActive.Value = true;
gameTime.Value = 300f;
Debug.Log("Игра запущена!");
}
}
void EndGame()
{
if (IsServer)
{
gameActive.Value = false;
Debug.Log("Игра завершена!");
}
}
void UpdatePlayerCount()
{
if (IsServer)
{
playerCount.Value = NetworkManager.Singleton.ConnectedClients.Count;
}
}
void OnTimeChanged(float previousTime, float newTime)
{
Debug.Log($"Время игры: {newTime:F1} сек");
}
void OnGameStateChanged(bool previousState, bool newState)
{
Debug.Log($"Состояние игры: {(newState ? "Активна" : "Неактивна")}");
}
void OnPlayerCountChanged(int previousCount, int newCount)
{
Debug.Log($"Игроков подключено: {newCount}");
}
}
Простая мультиплеерная игра
Пример базовой мультиплеерной игры с очками и взаимодействием.
using Unity.Netcode;
using UnityEngine;
public class MultiplayerGame : NetworkBehaviour
{
[Header("Игровые объекты")]
public GameObject collectiblePrefab;
public Transform[] spawnPoints;
private NetworkVariable<int> playerScore = new NetworkVariable<int>(0);
private NetworkList<Vector3> collectiblePositions;
public override void OnNetworkSpawn()
{
if (IsServer)
{
collectiblePositions = new NetworkList<Vector3>();
SpawnCollectibles();
}
playerScore.OnValueChanged += OnScoreChanged;
Debug.Log("Мультиплеерная игра инициализирована");
}
void SpawnCollectibles()
{
if (IsServer)
{
for (int i = 0; i < 5; i++)
{
Vector3 randomPos = new Vector3(
Random.Range(-10f, 10f),
1f,
Random.Range(-10f, 10f)
);
var collectible = Instantiate(collectiblePrefab, randomPos, Quaternion.identity);
collectible.GetComponent<NetworkObject>().Spawn();
collectiblePositions.Add(randomPos);
}
Debug.Log("Предметы для сбора созданы");
}
}
void OnTriggerEnter(Collider other)
{
if (other.CompareTag("Collectible") && IsOwner)
{
CollectItemServerRpc();
}
}
[ServerRpc]
void CollectItemServerRpc()
{
playerScore.Value += 10;
Debug.Log($"Игрок {OwnerClientId} собрал предмет. Счет: {playerScore.Value}");
// Создание нового предмета
Vector3 newPos = new Vector3(
Random.Range(-10f, 10f),
1f,
Random.Range(-10f, 10f)
);
var newCollectible = Instantiate(collectiblePrefab, newPos, Quaternion.identity);
newCollectible.GetComponent<NetworkObject>().Spawn();
}
void OnScoreChanged(int previousScore, int newScore)
{
Debug.Log($"Счет обновлен: {newScore}");
UpdateScoreUI(newScore);
}
void UpdateScoreUI(int score)
{
// Обновление UI счета
var scoreText = GameObject.Find("ScoreText");
if (scoreText != null)
{
scoreText.GetComponent<UnityEngine.UI.Text>().text = $"Счет: {score}";
}
}
public void ResetGame()
{
if (IsServer)
{
ResetGameServerRpc();
}
}
[ServerRpc(RequireOwnership = false)]
void ResetGameServerRpc()
{
// Сброс счета всех игроков
foreach (var client in NetworkManager.Singleton.ConnectedClients.Values)
{
var playerGame = client.PlayerObject.GetComponent<MultiplayerGame>();
if (playerGame != null)
{
playerGame.playerScore.Value = 0;
}
}
Debug.Log("Игра сброшена");
}
}