204 lines
6.6 KiB
C#
204 lines
6.6 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Unity.Netcode;
|
|
using UnityEngine;
|
|
|
|
namespace Northbound
|
|
{
|
|
/// <summary>
|
|
/// 네트워크 연결 및 스폰 관리
|
|
/// </summary>
|
|
public class NetworkConnectionHandler : MonoBehaviour
|
|
{
|
|
[Header("Spawn Settings")]
|
|
public List<Transform> spawnPoints = new List<Transform>();
|
|
public bool useRandomSpawn = false;
|
|
public bool findSpawnPointsAutomatically = true;
|
|
|
|
private Dictionary<ulong, int> _clientSpawnIndices = new Dictionary<ulong, int>();
|
|
private int _nextSpawnIndex = 0;
|
|
|
|
// ⭐ Awake에서 스폰 포인트 먼저 찾고, 콜백 등록
|
|
private void Awake()
|
|
{
|
|
// 1️⃣ 먼저 스폰 포인트 찾기
|
|
if (findSpawnPointsAutomatically)
|
|
{
|
|
FindSpawnPoints();
|
|
}
|
|
|
|
// 2️⃣ 그 다음 콜백 등록
|
|
if (NetworkManager.Singleton != null)
|
|
{
|
|
NetworkManager.Singleton.ConnectionApprovalCallback = ApprovalCheck;
|
|
NetworkManager.Singleton.OnServerStarted += OnServerStarted;
|
|
NetworkManager.Singleton.OnClientConnectedCallback += OnClientConnected;
|
|
}
|
|
else
|
|
{
|
|
}
|
|
}
|
|
|
|
private void FindSpawnPoints()
|
|
{
|
|
PlayerSpawnPoint[] points = FindObjectsByType<PlayerSpawnPoint>();
|
|
|
|
// spawnIndex로 정렬
|
|
var sortedPoints = points.OrderBy(p => p.spawnIndex == -1 ? int.MaxValue : p.spawnIndex);
|
|
|
|
spawnPoints.Clear();
|
|
foreach (var point in sortedPoints)
|
|
{
|
|
if (point != null && point.transform != null && point.isAvailable)
|
|
{
|
|
spawnPoints.Add(point.transform);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnServerStarted()
|
|
{
|
|
|
|
if (ServerResourceManager.Instance == null)
|
|
{
|
|
GameObject resourceManagerObj = new GameObject("ServerResourceManager");
|
|
ServerResourceManager manager = resourceManagerObj.AddComponent<ServerResourceManager>();
|
|
|
|
NetworkObject networkObject = resourceManagerObj.GetComponent<NetworkObject>();
|
|
if (networkObject == null)
|
|
{
|
|
networkObject = resourceManagerObj.AddComponent<NetworkObject>();
|
|
}
|
|
|
|
networkObject.Spawn();
|
|
}
|
|
|
|
if (NetworkManager.Singleton.IsHost)
|
|
{
|
|
SpawnPlayer(NetworkManager.Singleton.LocalClientId);
|
|
}
|
|
}
|
|
|
|
private void OnClientConnected(ulong clientId)
|
|
{
|
|
if (!NetworkManager.Singleton.IsServer) return;
|
|
if (clientId == NetworkManager.Singleton.LocalClientId) return;
|
|
|
|
|
|
if (!NetworkManager.Singleton.ConnectedClients.TryGetValue(clientId, out var client) || client.PlayerObject != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SpawnPlayer(clientId);
|
|
}
|
|
|
|
private void SpawnPlayer(ulong clientId)
|
|
{
|
|
Vector3 spawnPosition = GetSpawnPosition(clientId);
|
|
Quaternion spawnRotation = GetSpawnRotation(clientId);
|
|
|
|
GameObject playerPrefab = NetworkManager.Singleton.NetworkConfig.PlayerPrefab;
|
|
if (playerPrefab == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
GameObject playerObject = Instantiate(playerPrefab, spawnPosition, spawnRotation);
|
|
NetworkObject networkObject = playerObject.GetComponent<NetworkObject>();
|
|
if (networkObject == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// 서버 소유권으로 스폰
|
|
networkObject.SpawnWithOwnership(NetworkManager.ServerClientId);
|
|
|
|
// 플레이어 컨트롤러 초기화
|
|
var playerController = playerObject.GetComponent<NetworkPlayerController>();
|
|
if (playerController != null)
|
|
{
|
|
playerController.Initialize(clientId);
|
|
}
|
|
}
|
|
|
|
private void ApprovalCheck(
|
|
NetworkManager.ConnectionApprovalRequest request,
|
|
NetworkManager.ConnectionApprovalResponse response)
|
|
{
|
|
spawnPoints.RemoveAll(p => p == null);
|
|
|
|
if (spawnPoints.Count == 0)
|
|
{
|
|
}
|
|
|
|
response.Approved = true;
|
|
response.CreatePlayerObject = false;
|
|
response.Position = Vector3.zero;
|
|
response.Rotation = Quaternion.identity;
|
|
}
|
|
|
|
private Vector3 GetSpawnPosition(ulong clientId)
|
|
{
|
|
spawnPoints.RemoveAll(p => p == null);
|
|
|
|
if (spawnPoints.Count == 0)
|
|
{
|
|
return Vector3.zero;
|
|
}
|
|
|
|
int spawnIndex;
|
|
|
|
if (useRandomSpawn)
|
|
{
|
|
spawnIndex = Random.Range(0, spawnPoints.Count);
|
|
}
|
|
else
|
|
{
|
|
if (!_clientSpawnIndices.ContainsKey(clientId))
|
|
{
|
|
_clientSpawnIndices[clientId] = _nextSpawnIndex;
|
|
_nextSpawnIndex = (_nextSpawnIndex + 1) % spawnPoints.Count;
|
|
}
|
|
spawnIndex = _clientSpawnIndices[clientId];
|
|
|
|
if (spawnIndex >= spawnPoints.Count)
|
|
{
|
|
spawnIndex = spawnIndex % spawnPoints.Count;
|
|
}
|
|
}
|
|
|
|
return spawnPoints[spawnIndex].position;
|
|
}
|
|
|
|
private Quaternion GetSpawnRotation(ulong clientId)
|
|
{
|
|
spawnPoints.RemoveAll(p => p == null);
|
|
|
|
if (spawnPoints.Count == 0)
|
|
return Quaternion.identity;
|
|
|
|
int spawnIndex = _clientSpawnIndices.ContainsKey(clientId)
|
|
? _clientSpawnIndices[clientId]
|
|
: 0;
|
|
|
|
if (spawnIndex >= spawnPoints.Count)
|
|
{
|
|
spawnIndex = spawnIndex % spawnPoints.Count;
|
|
}
|
|
|
|
return spawnPoints[spawnIndex].rotation;
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (NetworkManager.Singleton != null)
|
|
{
|
|
NetworkManager.Singleton.ConnectionApprovalCallback = null;
|
|
NetworkManager.Singleton.OnServerStarted -= OnServerStarted;
|
|
NetworkManager.Singleton.OnClientConnectedCallback -= OnClientConnected;
|
|
}
|
|
}
|
|
}
|
|
}
|