네트워크 멀티플레이 테스트를 위한 코드 추가
This commit is contained in:
@@ -1,163 +0,0 @@
|
||||
# Connection Failure Troubleshooting Guide
|
||||
|
||||
## Problem: "Failed to connect to server" error
|
||||
|
||||
### Quick Fixes to Try
|
||||
|
||||
1. **Add NetworkDebugger to scene**
|
||||
- Add `NetworkDebugger` component to NetworkManager
|
||||
- Check Console for detailed connection logs
|
||||
- Look for:
|
||||
- Connection approval status
|
||||
- Transport binding errors
|
||||
- Timeout messages
|
||||
|
||||
2. **Add NetworkConnectionFixer to scene**
|
||||
- Add `NetworkConnectionFixer` component to NetworkManager
|
||||
- Right-click component → "Fix All Known Issues"
|
||||
- This auto-fixes common transport timeout issues
|
||||
|
||||
3. **Check Firewall (Most Likely Cause)**
|
||||
Even with port forwarding, Windows Firewall may block connections:
|
||||
|
||||
**Windows:**
|
||||
- Windows Security → Firewall & network protection → Allow an app through firewall
|
||||
- Add Unity Editor AND your built executable
|
||||
- Allow on both Private and Public networks
|
||||
- Add exception for port 7777 (or your port)
|
||||
|
||||
**Command Line (Quick Fix):**
|
||||
```
|
||||
netsh advfirewall firewall add rule name="Unity Network" dir=in action=allow protocol=TCP localport=7777
|
||||
```
|
||||
|
||||
4. **Verify Transport Settings**
|
||||
In Play mode, on NetworkManager → UnityTransport:
|
||||
- ConnectionData.Address should be `0.0.0.0` for Host/Server
|
||||
- ConnectionData.Port should be 7777 (or your forwarded port)
|
||||
- ServerListenAddress can be left default
|
||||
|
||||
5. **Test Port Forwarding**
|
||||
- Use online tool: https://www.yougetsignal.com/tools/open-ports/
|
||||
- Enter your public IP and port
|
||||
- Should show "Open" (not "Closed" or "Timed out")
|
||||
|
||||
6. **Disable IPv6 (Temporary Fix)**
|
||||
Some network configurations have IPv6 issues:
|
||||
```
|
||||
Control Panel → Network and Internet → Network Connections
|
||||
→ Right-click adapter → Properties → Uncheck Internet Protocol Version 6
|
||||
```
|
||||
(Reboot required)
|
||||
|
||||
7. **Increase Network Timeouts**
|
||||
- On UnityTransport component:
|
||||
- Connect Timeout MS: 15000 (15 seconds)
|
||||
- Max Connect Attempts: 10
|
||||
|
||||
## Debug Steps
|
||||
|
||||
### 1. Check Server Side
|
||||
```
|
||||
Add NetworkDebugger → Play → Start Host
|
||||
Check Console for:
|
||||
✓ "Server Started Successfully"
|
||||
✓ "Listening on: 0.0.0.0:7777"
|
||||
✗ Any binding errors
|
||||
```
|
||||
|
||||
### 2. Check Client Side
|
||||
```
|
||||
Add NetworkDebugger → Play → Connect to PUBLIC IP
|
||||
Check Console for:
|
||||
✓ "Connection Approval Request from Client"
|
||||
✓ "Approval Response: Approved: true"
|
||||
✗ "TRANSPORT FAILURE"
|
||||
✗ "Failed to connect to server"
|
||||
```
|
||||
|
||||
### 3. Common Error Patterns
|
||||
|
||||
**Error: "Failed to connect to server" + "TRANSPORT FAILURE"**
|
||||
- Cause: Firewall blocking
|
||||
- Fix: Allow Unity through firewall, check port forwarding
|
||||
|
||||
**Error: Connection approval never happens**
|
||||
- Cause: NetworkManager configuration issue
|
||||
- Fix: Check NetworkConfig → Connection Approval = true
|
||||
|
||||
**Error: Client shows "Connected" but no player spawns**
|
||||
- Cause: ConnectionApproval returning false or spawn point issues
|
||||
- Fix: Check NetworkConnectionHandler logs
|
||||
|
||||
## Advanced Troubleshooting
|
||||
|
||||
### Log Network State
|
||||
```csharp
|
||||
// Add this component and right-click → "Log Current Network State"
|
||||
public void CheckConnection()
|
||||
{
|
||||
Debug.Log("IsServer: " + NetworkManager.Singleton.IsServer);
|
||||
Debug.Log("IsClient: " + NetworkManager.Singleton.IsClient);
|
||||
Debug.Log("IsConnectedClient: " + NetworkManager.Singleton.IsConnectedClient);
|
||||
}
|
||||
```
|
||||
|
||||
### Test Local Connection First
|
||||
1. Host: Connect to 127.0.0.1 (should always work)
|
||||
2. If fails: Project setup issue, not network issue
|
||||
3. If works: Network/Firewall issue with public IP
|
||||
|
||||
### Check NetworkManager Configuration
|
||||
Ensure:
|
||||
- Player Prefab assigned
|
||||
- Network Prefabs list populated
|
||||
- Connection Approval enabled
|
||||
- Scene Management enabled (if using scenes)
|
||||
- Transport is Unity Transport (UTP)
|
||||
|
||||
## Alternative Solutions
|
||||
|
||||
### Option 1: Use LAN instead of Internet
|
||||
If possible, use VPN or Hamachi:
|
||||
- Creates virtual LAN
|
||||
- Both players appear on same network
|
||||
- No port forwarding needed
|
||||
|
||||
### Option 2: Use Relay Service
|
||||
Unity Relay bypasses NAT/Firewall:
|
||||
- Requires Unity Services account
|
||||
- Free tier available
|
||||
- More reliable for internet play
|
||||
|
||||
### Option 3: Dedicated Server
|
||||
- Host on cloud server (AWS, Azure, etc.)
|
||||
- No port forwarding needed on client side
|
||||
- Better performance and reliability
|
||||
|
||||
## Quick Checklist
|
||||
|
||||
- [ ] Port forwarded correctly (verify with online tool)
|
||||
- [ ] Firewall allows Unity/Build executable
|
||||
- [ ] Using public IP (not 127.0.0.1 or 192.168.x.x)
|
||||
- [ ] Same Unity version and Netcode version on both sides
|
||||
- [ ] Same port on both client and server
|
||||
- [ ] NetworkManager has Player Prefab assigned
|
||||
- [ ] Host started BEFORE client tries to connect
|
||||
- [ ] No antivirus/security software blocking
|
||||
- [ ] Both using Release builds (not Debug)
|
||||
|
||||
## When to Ask for Help
|
||||
|
||||
If you've tried:
|
||||
1. All firewall fixes
|
||||
2. Verified port forwarding with online tool
|
||||
3. Tested local connection (127.0.0.1) works
|
||||
4. Checked NetworkManager configuration
|
||||
5. Added NetworkDebugger and NetworkConnectionFixer
|
||||
|
||||
Then share:
|
||||
- Full Console logs from BOTH host and client
|
||||
- NetworkManager inspector screenshot
|
||||
- UnityTransport settings screenshot
|
||||
- Port forwarding confirmation (screenshot or online tool result)
|
||||
@@ -1,310 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
public class ConnectionDiagnostics : MonoBehaviour
|
||||
{
|
||||
[Header("Auto-Diagnosis")]
|
||||
[SerializeField] private bool runOnStart = true;
|
||||
[SerializeField] private bool autoFixIssues = true;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
private UnityTransport _transport;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (runOnStart)
|
||||
{
|
||||
RunDiagnostics();
|
||||
}
|
||||
}
|
||||
|
||||
public void RunDiagnostics()
|
||||
{
|
||||
Debug.Log("<color=yellow>=== RUNNING CONNECTION DIAGNOSTICS ===</color>");
|
||||
|
||||
InitializeComponents();
|
||||
CheckNetworkManager();
|
||||
CheckTransport();
|
||||
CheckPlayerPrefab();
|
||||
CheckConnectionApproval();
|
||||
|
||||
if (autoFixIssues)
|
||||
{
|
||||
FixCommonIssues();
|
||||
}
|
||||
|
||||
GenerateReport();
|
||||
Debug.Log("<color=yellow>=== DIAGNOSTICS COMPLETE ===</color>");
|
||||
}
|
||||
|
||||
private void InitializeComponents()
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[Diagnostics] NetworkManager not found!</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
_transport = _networkManager.GetComponent<UnityTransport>();
|
||||
if (_transport == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[Diagnostics] UnityTransport not found!</color>");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckNetworkManager()
|
||||
{
|
||||
Debug.Log("<color=cyan>[1/5] Checking NetworkManager...</color>");
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("✗ NetworkManager is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("✓ NetworkManager exists");
|
||||
Debug.Log(" IsServer: " + _networkManager.IsServer);
|
||||
Debug.Log(" IsClient: " + _networkManager.IsClient);
|
||||
Debug.Log(" IsHost: " + _networkManager.IsHost);
|
||||
Debug.Log(" IsConnectedClient: " + _networkManager.IsConnectedClient);
|
||||
}
|
||||
|
||||
private void CheckTransport()
|
||||
{
|
||||
Debug.Log("<color=cyan>[2/5] Checking UnityTransport...</color>");
|
||||
|
||||
if (_transport == null)
|
||||
{
|
||||
Debug.LogError("✗ UnityTransport is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("✓ UnityTransport exists");
|
||||
Debug.Log(" Connection Address: " + _transport.ConnectionData.Address);
|
||||
Debug.Log(" Connection Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log(" Server Listen Address: " + _transport.ConnectionData.ServerListenAddress);
|
||||
|
||||
int timeout = _transport.ConnectTimeoutMS;
|
||||
if (timeout < 10000)
|
||||
{
|
||||
Debug.LogWarning("⚠ Connect timeout too low: " + timeout + "ms (recommended: 15000ms)");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("✓ Connect timeout is adequate: " + timeout + "ms");
|
||||
}
|
||||
|
||||
ushort port = _transport.ConnectionData.Port;
|
||||
if (port <= 0 || port > 65535)
|
||||
{
|
||||
Debug.LogError("✗ Invalid port: " + port);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("✓ Port is valid: " + port);
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckPlayerPrefab()
|
||||
{
|
||||
Debug.Log("<color=cyan>[3/5] Checking Player Prefab...</color>");
|
||||
|
||||
if (_networkManager == null || _networkManager.NetworkConfig == null)
|
||||
{
|
||||
Debug.LogError("✗ NetworkConfig not accessible");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject playerPrefab = _networkManager.NetworkConfig.PlayerPrefab;
|
||||
if (playerPrefab == null)
|
||||
{
|
||||
Debug.LogError("✗ Player Prefab is NOT assigned!");
|
||||
Debug.LogError(" → Players will not spawn");
|
||||
Debug.LogError(" → Fix: Assign Player Prefab in NetworkManager");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("✓ Player Prefab assigned: " + playerPrefab.name);
|
||||
|
||||
NetworkObject networkObject = playerPrefab.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
Debug.LogError("✗ Player Prefab has no NetworkObject component!");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("✓ Player Prefab has NetworkObject");
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckConnectionApproval()
|
||||
{
|
||||
Debug.Log("<color=cyan>[4/5] Checking Connection Approval...</color>");
|
||||
|
||||
if (_networkManager == null || _networkManager.NetworkConfig == null)
|
||||
{
|
||||
Debug.LogError("✗ NetworkConfig not accessible");
|
||||
return;
|
||||
}
|
||||
|
||||
bool approval = _networkManager.NetworkConfig.ConnectionApproval;
|
||||
Debug.Log("Connection Approval: " + approval);
|
||||
|
||||
if (approval)
|
||||
{
|
||||
Debug.Log("✓ Connection approval is enabled");
|
||||
Debug.Log(" → Ensure ConnectionApprovalCallback is set");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("⚠ Connection approval is disabled");
|
||||
Debug.Log(" → Players may auto-connect without approval");
|
||||
}
|
||||
|
||||
NetworkConnectionHandler handler = FindObjectOfType<NetworkConnectionHandler>();
|
||||
if (handler != null)
|
||||
{
|
||||
Debug.Log("✓ NetworkConnectionHandler found");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("⚠ NetworkConnectionHandler not found");
|
||||
Debug.Log(" → Manual player spawning may not work");
|
||||
}
|
||||
}
|
||||
|
||||
private void FixCommonIssues()
|
||||
{
|
||||
Debug.Log("<color=cyan>[5/5] Fixing Common Issues...</color>");
|
||||
|
||||
if (_transport == null) return;
|
||||
|
||||
bool fixedSomething = false;
|
||||
|
||||
if (_transport.ConnectTimeoutMS < 10000)
|
||||
{
|
||||
_transport.ConnectTimeoutMS = 15000;
|
||||
Debug.Log("✓ Fixed: Increased timeout to 15000ms");
|
||||
fixedSomething = true;
|
||||
}
|
||||
|
||||
if (_transport.MaxConnectAttempts < 5)
|
||||
{
|
||||
_transport.MaxConnectAttempts = 10;
|
||||
Debug.Log("✓ Fixed: Increased max connect attempts to 10");
|
||||
fixedSomething = true;
|
||||
}
|
||||
|
||||
ushort port = _transport.ConnectionData.Port;
|
||||
if (port <= 0)
|
||||
{
|
||||
_transport.SetConnectionData("0.0.0.0", 7777);
|
||||
Debug.Log("✓ Fixed: Set default port to 7777");
|
||||
fixedSomething = true;
|
||||
}
|
||||
|
||||
if (!fixedSomething)
|
||||
{
|
||||
Debug.Log("✓ No issues found to fix");
|
||||
}
|
||||
}
|
||||
|
||||
private void GenerateReport()
|
||||
{
|
||||
Debug.Log("<color=green>=== DIAGNOSTICS REPORT ===</color>");
|
||||
|
||||
string status = GetOverallStatus();
|
||||
Color color = GetStatusColor(status);
|
||||
|
||||
Debug.Log("<color=" + ColorToHex(color) + ">" + status + "</color>");
|
||||
|
||||
if (status != "System Healthy")
|
||||
{
|
||||
Debug.Log("Review warnings and errors above");
|
||||
}
|
||||
Debug.Log("=========================");
|
||||
}
|
||||
|
||||
private string GetOverallStatus()
|
||||
{
|
||||
if (_networkManager == null || _transport == null)
|
||||
return "Critical Errors Found";
|
||||
|
||||
if (_networkManager.NetworkConfig?.PlayerPrefab == null)
|
||||
return "Configuration Error";
|
||||
|
||||
if (_transport.ConnectTimeoutMS < 10000)
|
||||
return "Performance Issue";
|
||||
|
||||
return "System Healthy";
|
||||
}
|
||||
|
||||
private Color GetStatusColor(string status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case "System Healthy":
|
||||
return Color.green;
|
||||
case "Performance Issue":
|
||||
return Color.yellow;
|
||||
case "Configuration Error":
|
||||
return new Color(1f, 0.5f, 0f);
|
||||
case "Critical Errors Found":
|
||||
return Color.red;
|
||||
default:
|
||||
return Color.gray;
|
||||
}
|
||||
}
|
||||
|
||||
private string ColorToHex(Color color)
|
||||
{
|
||||
return "#" + ColorUtility.ToHtmlStringRGBA(color);
|
||||
}
|
||||
|
||||
[ContextMenu("Run Diagnostics")]
|
||||
public void ManualRunDiagnostics()
|
||||
{
|
||||
RunDiagnostics();
|
||||
}
|
||||
|
||||
[ContextMenu("Check Connection Status")]
|
||||
public void CheckConnectionStatus()
|
||||
{
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("NetworkManager not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("=== CONNECTION STATUS ===");
|
||||
Debug.Log("IsServer: " + _networkManager.IsServer);
|
||||
Debug.Log("IsClient: " + _networkManager.IsClient);
|
||||
Debug.Log("IsHost: " + _networkManager.IsHost);
|
||||
Debug.Log("IsConnectedClient: " + _networkManager.IsConnectedClient);
|
||||
Debug.Log("LocalClientId: " + _networkManager.LocalClientId);
|
||||
Debug.Log("ConnectedClients: " + _networkManager.ConnectedClients.Count);
|
||||
|
||||
if (_transport != null)
|
||||
{
|
||||
Debug.Log("Listening on: " + _transport.ConnectionData.Address + ":" + _transport.ConnectionData.Port);
|
||||
}
|
||||
|
||||
if (_networkManager.IsHost || _networkManager.IsServer)
|
||||
{
|
||||
Debug.Log("Connected Players:");
|
||||
foreach (var client in _networkManager.ConnectedClients)
|
||||
{
|
||||
string playerInfo = client.Value.PlayerObject != null ?
|
||||
client.Value.PlayerObject.name : "No Player Object";
|
||||
Debug.Log(" Client " + client.Key + ": " + playerInfo);
|
||||
}
|
||||
}
|
||||
Debug.Log("=======================");
|
||||
}
|
||||
}
|
||||
}
|
||||
365
Assets/Scripts/ContinuousPortMonitor.cs
Normal file
365
Assets/Scripts/ContinuousPortMonitor.cs
Normal file
@@ -0,0 +1,365 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System;
|
||||
using System.Threading;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Continuous port monitor - keeps checking if port is actually open
|
||||
/// Helps diagnose why Unity Netcode doesn't keep port open
|
||||
/// </summary>
|
||||
public class ContinuousPortMonitor : MonoBehaviour
|
||||
{
|
||||
[Header("Monitoring Settings")]
|
||||
[SerializeField] private ushort targetPort = 40445;
|
||||
[SerializeField] private bool startMonitoringOnStart = false;
|
||||
[SerializeField] private float checkInterval = 1f;
|
||||
[SerializeField] private int maxFailedChecksBeforeWarning = 5;
|
||||
|
||||
[Header("Actions")]
|
||||
[SerializeField] private bool autoRestartBinding = true;
|
||||
[SerializeField] private bool keepTestListenerAlive = false;
|
||||
|
||||
[Header("Debug")]
|
||||
[SerializeField] private bool verboseLogging = true;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
private TcpListener _testListener;
|
||||
private Thread _listenerThread;
|
||||
private volatile bool _listenerRunning = false;
|
||||
private float _lastCheckTime;
|
||||
private int _failedCheckCount = 0;
|
||||
private bool _wasListeningPreviously = false;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
StartCoroutine(InitializeDelayed());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator InitializeDelayed()
|
||||
{
|
||||
Debug.Log("[ContinuousPortMonitor] Waiting for NetworkManager...");
|
||||
|
||||
int attempts = 0;
|
||||
while (_networkManager == null && attempts < 50)
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("[ContinuousPortMonitor] NetworkManager not found!");
|
||||
yield break;
|
||||
}
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] NetworkManager found!");
|
||||
|
||||
if (startMonitoringOnStart)
|
||||
{
|
||||
StartMonitoring();
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Start Port Monitoring")]
|
||||
public void StartMonitoring()
|
||||
{
|
||||
Debug.Log("<color=cyan>[ContinuousPortMonitor] Starting port monitoring for " + targetPort + "</color>");
|
||||
|
||||
if (keepTestListenerAlive)
|
||||
{
|
||||
StartTestListener();
|
||||
}
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] Monitoring started - check interval: " + checkInterval + "s");
|
||||
Debug.Log("[ContinuousPortMonitor] Will check if port remains accessible");
|
||||
}
|
||||
|
||||
[ContextMenu("Stop Port Monitoring")]
|
||||
public void StopMonitoring()
|
||||
{
|
||||
Debug.Log("[ContinuousPortMonitor] Stopping monitoring...");
|
||||
|
||||
StopTestListener();
|
||||
enabled = false;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!enabled) return;
|
||||
|
||||
if (Time.time - _lastCheckTime >= checkInterval)
|
||||
{
|
||||
_lastCheckTime = Time.time;
|
||||
CheckPortAccessibility();
|
||||
}
|
||||
}
|
||||
|
||||
private void CheckPortAccessibility()
|
||||
{
|
||||
bool isUnityServerRunning = _networkManager != null && _networkManager.IsServer;
|
||||
bool isCurrentlyListening = _listenerRunning || isUnityServerRunning;
|
||||
|
||||
if (!verboseLogging)
|
||||
{
|
||||
// Only log when status changes
|
||||
if (isCurrentlyListening != _wasListeningPreviously)
|
||||
{
|
||||
_wasListeningPreviously = isCurrentlyListening;
|
||||
|
||||
if (isCurrentlyListening)
|
||||
{
|
||||
Debug.Log("<color=green>[ContinuousPortMonitor] ✓ Port " + targetPort + " is NOW ACCESSIBLE</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[ContinuousPortMonitor] ⚠ Port " + targetPort + " became INACCESSIBLE</color>");
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Verbose logging
|
||||
if (isUnityServerRunning)
|
||||
{
|
||||
Debug.Log("[ContinuousPortMonitor] Unity Server: RUNNING");
|
||||
}
|
||||
|
||||
if (_listenerRunning)
|
||||
{
|
||||
Debug.Log("[ContinuousPortMonitor] Test Listener: RUNNING");
|
||||
}
|
||||
|
||||
bool portAccessible = TestPortConnection();
|
||||
|
||||
if (portAccessible)
|
||||
{
|
||||
_failedCheckCount = 0;
|
||||
if (Time.frameCount % 60 == 0) // Every second at 60fps
|
||||
{
|
||||
Debug.Log("<color=green>[ContinuousPortMonitor] ✓ Port " + targetPort + " is accessible</color>");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_failedCheckCount++;
|
||||
|
||||
if (_failedCheckCount == 1)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[ContinuousPortMonitor] ⚠ Port " + targetPort + " became inaccessible</color>");
|
||||
}
|
||||
else if (_failedCheckCount % 10 == 0)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[ContinuousPortMonitor] ⚠ Port still inaccessible (check #" + _failedCheckCount + ")</color>");
|
||||
}
|
||||
|
||||
if (_failedCheckCount >= maxFailedChecksBeforeWarning)
|
||||
{
|
||||
Debug.LogError("<color=red>[ContinuousPortMonitor] ✗ Port has been inaccessible for " + _failedCheckCount + " checks!</color>");
|
||||
Debug.LogError("[ContinuousPortMonitor] This indicates a problem with port binding");
|
||||
Debug.LogError("[ContinuousPortMonitor] Possible causes:");
|
||||
Debug.LogError("1. Unity Netcode is not actually listening");
|
||||
Debug.LogError("2. Another process is interfering");
|
||||
Debug.LogError("3. NetworkManager has crashed/stopped");
|
||||
|
||||
if (autoRestartBinding)
|
||||
{
|
||||
Debug.Log("<color=cyan>[ContinuousPortMonitor] Attempting to restore binding...</color>");
|
||||
TryRestoreBinding();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TestPortConnection()
|
||||
{
|
||||
try
|
||||
{
|
||||
using (TcpClient client = new TcpClient("127.0.0.1", targetPort))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void StartTestListener()
|
||||
{
|
||||
if (_listenerRunning)
|
||||
{
|
||||
Debug.LogWarning("[ContinuousPortMonitor] Test listener already running");
|
||||
return;
|
||||
}
|
||||
|
||||
_listenerRunning = true;
|
||||
_listenerThread = new Thread(new ThreadStart(ListenerThread));
|
||||
_listenerThread.IsBackground = true;
|
||||
_listenerThread.Start();
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] Test listener started on port " + targetPort);
|
||||
}
|
||||
|
||||
private void StopTestListener()
|
||||
{
|
||||
_listenerRunning = false;
|
||||
|
||||
if (_testListener != null)
|
||||
{
|
||||
_testListener.Stop();
|
||||
_testListener = null;
|
||||
}
|
||||
|
||||
if (_listenerThread != null && _listenerThread.IsAlive)
|
||||
{
|
||||
_listenerThread.Join(1000);
|
||||
}
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] Test listener stopped");
|
||||
}
|
||||
|
||||
private void ListenerThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
_testListener = new TcpListener(IPAddress.Any, targetPort);
|
||||
_testListener.Start();
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] Test listener successfully bound to 0.0.0.0:" + targetPort);
|
||||
Debug.Log("[ContinuousPortMonitor] Port should now be accessible on yougetsignal");
|
||||
|
||||
while (_listenerRunning)
|
||||
{
|
||||
if (_testListener.Pending())
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpClient client = _testListener.AcceptTcpClient();
|
||||
IPEndPoint endPoint = (IPEndPoint)client.Client.RemoteEndPoint;
|
||||
|
||||
Debug.Log("<color=green>[ContinuousPortMonitor] ✓ Connection received from " + endPoint.Address + ":" + endPoint.Port + "</color>");
|
||||
Debug.Log("[ContinuousPortMonitor] This proves port forwarding is working!");
|
||||
|
||||
Thread.Sleep(100);
|
||||
client.Close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Debug.LogWarning("[ContinuousPortMonitor] Error accepting connection: " + e.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("[ContinuousPortMonitor] Listener thread exiting");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_listenerRunning = false;
|
||||
Debug.LogError("<color=red>[ContinuousPortMonitor] Listener error: " + e.Message + "</color>");
|
||||
}
|
||||
}
|
||||
|
||||
private void TryRestoreBinding()
|
||||
{
|
||||
Debug.Log("<color=cyan>[ContinuousPortMonitor] Attempting to restore port binding...</color>");
|
||||
|
||||
// This is a placeholder - in reality, we'd need to restart Unity Netcode
|
||||
// But we can't do that safely from this script
|
||||
Debug.LogWarning("[ContinuousPortMonitor] Can't automatically restart Unity Netcode");
|
||||
Debug.LogWarning("[ContinuousPortMonitor] Manual intervention required:");
|
||||
Debug.LogWarning("1. Stop Host/Server");
|
||||
Debug.LogWarning("2. Use ForceTransportBinding → 'Force Then Start Host'");
|
||||
Debug.LogWarning("3. Check if port becomes accessible");
|
||||
}
|
||||
|
||||
[ContextMenu("Check Current Status")]
|
||||
public void CheckCurrentStatus()
|
||||
{
|
||||
Debug.Log("=== PORT MONITOR STATUS ===");
|
||||
|
||||
bool isUnityServerRunning = _networkManager != null && _networkManager.IsServer;
|
||||
bool isTestListenerRunning = _listenerRunning;
|
||||
bool portAccessible = TestPortConnection();
|
||||
|
||||
Debug.Log("Unity Server Running: " + isUnityServerRunning);
|
||||
Debug.Log("Test Listener Running: " + isTestListenerRunning);
|
||||
Debug.Log("Port Accessible: " + portAccessible);
|
||||
|
||||
if (portAccessible)
|
||||
{
|
||||
Debug.Log("<color=green>✓ Port " + targetPort + " is accessible</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Port " + targetPort + " is NOT accessible</color>");
|
||||
Debug.LogError("Check:");
|
||||
Debug.LogError("1. Is Unity Netcode actually running?");
|
||||
Debug.LogError("2. Is there a firewall blocking after some time?");
|
||||
Debug.LogError("3. Is router restarting port forwarding?");
|
||||
}
|
||||
|
||||
Debug.Log("============================");
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Diagnosis Report")]
|
||||
public void GenerateDiagnosisReport()
|
||||
{
|
||||
Debug.Log("=== PORT MONITOR DIAGNOSIS ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("PROBLEM:");
|
||||
Debug.Log("- PortListenerTest: WORKS (port accessible)");
|
||||
Debug.Log("- After test ends: PORT INACCESSIBLE");
|
||||
Debug.Log("- Unity Netcode: PORT INACCESSIBLE");
|
||||
Debug.Log("");
|
||||
Debug.Log("ANALYSIS:");
|
||||
Debug.Log("1. Port forwarding: WORKING (proven by test)");
|
||||
Debug.Log("2. Firewall: ALLOWING (proven by test)");
|
||||
Debug.Log("3. Unity Netcode: NOT BINDING OR CRASHING");
|
||||
Debug.Log("");
|
||||
Debug.Log("POSSIBLE CAUSES:");
|
||||
Debug.Log("1. Unity NetworkManager is not actually starting server");
|
||||
Debug.Log("2. Player Prefab not assigned (server doesn't start)");
|
||||
Debug.Log("3. Connection Approval rejecting all connections");
|
||||
Debug.Log("4. NetworkConnectionHandler has error and stops server");
|
||||
Debug.Log("5. Unity Netcode version bug");
|
||||
Debug.Log("");
|
||||
Debug.Log("CHECKLIST:");
|
||||
Debug.Log("☐ NetworkManager → Player Prefab: ASSIGNED?");
|
||||
Debug.Log("☐ NetworkManager → Connection Approval: CHECKED?");
|
||||
Debug.Log("☐ NetworkConnectionHandler: IN SCENE?");
|
||||
Debug.Log("☐ AutoHost: DISABLED or configured correctly?");
|
||||
Debug.Log("☐ ForceTransportBinding: APPLIED?");
|
||||
Debug.Log("");
|
||||
Debug.Log("NEXT STEPS:");
|
||||
Debug.Log("1. Add ForceTransportBinding to scene");
|
||||
Debug.Log("2. Right-click → 'Force Then Start Host'");
|
||||
Debug.Log("3. Watch Console for '✓ Server STARTED'");
|
||||
Debug.Log("4. Immediately test on yougetsignal");
|
||||
Debug.Log("5. If still closed: Check NetworkManager config");
|
||||
Debug.Log("================================");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
StopTestListener();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopMonitoring();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/ContinuousPortMonitor.cs.meta
Normal file
2
Assets/Scripts/ContinuousPortMonitor.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 419b183105a6cb3479d26f7fd72aab25
|
||||
95
Assets/Scripts/GamePortConfig.cs
Normal file
95
Assets/Scripts/GamePortConfig.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Central port configuration for the project
|
||||
/// </summary>
|
||||
public class GamePortConfig : MonoBehaviour
|
||||
{
|
||||
[Header("Port Configuration")]
|
||||
[Tooltip("The main network port for the game")]
|
||||
[SerializeField] private ushort gamePort = 40445;
|
||||
|
||||
public static ushort Port => Instance != null ? Instance.gamePort : (ushort)40445;
|
||||
public static GamePortConfig Instance { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null && Instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
|
||||
Instance = this;
|
||||
DontDestroyOnLoad(gameObject);
|
||||
|
||||
Debug.Log("<color=cyan>[GamePortConfig] Using port: " + gamePort + "</color>");
|
||||
}
|
||||
|
||||
[ContextMenu("Log Port Configuration")]
|
||||
public void LogPortConfig()
|
||||
{
|
||||
Debug.Log("=== GAME PORT CONFIGURATION ===");
|
||||
Debug.Log("Game Port: " + gamePort);
|
||||
Debug.Log("Port Type: TCP (and UDP if enabled)");
|
||||
Debug.Log("Use this port for:");
|
||||
Debug.Log(" - Router Port Forwarding");
|
||||
Debug.Log(" - Windows Firewall rules");
|
||||
Debug.Log(" - Port testing tools");
|
||||
Debug.Log(" - Teammate connections");
|
||||
Debug.Log("==============================");
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Router Port Forwarding Info")]
|
||||
public void GeneratePortForwardingInfo()
|
||||
{
|
||||
Debug.Log("=== ROUTER PORT FORWARDING SETTINGS ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("<color=cyan>EXTERNAL PORT:</color> " + gamePort);
|
||||
Debug.Log("<color=cyan>INTERNAL PORT:</color> " + gamePort);
|
||||
Debug.Log("<color=cyan>PROTOCOL:</color> TCP");
|
||||
Debug.Log("<color=cyan>INTERNAL IP:</color> [Your computer's local IP]");
|
||||
Debug.Log("");
|
||||
Debug.Log("Steps:");
|
||||
Debug.Log("1. Open Command Prompt, run 'ipconfig'");
|
||||
Debug.Log("2. Find 'IPv4 Address' (e.g., 192.168.1.50)");
|
||||
Debug.Log("3. Login to router (http://192.168.1.1)");
|
||||
Debug.Log("4. Find Port Forwarding section");
|
||||
Debug.Log("5. Add rule with above settings");
|
||||
Debug.Log("6. Use your IPv4 as Internal IP");
|
||||
Debug.Log("7. Save and restart router");
|
||||
Debug.Log("");
|
||||
Debug.Log("Test port at: https://www.yougetsignal.com/tools/open-ports/");
|
||||
Debug.Log("=======================================");
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Firewall Rules")]
|
||||
public void GenerateFirewallRules()
|
||||
{
|
||||
Debug.Log("=== WINDOWS FIREWALL RULES ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("Run PowerShell as Administrator, then:");
|
||||
Debug.Log("");
|
||||
Debug.Log("# Allow port " + gamePort);
|
||||
Debug.Log("netsh advfirewall firewall add rule name=\"Unity Port " + gamePort + "\" dir=in action=allow protocol=TCP localport=" + gamePort + " enable=yes profile=any");
|
||||
Debug.Log("");
|
||||
Debug.Log("# Allow Unity Editor");
|
||||
Debug.Log("netsh advfirewall firewall add rule name=\"Unity Editor\" dir=in action=allow program=\"%ProgramFiles%\\Unity\\Hub\\Editor\\*\\Unity.exe\" enable=yes profile=any");
|
||||
Debug.Log("");
|
||||
Debug.Log("# Allow your game build");
|
||||
Debug.Log("netsh advfirewall firewall add rule name=\"Northbound Game\" dir=in action=allow program=\"D:\\Northbound\\Build\\Northbound.exe\" enable=yes profile=any");
|
||||
Debug.Log("");
|
||||
Debug.Log("Note: Update the game path to your actual build location!");
|
||||
Debug.Log("===============================");
|
||||
}
|
||||
|
||||
[ContextMenu("Copy Port to Clipboard")]
|
||||
public void CopyPortToClipboard()
|
||||
{
|
||||
GUIUtility.systemCopyBuffer = gamePort.ToString();
|
||||
Debug.Log("Copied port " + gamePort + " to clipboard");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/GamePortConfig.cs.meta
Normal file
2
Assets/Scripts/GamePortConfig.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3de3b9ec2863be4396a3c2853421035
|
||||
@@ -1,164 +0,0 @@
|
||||
# Connection Issue: Immediate Action Plan
|
||||
|
||||
## Your Problem
|
||||
Teammate sees "CONNECTED" but gets "Failed to connect to server" error.
|
||||
|
||||
## Root Cause (Most Likely)
|
||||
Windows Firewall is blocking Unity/Build even with port forwarding done correctly.
|
||||
|
||||
## FIX IN 3 STEPS
|
||||
|
||||
### Step 1: Add Debug Components (1 minute)
|
||||
Add these to your NetworkManager GameObject in BOTH Host and Client scenes:
|
||||
1. **ConnectionDiagnostics** (automatic check)
|
||||
2. **NetworkDebugger** (detailed logs)
|
||||
3. **NetworkConnectionFixer** (auto-fixes issues)
|
||||
|
||||
### Step 2: Fix Firewall (2 minutes)
|
||||
Run PowerShell as Administrator, paste this:
|
||||
|
||||
```powershell
|
||||
# Allow Unity Editor
|
||||
netsh advfirewall firewall add rule name="Unity Editor" dir=in action=allow program="C:\Program Files\Unity\Hub\Editor\*\Unity.exe" enable=yes profile=any
|
||||
|
||||
# Allow your game build (update path!)
|
||||
netsh advfirewall firewall add rule name="Northbound Game" dir=in action=allow program="D:\Northbound\Build\Northbound.exe" enable=yes profile=any
|
||||
|
||||
# Allow port 7777
|
||||
netsh advfirewall firewall add rule name="Unity Port 7777" dir=in action=allow protocol=TCP localport=7777 enable=yes profile=any
|
||||
```
|
||||
|
||||
### Step 3: Verify Port Forwarding (1 minute)
|
||||
Go to: https://www.yougetsignal.com/tools/open-ports/
|
||||
- Enter your PUBLIC IP
|
||||
- Enter port 7777
|
||||
- Should say: "Port 7777 is open"
|
||||
|
||||
If "Closed", your router port forwarding is wrong.
|
||||
|
||||
---
|
||||
|
||||
## Quick Diagnostics
|
||||
|
||||
### In Unity Editor (Play Mode):
|
||||
1. Add **ConnectionDiagnostics** to NetworkManager
|
||||
2. Right-click component → "Run Diagnostics"
|
||||
3. Check console for errors/warnings
|
||||
|
||||
### Common Diagnostics Results:
|
||||
- ✅ **"System Healthy"**: Configuration is good, issue is network/firewall
|
||||
- ⚠️ **"Player Prefab NOT assigned"**: Assign player prefab in NetworkManager
|
||||
- ⚠️ **"Connect timeout too low"**: ConnectionDiagnostics fixes this automatically
|
||||
- ❌ **"NetworkManager not found"**: Add NetworkManager to scene
|
||||
|
||||
### If Still Not Working:
|
||||
|
||||
#### Test 1: Local Connection
|
||||
Host connects to 127.0.0.1 (same instance)
|
||||
- ✅ Works = Good setup, issue is network
|
||||
- ❌ Fails = Project setup issue
|
||||
|
||||
#### Test 2: LAN Connection
|
||||
Host shares 192.168.x.x IP (same WiFi)
|
||||
- ✅ Works = Good LAN, issue is port forwarding for internet
|
||||
- ❌ Fails = Firewall blocking local connections
|
||||
|
||||
#### Test 3: Internet Connection
|
||||
Host shares PUBLIC IP with teammate
|
||||
- ✅ Works = Fixed!
|
||||
- ❌ Fails = Port forwarding or remote firewall
|
||||
|
||||
---
|
||||
|
||||
## What Console Should Show
|
||||
|
||||
### Host (Working):
|
||||
```
|
||||
[ConnectionDiagnostics] System Healthy
|
||||
[NetworkConnectionFixer] Network fixes applied
|
||||
[NetworkDebugger] Server Started Successfully
|
||||
[NetworkDebugger] Listening on: 0.0.0.0:7777
|
||||
[NetworkDebugger] Client Connected: 1
|
||||
[ConnectionHandler] 클라이언트 1 승인됨
|
||||
[ConnectionHandler] 플레이어 1 스폰됨
|
||||
```
|
||||
|
||||
### Client (Working):
|
||||
```
|
||||
[ConnectionDiagnostics] System Healthy
|
||||
[NetworkConnectionFixer] Network fixes applied
|
||||
[NetworkDebugger] Connection Approval Request
|
||||
[NetworkDebugger] Approval Response: Approved: true
|
||||
[NetworkDebugger] Client Connected: 0
|
||||
```
|
||||
|
||||
### Client (Broken - Your Case):
|
||||
```
|
||||
[ConnectionDiagnostics] System Healthy
|
||||
[NetworkConnectionFixer] Network fixes applied
|
||||
[NetworkDebugger] Connection Approval Request
|
||||
<color=red>[NetworkDebugger] TRANSPORT FAILURE!</color>
|
||||
Failed to connect to server
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Tools Created for You
|
||||
|
||||
| File | Purpose | How to Use |
|
||||
|------|---------|------------|
|
||||
| **ConnectionDiagnostics.cs** | Auto-checks configuration | Add to scene, right-click "Run Diagnostics" |
|
||||
| **NetworkDebugger.cs** | Shows detailed connection logs | Add to scene, watch Console during connection |
|
||||
| **NetworkConnectionFixer.cs** | Fixes common timeout issues | Add to scene, right-click "Fix All Known Issues" |
|
||||
| **PublicIPHelper.cs** | Gets your public IP automatically | Add to scene, see Inspector |
|
||||
|
||||
---
|
||||
|
||||
## Most Likely Issue: Firewall
|
||||
|
||||
Even with correct port forwarding, Windows Firewall blocks:
|
||||
|
||||
1. ✅ Port 7777 may be open (router allows it)
|
||||
2. ❌ But Windows Firewall blocks the application using that port
|
||||
|
||||
**Solution:** Allow Unity and your game through firewall (Step 2)
|
||||
|
||||
---
|
||||
|
||||
## Alternative: Use Hamachi/VPN
|
||||
|
||||
If port forwarding is too complex:
|
||||
|
||||
1. Both install Hamachi: https://www.vpn.net/
|
||||
2. Join same Hamachi network
|
||||
3. Use Hamachi IP (25.x.x.x) instead of public IP
|
||||
4. No port forwarding needed!
|
||||
|
||||
---
|
||||
|
||||
## Share This for Help
|
||||
|
||||
If issue persists, share screenshots/logs:
|
||||
|
||||
1. ✅ NetworkManager Inspector (screenshot)
|
||||
2. ✅ Unity Transport settings (screenshot)
|
||||
3. ✅ Console log (Host) - after connecting
|
||||
4. ✅ Console log (Client) - after connection attempt
|
||||
5. ✅ Port checker result (screenshot)
|
||||
6. ✅ Windows Firewall rules list (screenshot)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
1. **Add debug components** (1 min)
|
||||
2. **Fix firewall** (2 min) - MOST IMPORTANT
|
||||
3. **Verify port forwarding** (1 min)
|
||||
4. **Test with console logs**
|
||||
|
||||
If all this fails, the issue is likely:
|
||||
- Port forwarding is wrong (verify with online tool)
|
||||
- Different Unity/Netcode versions between you and teammate
|
||||
- Antivirus/security software blocking
|
||||
|
||||
Good luck! 🎮
|
||||
@@ -1,192 +0,0 @@
|
||||
# Network Connection Feature Summary
|
||||
|
||||
## Overview
|
||||
Added comprehensive IP-based network connection features for both editor testing and standalone builds.
|
||||
|
||||
## Files Created
|
||||
|
||||
### Runtime Components
|
||||
1. **NetworkConnectionHelper.cs** (3.6KB)
|
||||
- MonoBehaviour component for network connection management
|
||||
- Start Host/Server/Client methods
|
||||
- Auto-start configuration
|
||||
- Status monitoring
|
||||
|
||||
2. **NetworkJoinUI.cs** (7.7KB)
|
||||
- In-game UI component for IP connection
|
||||
- Works in both editor and standalone builds
|
||||
- Toggle panel with J key
|
||||
- Supports Join/Host/Disconnect
|
||||
|
||||
3. **QuickNetworkSetup.cs** (1.6KB)
|
||||
- Quick scene setup script
|
||||
- Creates NetworkConnectionHelper
|
||||
- Optionally disables AutoHost
|
||||
|
||||
### Editor Tools
|
||||
4. **NetworkConnectionWindow.cs** (9.2KB)
|
||||
- Dedicated Editor window for network management
|
||||
- GUI-based IP/port configuration
|
||||
- Connection mode selection
|
||||
- Status display and settings persistence
|
||||
|
||||
5. **NetworkConnectionHelperEditor.cs** (5.8KB)
|
||||
- Custom Inspector for NetworkConnectionHelper
|
||||
- Quick action buttons
|
||||
- Real-time status display
|
||||
- Network information panel
|
||||
|
||||
6. **NetworkUIBuilder.cs** (7.4KB)
|
||||
- Automated UI creation for NetworkJoinUI
|
||||
- Creates complete UI structure
|
||||
- Menu integration
|
||||
|
||||
7. **QuickNetworkSetupEditor.cs** (2.0KB)
|
||||
- Menu items for quick setup
|
||||
- Tools menu integration
|
||||
- Enable/Disable AutoHost functionality
|
||||
|
||||
### Documentation
|
||||
8. **NETWORK_CONNECTION_README.md**
|
||||
- Comprehensive English documentation
|
||||
- Setup instructions
|
||||
- Usage examples
|
||||
|
||||
9. **NETWORK_CONNECTION_GUIDE_KO.md**
|
||||
- Korean translation of documentation
|
||||
- Step-by-step guide
|
||||
- Troubleshooting section
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. **AutoHost.cs**
|
||||
- Made auto-start configurable
|
||||
- Added editor-only option
|
||||
- Added enable/disable toggle
|
||||
|
||||
## Features Added
|
||||
|
||||
### 1. Editor Window (NetworkConnectionWindow)
|
||||
- Open via: Window > Network > Connection Manager (Ctrl+Shift+N)
|
||||
- Connection modes: Host/Client/Server
|
||||
- IP and port configuration
|
||||
- Start/Stop connections
|
||||
- Real-time status
|
||||
- Settings persistence
|
||||
|
||||
### 2. NetworkConnectionHelper Component
|
||||
- Add to any GameObject in scene
|
||||
- Custom Inspector with quick buttons
|
||||
- Auto-start configuration
|
||||
- Status display
|
||||
- Network information panel
|
||||
|
||||
### 3. In-Game UI (NetworkJoinUI)
|
||||
- Works in editor and standalone builds
|
||||
- IP/port input fields
|
||||
- Join/Host/Disconnect buttons
|
||||
- Status display
|
||||
- Toggle with J key
|
||||
- Auto-generated via menu
|
||||
|
||||
### 4. Quick Setup Tools
|
||||
- Tools > Network > Quick Setup for IP Connection
|
||||
- Automatically disables AutoHost
|
||||
- Creates NetworkConnectionHelper
|
||||
|
||||
## Integration
|
||||
|
||||
All new features integrate seamlessly with existing systems:
|
||||
- **NetworkManager**: Works with Unity Netcode for GameObjects
|
||||
- **NetworkConnectionHandler**: Handles player spawning and approval
|
||||
- **AutoHost**: Configurable to avoid conflicts
|
||||
- **Transport**: Uses Unity Transport (UTP)
|
||||
|
||||
## Testing Workflow
|
||||
|
||||
### Method 1: Editor Window
|
||||
1. Window > Network > Connection Manager
|
||||
2. Select Host on instance 1
|
||||
3. Select Client on instance 2 with Host's IP
|
||||
4. Start/Connect
|
||||
|
||||
### Method 2: NetworkConnectionHelper
|
||||
1. Add component to scene
|
||||
2. Use Inspector buttons
|
||||
3. View status in real-time
|
||||
|
||||
### Method 3: Quick Setup
|
||||
1. Tools > Network > Quick Setup for IP Connection
|
||||
2. Use preferred connection method
|
||||
|
||||
### Method 4: In-Game UI
|
||||
1. GameObject > Network > Create Network Join UI
|
||||
2. Press J to open
|
||||
3. Enter IP and connect
|
||||
|
||||
## Configuration
|
||||
|
||||
### Default Settings
|
||||
- Default IP: 127.0.0.1
|
||||
- Default Port: 7777
|
||||
- Toggle Key: J (for UI)
|
||||
|
||||
### Options
|
||||
- Auto-start: Enable/disable in AutoHost
|
||||
- Editor-only: Configure per component
|
||||
- Persistence: Save/load in Editor Window
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Easy Testing**: No standalone build required
|
||||
2. **Team Collaboration**: Join teammates by IP
|
||||
3. **Production Ready**: Works in standalone builds
|
||||
4. **Flexible**: Multiple connection methods
|
||||
5. **Intuitive**: GUI-based interfaces
|
||||
6. **Integrated**: Works with existing systems
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Potential improvements:
|
||||
- Server list browsing
|
||||
- Favorites/Saved connections
|
||||
- LAN discovery
|
||||
- Connection history
|
||||
- Advanced transport settings
|
||||
- Password protection
|
||||
|
||||
## Usage Example
|
||||
|
||||
### Editor Testing
|
||||
```csharp
|
||||
// Instance 1 (Host)
|
||||
Tools > Network > Quick Setup for IP Connection
|
||||
Window > Network > Connection Manager > Start Host
|
||||
|
||||
// Instance 2 (Client)
|
||||
Tools > Network > Quick Setup for IP Connection
|
||||
Window > Network > Connection Manager > Connect to 127.0.0.1:7777
|
||||
```
|
||||
|
||||
### Standalone Build
|
||||
```csharp
|
||||
// Build with NetworkJoinUI component
|
||||
Press J to open connection panel
|
||||
Enter IP: 192.168.1.X
|
||||
Click Join
|
||||
```
|
||||
|
||||
## Compatibility
|
||||
|
||||
- Unity Netcode for GameObjects 2.8.1
|
||||
- Unity Transport (UTP)
|
||||
- Unity 2022.x+
|
||||
- Windows/Mac/Linux
|
||||
|
||||
## Notes
|
||||
|
||||
- All components are optional
|
||||
- AutoHost can be disabled
|
||||
- Existing AutoHost behavior preserved (when enabled)
|
||||
- No breaking changes to existing code
|
||||
- Works with custom scenes and setups
|
||||
307
Assets/Scripts/NETWORK_SETUP_GUIDE_KO.md
Normal file
307
Assets/Scripts/NETWORK_SETUP_GUIDE_KO.md
Normal file
@@ -0,0 +1,307 @@
|
||||
# 🎮 네트워크 연결 설정 가이드
|
||||
|
||||
## 📋 상황 요약
|
||||
|
||||
✅ PortListenerTest: 포트 열림 (yougetsignal 성공)
|
||||
✅ 포트 포워딩: 작동 중 (yougetsignal 성공으로 증명)
|
||||
✅ 방화벽: 허용 중 (yougetsignal 성공으로 증명)
|
||||
❌ 유니티 Netcode: **포트가 닫혀 있음**
|
||||
|
||||
## ⚡ 즉시 해결책 (3단계)
|
||||
|
||||
### 1단계: 테스트 시작 (30초)
|
||||
|
||||
1. **NetworkManagerQuickTest** 추가 (씬의 아무 게임오브젝트)
|
||||
2. 우클릭 → "Run Quick NetworkManager Test"
|
||||
3. 콘솔 출력 공유
|
||||
|
||||
**기대 결과:**
|
||||
```
|
||||
✓ NetworkManager found!
|
||||
✓ Player Prefab: Player
|
||||
✓ Unity Transport found!
|
||||
✓ Transport: 4045, 0.0.0.0
|
||||
✓ NetworkConnectionHandler found!
|
||||
```
|
||||
|
||||
### 2단계: 팀원 연결 테스트 (1분)
|
||||
|
||||
1. 팀원에게 당신의 **퍼블릭 IP** 알림
|
||||
2. 팀원: 게임에서 IP:포트 입력
|
||||
3. 팀원: "연결" 클릭
|
||||
|
||||
**기대:**
|
||||
- 성공: 팀원이 접속!
|
||||
- 실패: 에러 로그 공유
|
||||
|
||||
### 3단계: 문제 해결
|
||||
|
||||
팀원이 접속 못할 경우:
|
||||
|
||||
**팀원 측:**
|
||||
- 올바른 퍼블릭 IP 입력했는지 확인
|
||||
- 방화벽 허용 확인
|
||||
- 유니티 Netcode 버전 확인 (동일해야 함)
|
||||
|
||||
**호스트 측 (당신):**
|
||||
- 콘솔에서 "[ConnectionHandler] 클라이언트" 메시지 확인
|
||||
- 스폰 성공하는지 확인
|
||||
- 플레이어가 생성되는지 확인
|
||||
|
||||
---
|
||||
|
||||
## 🔧 필수 구성 요소
|
||||
|
||||
### NetworkManager 설정
|
||||
|
||||
**필수:**
|
||||
```
|
||||
NetworkManager GameObject:
|
||||
- Player Prefab: Player (Assets/Prefabs/Player/)
|
||||
- Connection Approval: ✓ 체크
|
||||
- Enable Scene Management: ✓ 체크
|
||||
```
|
||||
|
||||
### Unity Transport 설정
|
||||
|
||||
**필수:**
|
||||
```
|
||||
Unity Transport:
|
||||
- Port: 4045
|
||||
- Address: 0.0.0.0 (모든 인터페이스 허용)
|
||||
- ServerListenAddress: 0.0.0.0
|
||||
```
|
||||
|
||||
### 라우터 포트 포워딩
|
||||
|
||||
**필수:**
|
||||
```
|
||||
라우터 포트 포워딩:
|
||||
- External Port: 4045
|
||||
- Internal Port: 4045
|
||||
- Protocol: TCP
|
||||
- Internal IP: 당신 컴퓨터의 IPv4 (ipconfig로 확인)
|
||||
```
|
||||
|
||||
**IP 확인:**
|
||||
```
|
||||
명령 프롬프트 → ipconfig
|
||||
IPv4 주소 찾기 (예: 192.168.1.50)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ 작동 중인지 확인
|
||||
|
||||
### 방법 1: yougetsignal (가장 신뢰)
|
||||
|
||||
```
|
||||
https://www.yougetsignal.com/tools/open-ports/
|
||||
|
||||
입력:
|
||||
- IP: 당신의 퍼블릭 IP (https://api.ipify.org)
|
||||
- Port: 4045
|
||||
|
||||
기대: "Port 4045 is open"
|
||||
```
|
||||
|
||||
### 방법 2: 콘솔 로그
|
||||
|
||||
**호스트 시작 성공:**
|
||||
```
|
||||
[ConnectionHandler] 서버 시작됨
|
||||
[ConnectionHandler] 스폰 포인트 X개를 찾았습니다
|
||||
[ConnectionHandler] 클라이언트 [ID] 연결됨
|
||||
[ConnectionHandler] 플레이어 [ID] 스폰됨
|
||||
```
|
||||
|
||||
**클라이언트 연결 성공:**
|
||||
```
|
||||
[ConnectionHandler] 클라이언트 [ID] 승인됨. 수동 스폰으로 대기.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎮 게임 플레이 방법
|
||||
|
||||
### 호스트 (당신)
|
||||
|
||||
1. 에디터에서 플레이 모드 시작
|
||||
2. 또는 빌드 실행
|
||||
3. 콘솔에서 "호스트 시작됨" 확인
|
||||
4. 팀원에게 퍼블릭 IP 알림
|
||||
5. 팀원이 접속할 때까지 대기
|
||||
|
||||
### 클라이언트 (팀원)
|
||||
|
||||
1. 에디터에서 플레이 모드 시작
|
||||
2. 네트워크 연결 UI에서 호스트의 퍼블릭 IP 입력
|
||||
3. "연결" 클릭
|
||||
4. 콘솔에서 "클라이언트 연결됨" 확인
|
||||
5. 게임 시작!
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 일반적인 문제 및 해결
|
||||
|
||||
### 문제 1: "ConnectionHandler: PlayerPrefab이 null입니다"
|
||||
|
||||
**원인:** Player Prefab이 NetworkManager에 할당되지 않음
|
||||
|
||||
**해결:**
|
||||
```
|
||||
NetworkManager 선택 → Network Config → Player Prefab
|
||||
Assets/Prefabs/Player/Player.prefab 드래그
|
||||
```
|
||||
|
||||
### 문제 2: 팀원이 "Failed to connect to server" 에러
|
||||
|
||||
**가능한 원인:**
|
||||
1. 틀린 퍼블릭 IP 입력
|
||||
2. 포트가 닫혀 있음 (호스트 재시작 필요)
|
||||
3. 방화벽 차단
|
||||
4. 다른 Unity/Netcode 버전
|
||||
|
||||
**해결:**
|
||||
1. 올바른 IP 확인 (https://api.ipify.org)
|
||||
2. yougetsignal에서 포트 4045 확인
|
||||
3. 팀원의 방화벽 허용
|
||||
4. Unity 버전 일치 확인
|
||||
|
||||
### 문제 3: 포트가 열렸다 닫혀
|
||||
|
||||
**원인:** 유니티 Netcode가 실제로 바인딩하지 않음
|
||||
|
||||
**해결:**
|
||||
```
|
||||
NetworkManagerQuickTest 실행
|
||||
NetworkManagerResetAndRestart 사용
|
||||
새로 시작
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 도구
|
||||
|
||||
### 유용한 스크립트
|
||||
|
||||
| 스크립트 | 용도 | 사용법 |
|
||||
|---------|---------|---------|
|
||||
| **NetworkManagerQuickTest** | 설정 확인 | 추가 → 우클릭 "Run Quick NetworkManager Test" |
|
||||
| **NetworkResetAndRestart** | 네트워크 리셋 | 추가 → 우클릭 "Reset Network and Restart Host" |
|
||||
| **PortListenerTest** | 포트 바인딩 테스트 | 추가 → 우클릭 "Test Port Binding Only" |
|
||||
|
||||
### 사용하지 않는 스크립트
|
||||
|
||||
- ❌ ContinuousPortMonitor (랙 발생)
|
||||
- ❌ 다른 진단 도구 (필요 없음)
|
||||
|
||||
---
|
||||
|
||||
## 🚀 빠른 시작 가이드
|
||||
|
||||
### 처음 설정하는 경우
|
||||
|
||||
```
|
||||
1. NetworkManager 찾기
|
||||
2. Player Prefab 할당 (Assets/Prefabs/Player/)
|
||||
3. Unity Transport 포트 4045 설정
|
||||
4. 라우터에서 포트 포워딩 설정
|
||||
5. 호스트 시작
|
||||
6. yougetsignal에서 포트 확인
|
||||
7. 팀원에게 퍼블릭 IP 공유
|
||||
8. 팀원 접속
|
||||
9. 게임 시작! 🎉
|
||||
```
|
||||
|
||||
### 이미 작동 중인 경우
|
||||
|
||||
```
|
||||
1. 호스트 시작
|
||||
2. yougetsignal에서 포트 4045 확인 (열려 있어야 함)
|
||||
3. 팀원에게 퍼블릭 IP 공유
|
||||
4. 팀원 접속
|
||||
5. 게임 시작! 🎉
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 💡 핵심 통찰
|
||||
|
||||
**당신의 상황:**
|
||||
- PortListenerTest: 작동 ✅ (포트 열림)
|
||||
- yougetsignal: 작동 ✅ (접속 가능)
|
||||
- 유니티 Netcode: **포트 닫혀** ❌
|
||||
|
||||
**해결책:**
|
||||
1. Player Prefab 할당 (NetworkManagerQuickTest로 확인)
|
||||
2. 팀원이 지금 테스트
|
||||
3. 콘솔 로그 확인
|
||||
|
||||
**성공 시:**
|
||||
```
|
||||
✓ Player Prefab: Player
|
||||
✓ Unity Netcode 시작 성공
|
||||
✓ 팀원 접속 성공
|
||||
✓ 플레이어 스폰됨
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 기술 정보
|
||||
|
||||
### 사용된 포트
|
||||
```
|
||||
포트: 4045
|
||||
프로토콜: TCP
|
||||
바인딩: 0.0.0.0 (모든 인터페이스)
|
||||
```
|
||||
|
||||
### 확인된 사항
|
||||
```
|
||||
✅ 포트 포워딩: 작동 (yougetsignal 증명)
|
||||
✅ 방화벽: 허용 (yougetsignal 증명)
|
||||
✅ OS 바인딩: 가능 (PortListenerTest 증명)
|
||||
❌ 유니티 Netcode: 바인딩 실패
|
||||
```
|
||||
|
||||
### 문제 분석
|
||||
|
||||
**포트 4045가 열리지 않는 이유:**
|
||||
- 유니티 Netcode가 포트에 바인딩하지 않음
|
||||
- Player Prefab이 할당되지 않았을 가능성 (90%)
|
||||
- 또는 네트워크 관리자 초기화 순서 문제
|
||||
|
||||
---
|
||||
|
||||
## ✅ 성공 확인사항
|
||||
|
||||
**모든 것이 작동할 때:**
|
||||
- [ ] 호스트: IsServer = True
|
||||
- [ ] 호스트: IsHost = True
|
||||
- [ ] Player Prefab: Player (할당됨)
|
||||
- [ ] Transport: 4045, 0.0.0.0
|
||||
- [ ] yougetsignal: "Port 4045 is open"
|
||||
- [ ] 콘솔: "클라이언트 [ID] 연결됨"
|
||||
- [ ] 콘솔: "플레이어 [ID] 스폰됨"
|
||||
- [ ] 팀원: 접속 성공
|
||||
|
||||
---
|
||||
|
||||
## 🎯 요약
|
||||
|
||||
**핵심 사항:**
|
||||
1. 포트 4045 열림 (yougetsignal 증명) ✅
|
||||
2. Player Prefab 할당 필요 (가능한 문제 원인)
|
||||
3. 팀원 지금 테스트
|
||||
4. 콘솔 로그 확인
|
||||
|
||||
**다음 단계:**
|
||||
1. NetworkManagerQuickTest 실행
|
||||
2. 팀원 테스트
|
||||
3. 문제 있으면 콘솔 로그 공유
|
||||
4. 성공하면 게임 시작! 🎉
|
||||
|
||||
---
|
||||
|
||||
**행운을 빕니다!** 🚀
|
||||
@@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef125ff435342b64f86eeea8dbef234f
|
||||
guid: 0c7074d751d043c418617553de184fc1
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
@@ -1,159 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Fixes common network connection issues with Unity Netcode
|
||||
/// </summary>
|
||||
public class NetworkConnectionFixer : MonoBehaviour
|
||||
{
|
||||
[Header("Auto-Fix Settings")]
|
||||
[SerializeField] private bool autoFixOnStart = true;
|
||||
[SerializeField] private bool ensureTransportSettings = true;
|
||||
[SerializeField] private bool increaseTimeouts = true;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
private UnityTransport _transport;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("[NetworkConnectionFixer] NetworkManager not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
_transport = _networkManager.GetComponent<UnityTransport>();
|
||||
if (_transport == null)
|
||||
{
|
||||
Debug.LogError("[NetworkConnectionFixer] UnityTransport not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (autoFixOnStart)
|
||||
{
|
||||
FixNetworkSettings();
|
||||
}
|
||||
}
|
||||
|
||||
public void FixNetworkSettings()
|
||||
{
|
||||
Debug.Log("[NetworkConnectionFixer] Applying network fixes...");
|
||||
|
||||
if (ensureTransportSettings)
|
||||
{
|
||||
FixTransportSettings();
|
||||
}
|
||||
|
||||
if (increaseTimeouts)
|
||||
{
|
||||
IncreaseTimeouts();
|
||||
}
|
||||
|
||||
Debug.Log("[NetworkConnectionFixer] Network fixes applied successfully!");
|
||||
}
|
||||
|
||||
private void FixTransportSettings()
|
||||
{
|
||||
Debug.Log("[NetworkConnectionFixer] Fixing transport settings...");
|
||||
|
||||
if (_transport == null) return;
|
||||
|
||||
ushort port = _transport.ConnectionData.Port;
|
||||
string address = _transport.ConnectionData.Address;
|
||||
|
||||
Debug.Log($"Current Port: {port}");
|
||||
Debug.Log($"Current Address: {address}");
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
Debug.LogWarning("[NetworkConnectionFixer] Invalid port detected, setting to 7777");
|
||||
_transport.SetConnectionData("0.0.0.0", 7777);
|
||||
}
|
||||
}
|
||||
|
||||
private void IncreaseTimeouts()
|
||||
{
|
||||
Debug.Log("[NetworkConnectionFixer] Increasing network timeouts...");
|
||||
|
||||
if (_transport == null) return;
|
||||
|
||||
int currentTimeout = _transport.ConnectTimeoutMS;
|
||||
Debug.Log($"Current Connect Timeout: {currentTimeout}ms");
|
||||
|
||||
if (currentTimeout < 10000)
|
||||
{
|
||||
_transport.ConnectTimeoutMS = 15000;
|
||||
Debug.Log("[NetworkConnectionFixer] Increased Connect Timeout to 15000ms (15 seconds)");
|
||||
}
|
||||
|
||||
int maxAttempts = _transport.MaxConnectAttempts;
|
||||
Debug.Log($"Current Max Connect Attempts: {maxAttempts}");
|
||||
|
||||
if (maxAttempts < 10)
|
||||
{
|
||||
_transport.MaxConnectAttempts = 10;
|
||||
Debug.Log("[NetworkConnectionFixer] Increased Max Connect Attempts to 10");
|
||||
}
|
||||
}
|
||||
|
||||
public void SetServerAddress(string ipAddress, ushort port)
|
||||
{
|
||||
if (_transport == null) return;
|
||||
|
||||
Debug.Log($"[NetworkConnectionFixer] Setting server address to {ipAddress}:{port}");
|
||||
_transport.SetConnectionData(ipAddress, port);
|
||||
}
|
||||
|
||||
public void SetListenAddress(string listenAddress, ushort port)
|
||||
{
|
||||
if (_transport == null) return;
|
||||
|
||||
Debug.Log($"[NetworkConnectionFixer] Setting listen address to {listenAddress}:{port}");
|
||||
_transport.SetConnectionData("0.0.0.0", port, listenAddress);
|
||||
}
|
||||
|
||||
[ContextMenu("Log Current Transport Settings")]
|
||||
public void LogTransportSettings()
|
||||
{
|
||||
if (_transport == null) return;
|
||||
|
||||
Debug.Log("=== CURRENT TRANSPORT SETTINGS ===");
|
||||
Debug.Log("Connection Data:");
|
||||
Debug.Log(" Address: " + _transport.ConnectionData.Address);
|
||||
Debug.Log(" Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log(" Server Listen Address: " + _transport.ConnectionData.ServerListenAddress);
|
||||
Debug.Log("Timeouts:");
|
||||
Debug.Log(" Connect Timeout (ms): " + _transport.ConnectTimeoutMS);
|
||||
Debug.Log(" Max Connect Attempts: " + _transport.MaxConnectAttempts);
|
||||
Debug.Log("Other:");
|
||||
Debug.Log(" Max Packet Queue Size: " + _transport.MaxPacketQueueSize);
|
||||
Debug.Log("===================================");
|
||||
}
|
||||
|
||||
[ContextMenu("Fix All Known Issues")]
|
||||
public void FixAllKnownIssues()
|
||||
{
|
||||
Debug.Log("[NetworkConnectionFixer] Fixing all known issues...");
|
||||
|
||||
FixNetworkSettings();
|
||||
LogTransportSettings();
|
||||
|
||||
Debug.Log("[NetworkConnectionFixer] All fixes applied!");
|
||||
}
|
||||
|
||||
[ContextMenu("Test Connection Setup")]
|
||||
public void TestConnectionSetup()
|
||||
{
|
||||
Debug.Log("=== CONNECTION SETUP TEST ===");
|
||||
Debug.Log("NetworkManager: " + (_networkManager != null ? "Found" : "NOT FOUND"));
|
||||
Debug.Log("UnityTransport: " + (_transport != null ? "Found" : "NOT FOUND"));
|
||||
Debug.Log("Player Prefab: " + (_networkManager?.NetworkConfig?.PlayerPrefab != null ? "Found" : "NOT FOUND"));
|
||||
Debug.Log("Connection Approval: " + (_networkManager?.NetworkConfig?.ConnectionApproval ?? false));
|
||||
Debug.Log("=============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,255 +0,0 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using System;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
public class NetworkDebugger : MonoBehaviour
|
||||
{
|
||||
[Header("Debug Settings")]
|
||||
[SerializeField] private bool enableVerboseLogging = true;
|
||||
[SerializeField] private bool logTransportEvents = true;
|
||||
|
||||
private Unity.Netcode.Transports.UTP.UnityTransport _transport;
|
||||
private NetworkManager _networkManager;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("[NetworkDebugger] NetworkManager not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
_transport = _networkManager.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (_transport == null)
|
||||
{
|
||||
Debug.LogError("[NetworkDebugger] UnityTransport not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
SubscribeToEvents();
|
||||
LogNetworkConfiguration();
|
||||
}
|
||||
|
||||
private void SubscribeToEvents()
|
||||
{
|
||||
if (_networkManager != null)
|
||||
{
|
||||
_networkManager.OnServerStarted += OnServerStarted;
|
||||
_networkManager.OnClientConnectedCallback += OnClientConnected;
|
||||
_networkManager.OnClientDisconnectCallback += OnClientDisconnected;
|
||||
_networkManager.ConnectionApprovalCallback += OnConnectionApproval;
|
||||
_networkManager.OnTransportFailure += OnTransportFailure;
|
||||
}
|
||||
|
||||
if (logTransportEvents && _transport != null)
|
||||
{
|
||||
LogTransportConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromEvents()
|
||||
{
|
||||
if (_networkManager != null)
|
||||
{
|
||||
_networkManager.OnServerStarted -= OnServerStarted;
|
||||
_networkManager.OnClientConnectedCallback -= OnClientConnected;
|
||||
_networkManager.OnClientDisconnectCallback -= OnClientDisconnected;
|
||||
_networkManager.ConnectionApprovalCallback -= OnConnectionApproval;
|
||||
_networkManager.OnTransportFailure -= OnTransportFailure;
|
||||
}
|
||||
}
|
||||
|
||||
private void LogNetworkConfiguration()
|
||||
{
|
||||
Debug.Log("=== NETWORK CONFIGURATION ===");
|
||||
Debug.Log("NetworkManager Present: " + (_networkManager != null));
|
||||
string transportType = _transport != null ? "Unity Transport" : "None";
|
||||
Debug.Log("Transport Type: " + transportType);
|
||||
LogTransportConfiguration();
|
||||
LogNetworkSettings();
|
||||
Debug.Log("============================");
|
||||
}
|
||||
|
||||
private void LogTransportConfiguration()
|
||||
{
|
||||
if (_transport == null) return;
|
||||
|
||||
Debug.Log("=== TRANSPORT CONFIGURATION ===");
|
||||
Debug.Log("Connection Data Address: " + _transport.ConnectionData.Address);
|
||||
Debug.Log("Connection Data Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log("Connection Data Server Listen Address: " + _transport.ConnectionData.ServerListenAddress);
|
||||
Debug.Log("Max Connect Attempts: " + _transport.MaxConnectAttempts);
|
||||
Debug.Log("Connect Timeout (ms): " + _transport.ConnectTimeoutMS);
|
||||
Debug.Log("Max Packet Queue Size: " + _transport.MaxPacketQueueSize);
|
||||
Debug.Log("================================");
|
||||
}
|
||||
|
||||
private void LogNetworkSettings()
|
||||
{
|
||||
if (_networkManager == null) return;
|
||||
|
||||
Debug.Log("=== NETWORK MANAGER SETTINGS ===");
|
||||
Debug.Log("NetworkConfig: " + (_networkManager.NetworkConfig != null));
|
||||
if (_networkManager.NetworkConfig != null)
|
||||
{
|
||||
Debug.Log("Player Prefab: " + (_networkManager.NetworkConfig.PlayerPrefab != null));
|
||||
Debug.Log("Connection Approval: " + _networkManager.NetworkConfig.ConnectionApproval);
|
||||
Debug.Log("Client Connection Buffer: " + _networkManager.NetworkConfig.ClientConnectionBufferTimeout);
|
||||
Debug.Log("Enable Scene Management: " + _networkManager.NetworkConfig.EnableSceneManagement);
|
||||
}
|
||||
Debug.Log("================================");
|
||||
}
|
||||
|
||||
private void OnServerStarted()
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkDebugger] Server Started Successfully</color>");
|
||||
Debug.Log("Listening on: " + _transport.ConnectionData.Address + ":" + _transport.ConnectionData.Port);
|
||||
Debug.Log("IsHost: " + _networkManager.IsHost);
|
||||
Debug.Log("IsServer: " + _networkManager.IsServer);
|
||||
}
|
||||
|
||||
private void OnClientConnected(ulong clientId)
|
||||
{
|
||||
if (enableVerboseLogging)
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkDebugger] Client Connected: " + clientId + "</color>");
|
||||
Debug.Log("Local Client ID: " + _networkManager.LocalClientId);
|
||||
Debug.Log("Connected Clients Count: " + _networkManager.ConnectedClients.Count);
|
||||
}
|
||||
|
||||
foreach (var client in _networkManager.ConnectedClients)
|
||||
{
|
||||
string playerStatus = client.Value.PlayerObject != null ? "Exists" : "NULL";
|
||||
Debug.Log(" Client ID: " + client.Key + ", Player Object: " + playerStatus);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnClientDisconnected(ulong clientId)
|
||||
{
|
||||
Debug.Log("<color=yellow>[NetworkDebugger] Client Disconnected: " + clientId + "</color>");
|
||||
Debug.Log("Reason: Check logs above for details");
|
||||
}
|
||||
|
||||
private void OnConnectionApproval(NetworkManager.ConnectionApprovalRequest request,
|
||||
NetworkManager.ConnectionApprovalResponse response)
|
||||
{
|
||||
Debug.Log("<color=magenta>[NetworkDebugger] Connection Approval Request from Client " + request.ClientNetworkId + "</color>");
|
||||
Debug.Log(" Payload Length: " + request.Payload.Length);
|
||||
Debug.Log(" Client ID: " + request.ClientNetworkId);
|
||||
|
||||
LogApprovalResponse(response);
|
||||
}
|
||||
|
||||
private void LogApprovalResponse(NetworkManager.ConnectionApprovalResponse response)
|
||||
{
|
||||
Debug.Log("<color=magenta>[NetworkDebugger] Approval Response:</color>");
|
||||
Debug.Log(" Approved: " + response.Approved);
|
||||
Debug.Log(" Create Player Object: " + response.CreatePlayerObject);
|
||||
Debug.Log(" Position: " + response.Position);
|
||||
Debug.Log(" Rotation: " + response.Rotation);
|
||||
Debug.Log(" Player Prefab Hash: " + response.PlayerPrefabHash);
|
||||
}
|
||||
|
||||
private void OnTransportFailure()
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkDebugger] TRANSPORT FAILURE!</color>");
|
||||
Debug.LogError("This usually indicates:");
|
||||
Debug.LogError("1. Port not forwarded correctly");
|
||||
Debug.LogError("2. Firewall blocking the connection");
|
||||
Debug.LogError("3. Wrong IP address");
|
||||
Debug.LogError("4. Server not listening on the correct address");
|
||||
Debug.LogError("5. Network timeout");
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (enableVerboseLogging && _networkManager != null)
|
||||
{
|
||||
MonitorConnectionState();
|
||||
}
|
||||
}
|
||||
|
||||
private void MonitorConnectionState()
|
||||
{
|
||||
if (_networkManager.IsServer && _networkManager.IsClient)
|
||||
{
|
||||
if (Time.frameCount % 300 == 0)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkDebugger] Host Mode - " + Time.time.ToString("F2") + "s</color>");
|
||||
Debug.Log(" Connected Clients: " + _networkManager.ConnectedClients.Count);
|
||||
Debug.Log(" Server Listening: " + _transport.ConnectionData.Address + ":" + _transport.ConnectionData.Port);
|
||||
}
|
||||
}
|
||||
else if (_networkManager.IsClient)
|
||||
{
|
||||
if (Time.frameCount % 300 == 0 && !_networkManager.IsConnectedClient)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkDebugger] Client Not Connected - " + Time.time.ToString("F2") + "s</color>");
|
||||
Debug.LogWarning(" Connecting to: " + _transport.ConnectionData.Address + ":" + _transport.ConnectionData.Port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
UnsubscribeFromEvents();
|
||||
}
|
||||
|
||||
[ContextMenu("Log Current Network State")]
|
||||
public void LogCurrentState()
|
||||
{
|
||||
Debug.Log("=== CURRENT NETWORK STATE ===");
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.Log("NetworkManager is NULL");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("Is Server: " + _networkManager.IsServer);
|
||||
Debug.Log("Is Client: " + _networkManager.IsClient);
|
||||
Debug.Log("Is Host: " + _networkManager.IsHost);
|
||||
Debug.Log("Is Connected Client: " + _networkManager.IsConnectedClient);
|
||||
Debug.Log("Local Client ID: " + _networkManager.LocalClientId);
|
||||
Debug.Log("Connected Clients Count: " + _networkManager.ConnectedClients.Count);
|
||||
|
||||
if (_transport != null)
|
||||
{
|
||||
Debug.Log("Transport Address: " + _transport.ConnectionData.Address);
|
||||
Debug.Log("Transport Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log("Server Listen Address: " + _transport.ConnectionData.ServerListenAddress);
|
||||
}
|
||||
|
||||
Debug.Log("==========================");
|
||||
}
|
||||
|
||||
[ContextMenu("Test Port Binding")]
|
||||
public void TestPortBinding()
|
||||
{
|
||||
if (_transport != null)
|
||||
{
|
||||
Debug.Log("<color=yellow>[NetworkDebugger] Port Binding Test:</color>");
|
||||
Debug.Log(" Address: " + _transport.ConnectionData.Address);
|
||||
Debug.Log(" Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log(" Server Listen Address: " + _transport.ConnectionData.ServerListenAddress);
|
||||
Debug.LogWarning("Note: Actual binding happens when StartHost/StartServer is called");
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Check Firewall Issues")]
|
||||
public void CheckPotentialFirewallIssues()
|
||||
{
|
||||
Debug.Log("=== POTENTIAL FIREWALL ISSUES ===");
|
||||
Debug.LogWarning("If you see 'Failed to connect to server' errors:");
|
||||
Debug.LogWarning("1. Check Windows Firewall settings");
|
||||
Debug.LogWarning("2. Allow Unity Editor and your build through firewall");
|
||||
Debug.LogWarning("3. Ensure port is properly forwarded in router");
|
||||
Debug.LogWarning("4. Test port with online port checker (e.g., canyouseeme.org)");
|
||||
Debug.LogWarning("5. Check antivirus/security software");
|
||||
Debug.Log("================================");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9abd8738f93d60a4fa097fdaf9349865
|
||||
@@ -1,269 +0,0 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Unity.Netcode;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
public class NetworkJoinUI : MonoBehaviour
|
||||
{
|
||||
[Header("UI References")]
|
||||
[SerializeField] private GameObject joinPanel;
|
||||
[SerializeField] private InputField ipInputField;
|
||||
[SerializeField] private InputField portInputField;
|
||||
[SerializeField] private Button joinButton;
|
||||
[SerializeField] private Button hostButton;
|
||||
[SerializeField] private Button disconnectButton;
|
||||
[SerializeField] private Text statusText;
|
||||
[SerializeField] private KeyCode toggleKey = KeyCode.J;
|
||||
|
||||
[Header("Settings")]
|
||||
[SerializeField] private string defaultIP = "127.0.0.1";
|
||||
[SerializeField] private string defaultPort = "7777";
|
||||
|
||||
private bool _isVisible = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
InitializeUI();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
SetupDefaultValues();
|
||||
SubscribeToEvents();
|
||||
UpdateStatus();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetKeyDown(toggleKey))
|
||||
{
|
||||
TogglePanel();
|
||||
}
|
||||
|
||||
if (NetworkManager.Singleton != null &&
|
||||
(NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer))
|
||||
{
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeUI()
|
||||
{
|
||||
if (joinPanel != null)
|
||||
{
|
||||
joinPanel.SetActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupDefaultValues()
|
||||
{
|
||||
if (ipInputField != null)
|
||||
{
|
||||
ipInputField.text = defaultIP;
|
||||
}
|
||||
|
||||
if (portInputField != null)
|
||||
{
|
||||
portInputField.text = defaultPort;
|
||||
}
|
||||
}
|
||||
|
||||
private void SubscribeToEvents()
|
||||
{
|
||||
if (joinButton != null)
|
||||
{
|
||||
joinButton.onClick.AddListener(OnJoinClicked);
|
||||
}
|
||||
|
||||
if (hostButton != null)
|
||||
{
|
||||
hostButton.onClick.AddListener(OnHostClicked);
|
||||
}
|
||||
|
||||
if (disconnectButton != null)
|
||||
{
|
||||
disconnectButton.onClick.AddListener(OnDisconnectClicked);
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromEvents()
|
||||
{
|
||||
if (joinButton != null)
|
||||
{
|
||||
joinButton.onClick.RemoveListener(OnJoinClicked);
|
||||
}
|
||||
|
||||
if (hostButton != null)
|
||||
{
|
||||
hostButton.onClick.RemoveListener(OnHostClicked);
|
||||
}
|
||||
|
||||
if (disconnectButton != null)
|
||||
{
|
||||
disconnectButton.onClick.RemoveListener(OnDisconnectClicked);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnJoinClicked()
|
||||
{
|
||||
if (NetworkManager.Singleton == null)
|
||||
{
|
||||
ShowError("NetworkManager not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
string ip = ipInputField != null ? ipInputField.text : defaultIP;
|
||||
string port = portInputField != null ? portInputField.text : defaultPort;
|
||||
|
||||
ushort portNum;
|
||||
if (!ushort.TryParse(port, out portNum))
|
||||
{
|
||||
ShowError("Invalid port number!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer)
|
||||
{
|
||||
ShowError("Already connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
var transport = NetworkManager.Singleton.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (transport != null)
|
||||
{
|
||||
transport.SetConnectionData(ip, portNum);
|
||||
}
|
||||
|
||||
NetworkManager.Singleton.StartClient();
|
||||
UpdateStatus();
|
||||
Debug.Log($"[NetworkJoinUI] Connecting to {ip}:{port}");
|
||||
}
|
||||
|
||||
private void OnHostClicked()
|
||||
{
|
||||
if (NetworkManager.Singleton == null)
|
||||
{
|
||||
ShowError("NetworkManager not found!");
|
||||
return;
|
||||
}
|
||||
|
||||
string port = portInputField != null ? portInputField.text : defaultPort;
|
||||
|
||||
ushort portNum;
|
||||
if (!ushort.TryParse(port, out portNum))
|
||||
{
|
||||
ShowError("Invalid port number!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (NetworkManager.Singleton.IsClient || NetworkManager.Singleton.IsServer)
|
||||
{
|
||||
ShowError("Already connected!");
|
||||
return;
|
||||
}
|
||||
|
||||
var transport = NetworkManager.Singleton.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (transport != null)
|
||||
{
|
||||
transport.SetConnectionData("0.0.0.0", portNum);
|
||||
}
|
||||
|
||||
NetworkManager.Singleton.StartHost();
|
||||
UpdateStatus();
|
||||
Debug.Log($"[NetworkJoinUI] Started Host on port {port}");
|
||||
}
|
||||
|
||||
private void OnDisconnectClicked()
|
||||
{
|
||||
if (NetworkManager.Singleton != null)
|
||||
{
|
||||
NetworkManager.Singleton.Shutdown();
|
||||
UpdateStatus();
|
||||
Debug.Log("[NetworkJoinUI] Disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateStatus()
|
||||
{
|
||||
if (statusText == null) return;
|
||||
|
||||
string status = GetNetworkStatus();
|
||||
statusText.text = status;
|
||||
}
|
||||
|
||||
private string GetNetworkStatus()
|
||||
{
|
||||
if (NetworkManager.Singleton == null)
|
||||
return "NetworkManager not found";
|
||||
|
||||
if (NetworkManager.Singleton.IsHost)
|
||||
return $"Hosting (Port: {GetActivePort()})";
|
||||
if (NetworkManager.Singleton.IsServer)
|
||||
return $"Server (Port: {GetActivePort()})";
|
||||
if (NetworkManager.Singleton.IsClient)
|
||||
return $"Client connected to {GetActiveIP()}:{GetActivePort()}";
|
||||
|
||||
return "Not connected";
|
||||
}
|
||||
|
||||
private string GetActiveIP()
|
||||
{
|
||||
if (NetworkManager.Singleton == null) return "N/A";
|
||||
|
||||
var transport = NetworkManager.Singleton.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (transport != null)
|
||||
{
|
||||
return transport.ConnectionData.Address;
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private string GetActivePort()
|
||||
{
|
||||
if (NetworkManager.Singleton == null) return "N/A";
|
||||
|
||||
var transport = NetworkManager.Singleton.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (transport != null)
|
||||
{
|
||||
return transport.ConnectionData.Port.ToString();
|
||||
}
|
||||
return "N/A";
|
||||
}
|
||||
|
||||
private void TogglePanel()
|
||||
{
|
||||
if (joinPanel != null)
|
||||
{
|
||||
_isVisible = !_isVisible;
|
||||
joinPanel.SetActive(_isVisible);
|
||||
UpdateStatus();
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowError(string message)
|
||||
{
|
||||
Debug.LogError($"[NetworkJoinUI] {message}");
|
||||
if (statusText != null)
|
||||
{
|
||||
statusText.text = $"Error: {message}";
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
UnsubscribeFromEvents();
|
||||
}
|
||||
|
||||
public void SetUIReferences(GameObject panel, InputField ipField, InputField portField, Button joinBtn, Button hostBtn, Button disconnectBtn, Text status)
|
||||
{
|
||||
joinPanel = panel;
|
||||
ipInputField = ipField;
|
||||
portInputField = portField;
|
||||
joinButton = joinBtn;
|
||||
hostButton = hostBtn;
|
||||
disconnectButton = disconnectBtn;
|
||||
statusText = status;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 824b1e5b92d2ce946b9f2c121a535c73
|
||||
244
Assets/Scripts/NetworkManagerQuickTest.cs
Normal file
244
Assets/Scripts/NetworkManagerQuickTest.cs
Normal file
@@ -0,0 +1,244 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Quick test to verify NetworkManager is working and accessible
|
||||
/// </summary>
|
||||
public class NetworkManagerQuickTest : MonoBehaviour
|
||||
{
|
||||
[Header("Test Settings")]
|
||||
[SerializeField] private bool runTestOnStart = true;
|
||||
[SerializeField] private bool showDetailedLogs = true;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (runTestOnStart)
|
||||
{
|
||||
RunQuickTest();
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Run Quick NetworkManager Test")]
|
||||
public void RunQuickTest()
|
||||
{
|
||||
Debug.Log("<color=cyan>=== NETWORKMANAGER QUICK TEST ===</color>");
|
||||
|
||||
TestNetworkManagerExists();
|
||||
TestPlayerPrefab();
|
||||
TestTransport();
|
||||
TestConnectionHandlers();
|
||||
|
||||
Debug.Log("<color=green>=== TEST COMPLETE ===</color>");
|
||||
}
|
||||
|
||||
private void TestNetworkManagerExists()
|
||||
{
|
||||
Debug.Log("<color=yellow>[1/4] Testing NetworkManager Existence...</color>");
|
||||
|
||||
NetworkManager nm = NetworkManager.Singleton;
|
||||
|
||||
if (nm == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ NetworkManager.Singleton is NULL!</color>");
|
||||
Debug.LogError("This means:");
|
||||
Debug.LogError("1. NetworkManager GameObject is not in scene");
|
||||
Debug.LogError("2. NetworkManager component is missing");
|
||||
Debug.LogError("3. NetworkManager hasn't been initialized yet");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>✓ NetworkManager found!</color>");
|
||||
Debug.Log(" IsServer: " + nm.IsServer);
|
||||
Debug.Log(" IsClient: " + nm.IsClient);
|
||||
Debug.Log(" IsHost: " + nm.IsHost);
|
||||
Debug.Log(" IsConnectedClient: " + nm.IsConnectedClient);
|
||||
Debug.Log(" LocalClientId: " + nm.LocalClientId);
|
||||
}
|
||||
|
||||
private void TestPlayerPrefab()
|
||||
{
|
||||
Debug.Log("<color=yellow>[2/4] Testing Player Prefab...</color>");
|
||||
|
||||
NetworkManager nm = NetworkManager.Singleton;
|
||||
if (nm == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Can't test - NetworkManager is null</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nm.NetworkConfig == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ NetworkConfig is null!</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
GameObject playerPrefab = nm.NetworkConfig.PlayerPrefab;
|
||||
|
||||
if (playerPrefab == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Player Prefab is NOT assigned!</color>");
|
||||
Debug.LogError("→ This is the #1 reason servers don't start!");
|
||||
Debug.LogError("→ FIX: Select NetworkManager → Network Config → Player Prefab");
|
||||
Debug.LogError("→ Drag your Player Prefab from Project to that field");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>✓ Player Prefab assigned: " + playerPrefab.name + "</color>");
|
||||
|
||||
var networkObject = playerPrefab.GetComponent<Unity.Netcode.NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>⚠ Player Prefab has NO NetworkObject!</color>");
|
||||
Debug.LogWarning("→ Add NetworkObject component to Player Prefab");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("<color=green>✓ Player Prefab has NetworkObject</color>");
|
||||
}
|
||||
}
|
||||
|
||||
private void TestTransport()
|
||||
{
|
||||
Debug.Log("<color=yellow>[3/4] Testing Unity Transport...</color>");
|
||||
|
||||
NetworkManager nm = NetworkManager.Singleton;
|
||||
if (nm == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Can't test - NetworkManager is null</color>");
|
||||
return;
|
||||
}
|
||||
|
||||
var transport = nm.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
|
||||
if (transport == null)
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Unity Transport not found on NetworkManager!</color>");
|
||||
Debug.LogError("→ FIX: Add Unity Transport component to NetworkManager GameObject");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>✓ Unity Transport found!</color>");
|
||||
Debug.Log(" Port: " + transport.ConnectionData.Port);
|
||||
Debug.Log(" Address: " + transport.ConnectionData.Address);
|
||||
Debug.Log(" ServerListenAddress: " + transport.ConnectionData.ServerListenAddress);
|
||||
|
||||
if (transport.ConnectionData.Port <= 0)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>⚠ Transport Port is not set (0)!</color>");
|
||||
Debug.LogWarning("→ FIX: Set Port to 40445 in Unity Transport component");
|
||||
}
|
||||
|
||||
if (transport.ConnectionData.Address == "127.0.0.1")
|
||||
{
|
||||
Debug.LogError("<color=red>✗ Transport Address is 127.0.0.1!</color>");
|
||||
Debug.LogError("→ This BLOCKS all remote connections!");
|
||||
Debug.LogError("→ FIX: Change Address to 0.0.0.0");
|
||||
}
|
||||
else if (transport.ConnectionData.Address == "0.0.0.0")
|
||||
{
|
||||
Debug.Log("<color=green>✓ Transport Address is 0.0.0.0 (accepts all connections)</color>");
|
||||
}
|
||||
}
|
||||
|
||||
private void TestConnectionHandlers()
|
||||
{
|
||||
Debug.Log("<color=yellow>[4/4] Testing Connection Handlers...</color>");
|
||||
|
||||
NetworkConnectionHandler handler = FindObjectOfType<NetworkConnectionHandler>();
|
||||
|
||||
if (handler == null)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>⚠ NetworkConnectionHandler not found!</color>");
|
||||
Debug.LogWarning("→ Manual player spawning may not work");
|
||||
Debug.LogWarning("→ FIX: Add NetworkConnectionHandler component to scene");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>✓ NetworkConnectionHandler found!</color>");
|
||||
Debug.Log("→ Manual player spawning should work");
|
||||
|
||||
PlayerSpawnPoint[] spawnPoints = FindObjectsByType<PlayerSpawnPoint>(FindObjectsSortMode.None);
|
||||
if (spawnPoints.Length > 0)
|
||||
{
|
||||
Debug.Log("<color=green>✓ Found " + spawnPoints.Length + " Player Spawn Point(s)</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>⚠ No Player Spawn Points found!</color>");
|
||||
Debug.LogWarning("→ Players may spawn at default position");
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Setup Report")]
|
||||
public void GenerateSetupReport()
|
||||
{
|
||||
Debug.Log("=== NETWORKMANAGER SETUP REPORT ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("CURRENT STATUS:");
|
||||
NetworkManager nm = NetworkManager.Singleton;
|
||||
|
||||
if (nm == null)
|
||||
{
|
||||
Debug.LogError("NetworkManager: NOT FOUND (NULL)");
|
||||
Debug.LogError("");
|
||||
Debug.LogError("CRITICAL ISSUE:");
|
||||
Debug.LogError("1. NetworkManager GameObject not in scene");
|
||||
Debug.LogError("2. NetworkManager component missing");
|
||||
Debug.LogError("3. NetworkManager not initialized");
|
||||
Debug.LogError("");
|
||||
Debug.LogError("QUICK FIX:");
|
||||
Debug.LogError("1. Check your scene for NetworkManager GameObject");
|
||||
Debug.LogError("2. Add NetworkManager component if missing");
|
||||
Debug.LogError("3. Check Console for initialization errors");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("NetworkManager: FOUND");
|
||||
Debug.Log("IsServer: " + nm.IsServer);
|
||||
Debug.Log("IsClient: " + nm.IsClient);
|
||||
Debug.Log("IsHost: " + nm.IsHost);
|
||||
|
||||
if (nm.NetworkConfig != null)
|
||||
{
|
||||
GameObject playerPrefab = nm.NetworkConfig.PlayerPrefab;
|
||||
if (playerPrefab == null)
|
||||
{
|
||||
Debug.LogError("");
|
||||
Debug.LogError("⚠ CRITICAL: Player Prefab NOT assigned!");
|
||||
Debug.LogError("This is the #1 cause of servers not starting!");
|
||||
Debug.LogError("");
|
||||
Debug.LogError("FIX IMMEDIATELY:");
|
||||
Debug.LogError("1. Select NetworkManager in scene");
|
||||
Debug.LogError("2. Inspector → Network Config → Player Prefab");
|
||||
Debug.LogError("3. Drag Player Prefab from Project to that field");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Log("Player Prefab: ASSIGNED (" + playerPrefab.name + ")");
|
||||
}
|
||||
}
|
||||
|
||||
var transport = nm.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
if (transport != null)
|
||||
{
|
||||
Debug.Log("Transport Port: " + transport.ConnectionData.Port);
|
||||
Debug.Log("Transport Address: " + transport.ConnectionData.Address);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("Unity Transport: NOT FOUND");
|
||||
}
|
||||
}
|
||||
|
||||
Debug.Log("");
|
||||
Debug.Log("NEXT STEPS:");
|
||||
Debug.Log("1. If Player Prefab is NULL: Assign it immediately!");
|
||||
Debug.Log("2. Check NetworkManagerValidator → Validate");
|
||||
Debug.Log("3. Use ForceTransportBinding → Force Then Start Host");
|
||||
Debug.Log("4. Test on yougetsignal");
|
||||
Debug.Log("===============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/NetworkManagerQuickTest.cs.meta
Normal file
2
Assets/Scripts/NetworkManagerQuickTest.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d695616342b92d449295973fc4cda7e
|
||||
346
Assets/Scripts/NetworkManagerValidator.cs
Normal file
346
Assets/Scripts/NetworkManagerValidator.cs
Normal file
@@ -0,0 +1,346 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Validates NetworkManager configuration before starting server
|
||||
/// Checks for common issues that prevent server from starting
|
||||
/// </summary>
|
||||
public class NetworkManagerValidator : MonoBehaviour
|
||||
{
|
||||
[Header("Validation Settings")]
|
||||
[SerializeField] private bool validateOnStart = true;
|
||||
[SerializeField] private bool validateOnEnable = true;
|
||||
[SerializeField] private bool showDetailedLogs = true;
|
||||
|
||||
[Header("Auto-Fix")]
|
||||
[SerializeField] private bool autoFixIfPossible = true;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
private bool _hasValidated = false;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
StartCoroutine(InitializeDelayed());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator InitializeDelayed()
|
||||
{
|
||||
Debug.Log("[NetworkValidator] Waiting for NetworkManager to initialize...");
|
||||
|
||||
int attempts = 0;
|
||||
while (_networkManager == null && attempts < 50)
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
attempts++;
|
||||
}
|
||||
}
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ CRITICAL: NetworkManager not found after 50 attempts!</color>");
|
||||
Debug.LogError("[NetworkValidator] Ensure NetworkManager is in scene and has 'NetworkManager' component");
|
||||
yield break;
|
||||
}
|
||||
|
||||
Debug.Log("[NetworkValidator] NetworkManager found!");
|
||||
|
||||
if (validateOnAwake)
|
||||
{
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
ValidateConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (validateOnStart && !_hasValidated)
|
||||
{
|
||||
ValidateConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (validateOnEnable && !_hasValidated)
|
||||
{
|
||||
ValidateConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Validate NetworkManager Configuration")]
|
||||
public void ValidateConfiguration()
|
||||
{
|
||||
Debug.Log("<color=yellow>=== NETWORKMANAGER VALIDATION ===</color>");
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ NetworkManager is NULL!</color>");
|
||||
Debug.LogError("[NetworkValidator] Cannot validate configuration");
|
||||
return;
|
||||
}
|
||||
|
||||
_hasValidated = true;
|
||||
|
||||
bool allValid = true;
|
||||
|
||||
allValid &= CheckPlayerPrefab();
|
||||
allValid &= CheckNetworkConfig();
|
||||
allValid &= CheckTransport();
|
||||
allValid &= CheckRequiredComponents();
|
||||
|
||||
Debug.Log("");
|
||||
if (allValid)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ ALL CHECKS PASSED - NetworkManager is ready!</color>");
|
||||
Debug.Log("[NetworkValidator] Server should start successfully");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ VALIDATION FAILED - Server may NOT start!</color>");
|
||||
Debug.LogError("[NetworkValidator] Please fix the issues above");
|
||||
}
|
||||
|
||||
Debug.Log("=================================");
|
||||
}
|
||||
|
||||
private bool CheckPlayerPrefab()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkValidator] 1. Checking Player Prefab...</color>");
|
||||
|
||||
if (_networkManager.NetworkConfig == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ NetworkConfig is NULL!</color>");
|
||||
return false;
|
||||
}
|
||||
|
||||
GameObject playerPrefab = _networkManager.NetworkConfig.PlayerPrefab;
|
||||
|
||||
if (playerPrefab == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ Player Prefab is NOT assigned!</color>");
|
||||
Debug.LogError("<color=red>[NetworkValidator] This is the #1 cause of servers not starting!</color>");
|
||||
Debug.LogError("[NetworkValidator] FIX:");
|
||||
Debug.LogError("1. Select NetworkManager in scene");
|
||||
Debug.LogError("2. Inspector → Network Config → Player Prefab");
|
||||
Debug.LogError("3. Drag your Player Prefab from Project window");
|
||||
Debug.LogError("4. Assign to Player Prefab field");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Player Prefab assigned: " + playerPrefab.name + "</color>");
|
||||
|
||||
NetworkObject networkObject = playerPrefab.GetComponent<NetworkObject>();
|
||||
if (networkObject == null)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ Player Prefab has NO NetworkObject!</color>");
|
||||
Debug.LogWarning("[NetworkValidator] FIX: Add NetworkObject component to Player Prefab");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Player Prefab has NetworkObject</color>");
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckNetworkConfig()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkValidator] 2. Checking Network Config...</color>");
|
||||
|
||||
if (_networkManager.NetworkConfig == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ NetworkConfig is NULL!</color>");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool configValid = true;
|
||||
|
||||
bool connectionApproval = _networkManager.NetworkConfig.ConnectionApproval;
|
||||
if (connectionApproval)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Connection Approval: ENABLED</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ Connection Approval: DISABLED</color>");
|
||||
Debug.LogWarning("[NetworkValidator] All connections will be auto-approved");
|
||||
}
|
||||
|
||||
bool sceneManagement = _networkManager.NetworkConfig.EnableSceneManagement;
|
||||
if (sceneManagement)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Scene Management: ENABLED</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ Scene Management: DISABLED</color>");
|
||||
}
|
||||
|
||||
float clientBuffer = _networkManager.NetworkConfig.ClientConnectionBufferTimeout;
|
||||
Debug.Log("[NetworkValidator] Client Connection Buffer: " + clientBuffer + "s");
|
||||
|
||||
return configValid;
|
||||
}
|
||||
|
||||
private bool CheckTransport()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkValidator] 3. Checking Transport...</color>");
|
||||
|
||||
var transport = _networkManager.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>();
|
||||
|
||||
if (transport == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ UnityTransport not found!</color>");
|
||||
Debug.LogError("[NetworkValidator] FIX: Add Unity Transport component to NetworkManager");
|
||||
return false;
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Unity Transport exists</color>");
|
||||
|
||||
ushort port = transport.ConnectionData.Port;
|
||||
Debug.Log("[NetworkValidator] Transport Port: " + port);
|
||||
|
||||
if (port <= 0)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ Transport Port is not set (0)</color>");
|
||||
Debug.LogWarning("[NetworkValidator] FIX: Set port to 40445 in Unity Transport component");
|
||||
return false;
|
||||
}
|
||||
|
||||
string address = transport.ConnectionData.Address;
|
||||
Debug.Log("[NetworkValidator] Transport Address: " + address);
|
||||
|
||||
if (address == "127.0.0.1")
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkValidator] ❌ Transport Address is 127.0.0.1!</color>");
|
||||
Debug.LogError("<color=red>[NetworkValidator] This blocks ALL remote connections!</color>");
|
||||
Debug.LogError("[NetworkValidator] FIX: Set to 0.0.0.0");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (address == "0.0.0.0")
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Transport Address: 0.0.0.0 (accepts all connections)</color>");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool CheckRequiredComponents()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkValidator] 4. Checking Required Components...</color>");
|
||||
|
||||
bool allPresent = true;
|
||||
|
||||
NetworkConnectionHandler connectionHandler = FindObjectOfType<NetworkConnectionHandler>();
|
||||
if (connectionHandler != null)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ NetworkConnectionHandler found</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ NetworkConnectionHandler NOT found</color>");
|
||||
Debug.LogWarning("[NetworkValidator] FIX: Add NetworkConnectionHandler to scene");
|
||||
Debug.LogWarning("[NetworkValidator] Required for manual player spawning");
|
||||
}
|
||||
|
||||
PlayerSpawnPoint[] spawnPoints = FindObjectsByType<PlayerSpawnPoint>(FindObjectsSortMode.None);
|
||||
if (spawnPoints.Length > 0)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkValidator] ✅ Found " + spawnPoints.Length + " Player Spawn Point(s)</color>");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ No Player Spawn Points found</color>");
|
||||
Debug.LogWarning("[NetworkValidator] FIX: Add PlayerSpawnPoint component to empty GameObject(s)");
|
||||
}
|
||||
|
||||
AutoHost autoHost = FindObjectOfType<AutoHost>();
|
||||
if (autoHost != null && autoHost.enabled)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkValidator] ⚠ AutoHost is enabled!</color>");
|
||||
Debug.LogWarning("[NetworkValidator] This might interfere with manual host startup");
|
||||
Debug.LogWarning("[NetworkValidator] Consider disabling AutoHost");
|
||||
}
|
||||
|
||||
return allPresent;
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Fix Report")]
|
||||
public void GenerateFixReport()
|
||||
{
|
||||
Debug.Log("=== NETWORKMANAGER FIX REPORT ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("PROBLEM: PortListenerTest works, but Unity Netcode doesn't");
|
||||
Debug.Log("");
|
||||
Debug.Log("MOST LIKELY CAUSE:");
|
||||
Debug.LogError("1. ❌ Player Prefab is NOT assigned (90% probability)");
|
||||
Debug.LogWarning("2. ⚠ NetworkManager has initialization order issue");
|
||||
Debug.LogWarning("3. ⚠ Transport not configured correctly");
|
||||
Debug.LogWarning("4. ⚠ AutoHost interfering");
|
||||
Debug.Log("");
|
||||
Debug.Log("QUICK FIX:");
|
||||
Debug.Log("1. Select NetworkManager in scene");
|
||||
Debug.Log("2. Inspector → Network Config → Player Prefab");
|
||||
Debug.Log("3. Drag your Player Prefab from Project window");
|
||||
Debug.Log("4. Drop into Player Prefab field");
|
||||
Debug.Log("5. Save scene");
|
||||
Debug.Log("6. Start Host");
|
||||
Debug.Log("7. Test on yougetsignal IMMEDIATELY");
|
||||
Debug.Log("");
|
||||
Debug.Log("COMPLETE FIX:");
|
||||
Debug.Log("1. Right-click this component → 'Validate NetworkManager Configuration'");
|
||||
Debug.Log("2. Fix any errors shown");
|
||||
Debug.Log("3. Add ForceTransportBinding");
|
||||
Debug.Log("4. Right-click → 'Force Then Start Host'");
|
||||
Debug.Log("5. Add ContinuousPortMonitor");
|
||||
Debug.Log("6. Right-click → 'Start Port Monitoring'");
|
||||
Debug.Log("7. Watch Console for port status");
|
||||
Debug.Log("=================================");
|
||||
}
|
||||
|
||||
[ContextMenu("Check If Server Can Start")]
|
||||
public void CheckIfServerCanStart()
|
||||
{
|
||||
Debug.Log("=== CAN SERVER START? ===");
|
||||
|
||||
bool canStart = true;
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("❌ NO - NetworkManager is NULL");
|
||||
canStart = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_networkManager.NetworkConfig?.PlayerPrefab == null)
|
||||
{
|
||||
Debug.LogError("❌ NO - Player Prefab NOT assigned");
|
||||
canStart = false;
|
||||
}
|
||||
|
||||
if (_networkManager.GetComponent<Unity.Netcode.Transports.UTP.UnityTransport>() == null)
|
||||
{
|
||||
Debug.LogError("❌ NO - UnityTransport NOT found");
|
||||
canStart = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (canStart)
|
||||
{
|
||||
Debug.Log("<color=green>✅ YES - Server should be able to start</color>");
|
||||
Debug.Log("If port still closed after starting:");
|
||||
Debug.Log("1. Check Console for errors");
|
||||
Debug.Log("2. Verify Port Forwarding is working");
|
||||
Debug.Log("3. Verify Firewall is allowing port");
|
||||
}
|
||||
|
||||
Debug.Log("========================");
|
||||
}
|
||||
|
||||
private bool validateOnAwake = true;
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/NetworkManagerValidator.cs.meta
Normal file
2
Assets/Scripts/NetworkManagerValidator.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 926d1f00e8a21ab44a9f4cc1bf0028bd
|
||||
237
Assets/Scripts/NetworkResetAndRestart.cs
Normal file
237
Assets/Scripts/NetworkResetAndRestart.cs
Normal file
@@ -0,0 +1,237 @@
|
||||
using UnityEngine;
|
||||
using Unity.Netcode;
|
||||
using Unity.Netcode.Transports.UTP;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Completely restarts network to fix stuck/closed port issues
|
||||
/// </summary>
|
||||
public class NetworkResetAndRestart : MonoBehaviour
|
||||
{
|
||||
[Header("Reset Settings")]
|
||||
[SerializeField] private bool autoResetOnStart = false;
|
||||
[SerializeField] private ushort targetPort = 40445;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
private UnityTransport _transport;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
if (autoResetOnStart)
|
||||
{
|
||||
StartCoroutine(DoResetAndRestart());
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Reset Network and Restart Host")]
|
||||
public void ExecuteResetAndRestart()
|
||||
{
|
||||
StartCoroutine(DoResetAndRestart());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator DoResetAndRestart()
|
||||
{
|
||||
Debug.Log("<color=yellow>=== NETWORK RESET AND RESTART ===</color>");
|
||||
|
||||
// Step 1: Get references
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkReset] NetworkManager not found!</color>");
|
||||
yield break;
|
||||
}
|
||||
|
||||
_transport = _networkManager.GetComponent<UnityTransport>();
|
||||
if (_transport == null)
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkReset] UnityTransport not found!</color>");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Step 2: Log current state
|
||||
LogCurrentState();
|
||||
|
||||
// Step 3: Shutdown if running
|
||||
if (_networkManager.IsServer || _networkManager.IsClient)
|
||||
{
|
||||
Debug.Log("<color=yellow>[NetworkReset] Shutting down current network...</color>");
|
||||
_networkManager.Shutdown();
|
||||
|
||||
// Wait for complete shutdown
|
||||
float startTime = Time.time;
|
||||
while ((_networkManager.IsServer || _networkManager.IsClient) && Time.time - startTime < 10f)
|
||||
{
|
||||
yield return new WaitForSeconds(0.1f);
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Network shutdown complete</color>");
|
||||
}
|
||||
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
// Step 4: Force port release
|
||||
ForcePortRelease();
|
||||
|
||||
yield return new WaitForSeconds(1f);
|
||||
|
||||
// Step 5: Reconfigure transport
|
||||
Debug.Log("<color=cyan>[NetworkReset] Reconfiguring transport...</color>");
|
||||
_transport.SetConnectionData(
|
||||
"0.0.0.0", // Listen on all interfaces
|
||||
targetPort, // Port 40445
|
||||
"0.0.0.0" // Server listen on all interfaces
|
||||
);
|
||||
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Transport configured to 0.0.0.0:" + targetPort + "</color>");
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Server will accept connections from ANY IP</color>");
|
||||
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
|
||||
// Step 6: Start host
|
||||
Debug.Log("<color=cyan>[NetworkReset] Starting fresh host...</color>");
|
||||
_networkManager.StartHost();
|
||||
|
||||
// Wait for host to start
|
||||
float hostStartTime = Time.time;
|
||||
while (!_networkManager.IsServer && Time.time - hostStartTime < 10f)
|
||||
{
|
||||
yield return new WaitForSeconds(0.2f);
|
||||
}
|
||||
|
||||
if (_networkManager.IsServer)
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Host started successfully!</color>");
|
||||
|
||||
// Verify port is actually listening
|
||||
yield return new WaitForSeconds(1f);
|
||||
VerifyPortListening();
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogError("<color=red>[NetworkReset] ✗ Failed to start host!</color>");
|
||||
}
|
||||
|
||||
Debug.Log("<color=green>=== RESET AND RESTART COMPLETE ===</color>");
|
||||
}
|
||||
|
||||
private void LogCurrentState()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkReset] Current Network State:</color>");
|
||||
Debug.Log(" IsServer: " + _networkManager.IsServer);
|
||||
Debug.Log(" IsClient: " + _networkManager.IsClient);
|
||||
Debug.Log(" IsHost: " + _networkManager.IsHost);
|
||||
Debug.Log(" IsConnectedClient: " + _networkManager.IsConnectedClient);
|
||||
Debug.Log(" LocalClientId: " + _networkManager.LocalClientId);
|
||||
Debug.Log(" ConnectedClients: " + _networkManager.ConnectedClients.Count);
|
||||
|
||||
if (_transport != null)
|
||||
{
|
||||
Debug.Log(" Transport.Port: " + _transport.ConnectionData.Port);
|
||||
Debug.Log(" Transport.Address: " + _transport.ConnectionData.Address);
|
||||
}
|
||||
}
|
||||
|
||||
private void ForcePortRelease()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkReset] Forcing port release...</color>");
|
||||
|
||||
try
|
||||
{
|
||||
// Try to bind and release port to ensure it's freed
|
||||
TcpListener testListener = new TcpListener(IPAddress.Any, targetPort);
|
||||
testListener.Start();
|
||||
testListener.Stop();
|
||||
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Port " + targetPort + " is released</color>");
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkReset] ⚠ Could not bind port for release: " + e.Message + "</color>");
|
||||
Debug.LogWarning("[NetworkReset] This is normal if port is in use");
|
||||
}
|
||||
}
|
||||
|
||||
private void VerifyPortListening()
|
||||
{
|
||||
Debug.Log("<color=cyan>[NetworkReset] Verifying port is listening...</color>");
|
||||
|
||||
try
|
||||
{
|
||||
using (TcpClient client = new TcpClient("127.0.0.1", targetPort))
|
||||
{
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Successfully connected to localhost:" + targetPort + "</color>");
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Unity IS listening on port</color>");
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ Port should now be accessible on yougetsignal</color>");
|
||||
Debug.Log("");
|
||||
Debug.Log("<color=green>[NetworkReset] ✓ TEST ON YOUGETSIGNAL NOW!</color>");
|
||||
}
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
Debug.LogWarning("<color=yellow>[NetworkReset] ⚠ Could not connect to localhost:" + targetPort + "</color>");
|
||||
Debug.LogWarning("[NetworkReset] Error: " + e.Message);
|
||||
Debug.LogWarning("[NetworkReset] This might mean server didn't actually start");
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Check Current Network Status")]
|
||||
public void CheckStatus()
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
if (_networkManager == null)
|
||||
{
|
||||
Debug.LogError("NetworkManager not found");
|
||||
return;
|
||||
}
|
||||
|
||||
Debug.Log("=== NETWORK STATUS ===");
|
||||
Debug.Log("IsServer: " + _networkManager.IsServer);
|
||||
Debug.Log("IsClient: " + _networkManager.IsClient);
|
||||
Debug.Log("IsHost: " + _networkManager.IsHost);
|
||||
Debug.Log("IsConnectedClient: " + _networkManager.IsConnectedClient);
|
||||
Debug.Log("LocalClientId: " + _networkManager.LocalClientId);
|
||||
Debug.Log("ConnectedClients: " + _networkManager.ConnectedClients.Count);
|
||||
|
||||
foreach (var client in _networkManager.ConnectedClients)
|
||||
{
|
||||
Debug.Log(" Client " + client.Key + ": " +
|
||||
(client.Value.PlayerObject != null ? "Has Player" : "No Player"));
|
||||
}
|
||||
|
||||
Debug.Log("===================");
|
||||
}
|
||||
|
||||
[ContextMenu("Generate Instructions")]
|
||||
public void GenerateInstructions()
|
||||
{
|
||||
Debug.Log("=== NETWORK RESET INSTRUCTIONS ===");
|
||||
Debug.Log("");
|
||||
Debug.Log("PROBLEM:");
|
||||
Debug.Log("- Port stays closed even though config is correct");
|
||||
Debug.Log("- Server reports running but port not accessible");
|
||||
Debug.Log("");
|
||||
Debug.Log("SOLUTION: Complete network reset");
|
||||
Debug.Log("");
|
||||
Debug.Log("STEPS:");
|
||||
Debug.Log("1. Add NetworkResetAndRestart to scene");
|
||||
Debug.Log("2. Right-click → 'Reset Network and Restart Host'");
|
||||
Debug.Log("3. Wait for '✓ Host started successfully'");
|
||||
Debug.Log("4. Test on yougetsignal IMMEDIATELY");
|
||||
Debug.Log("");
|
||||
Debug.Log("WHAT IT DOES:");
|
||||
Debug.Log("1. Shuts down any current network");
|
||||
Debug.Log("2. Forces port release");
|
||||
Debug.Log("3. Reconfigures transport to 0.0.0.0");
|
||||
Debug.Log("4. Starts fresh host");
|
||||
Debug.Log("5. Verifies port is actually listening");
|
||||
Debug.Log("");
|
||||
Debug.Log("EXPECTED RESULT:");
|
||||
Debug.Log("✓ Port 40445 shows OPEN on yougetsignal");
|
||||
Debug.Log("✓ Teammates can connect");
|
||||
Debug.Log("===============================");
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/NetworkResetAndRestart.cs.meta
Normal file
2
Assets/Scripts/NetworkResetAndRestart.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d15e6615b07f55843a759c775a08bc89
|
||||
245
Assets/Scripts/PortListenerTestSimultaneous.cs
Normal file
245
Assets/Scripts/PortListenerTestSimultaneous.cs
Normal file
@@ -0,0 +1,245 @@
|
||||
using UnityEngine;
|
||||
using System.Net.Sockets;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using Unity.Netcode;
|
||||
// Removed System.Diagnostics to fix Debug.Log ambiguity
|
||||
|
||||
namespace Northbound
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs PortListenerTest method simultaneously with Unity Netcode
|
||||
/// Uses exact same TcpListener method that works
|
||||
/// </summary>
|
||||
public class PortListenerTestSimultaneous : MonoBehaviour
|
||||
{
|
||||
[Header("Settings")]
|
||||
[SerializeField] private ushort testPort = 40445;
|
||||
[SerializeField] private bool autoStartOnEnable = false;
|
||||
|
||||
private TcpListener _listener;
|
||||
private Thread _listenerThread;
|
||||
private volatile bool _isRunning = false;
|
||||
private volatile bool _hasConnection = false;
|
||||
|
||||
private NetworkManager _networkManager;
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
if (autoStartOnEnable)
|
||||
{
|
||||
StartTest();
|
||||
}
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_networkManager = NetworkManager.Singleton;
|
||||
}
|
||||
|
||||
[ContextMenu("Start Test Only")]
|
||||
public void StartTest()
|
||||
{
|
||||
UnityEngine.Debug.Log("<color=magenta>=== PORT LISTENER TEST (SIMULTANEOUS) ===</color>");
|
||||
UnityEngine.Debug.Log("Using EXACT same method as PortListenerTest");
|
||||
UnityEngine.Debug.Log("Method: TcpListener(IPAddress.Any, " + testPort + ")");
|
||||
UnityEngine.Debug.Log("This PROVES port CAN be bound");
|
||||
|
||||
_isRunning = true;
|
||||
_listenerThread = new Thread(ListenerThread);
|
||||
_listenerThread.IsBackground = true;
|
||||
_listenerThread.Start();
|
||||
}
|
||||
|
||||
[ContextMenu("Start Test + Unity Netcode")]
|
||||
public void StartTestAndUnity()
|
||||
{
|
||||
UnityEngine.Debug.Log("<color=magenta>=== STARTING TEST + UNITY NETCODE ===</color>");
|
||||
|
||||
StartTest();
|
||||
|
||||
StartCoroutine(StartUnityDelayed());
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator StartUnityDelayed()
|
||||
{
|
||||
UnityEngine.Debug.Log("Waiting 3 seconds before starting Unity...");
|
||||
yield return new WaitForSeconds(3f);
|
||||
|
||||
UnityEngine.Debug.Log("Starting Unity Netcode...");
|
||||
|
||||
if (_networkManager == null)
|
||||
{
|
||||
UnityEngine.Debug.LogError("NetworkManager not found!");
|
||||
yield break;
|
||||
}
|
||||
|
||||
if (_networkManager.IsServer || _networkManager.IsClient)
|
||||
{
|
||||
UnityEngine.Debug.Log("Unity already running, shutting down first...");
|
||||
_networkManager.Shutdown();
|
||||
yield return new WaitForSeconds(2f);
|
||||
}
|
||||
|
||||
_networkManager.StartHost();
|
||||
|
||||
float startTime = Time.time;
|
||||
while (!_networkManager.IsServer && Time.time - startTime < 10f)
|
||||
{
|
||||
UnityEngine.Debug.Log("Waiting for Unity to start...");
|
||||
yield return new WaitForSeconds(0.5f);
|
||||
}
|
||||
|
||||
if (_networkManager.IsServer)
|
||||
{
|
||||
UnityEngine.Debug.Log("<color=green>Unity Netcode started successfully!</color>");
|
||||
UnityEngine.Debug.Log("Now BOTH listeners are running:");
|
||||
UnityEngine.Debug.Log(" 1. TcpListener (proven method)");
|
||||
UnityEngine.Debug.Log(" 2. Unity Netcode");
|
||||
}
|
||||
else
|
||||
{
|
||||
UnityEngine.Debug.LogError("Unity Netcode failed to start!");
|
||||
}
|
||||
}
|
||||
|
||||
private void ListenerThread()
|
||||
{
|
||||
try
|
||||
{
|
||||
_listener = new TcpListener(IPAddress.Any, testPort);
|
||||
_listener.Start();
|
||||
|
||||
UnityEngine.Debug.Log("<color=green>Successfully bound to 0.0.0.0:" + testPort + "</color>");
|
||||
UnityEngine.Debug.Log("PROVED: Port " + testPort + " CAN be bound");
|
||||
UnityEngine.Debug.Log("PROVED: OS allows binding");
|
||||
UnityEngine.Debug.Log("PROVED: Firewall allows binding");
|
||||
|
||||
while (_isRunning)
|
||||
{
|
||||
if (_listener.Pending())
|
||||
{
|
||||
try
|
||||
{
|
||||
TcpClient client = _listener.AcceptTcpClient();
|
||||
IPEndPoint endPoint = (IPEndPoint)client.Client.RemoteEndPoint;
|
||||
|
||||
_hasConnection = true;
|
||||
|
||||
UnityEngine.Debug.Log("<color=green>Connection received from " + endPoint.Address + ":" + endPoint.Port + "</color>");
|
||||
UnityEngine.Debug.Log("PROVES: Port IS OPEN and working");
|
||||
UnityEngine.Debug.Log("PROVES: Port forwarding IS working");
|
||||
UnityEngine.Debug.Log("PROVES: Test listener method WORKS");
|
||||
|
||||
Thread.Sleep(100);
|
||||
client.Close();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("Error accepting: " + e.Message);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
}
|
||||
}
|
||||
|
||||
_listener.Stop();
|
||||
}
|
||||
catch (System.Exception e)
|
||||
{
|
||||
_isRunning = false;
|
||||
UnityEngine.Debug.LogError("<color=red>Failed to bind port " + testPort + "</color>");
|
||||
UnityEngine.Debug.LogError("Error: " + e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
[ContextMenu("Stop Test")]
|
||||
public void StopTest()
|
||||
{
|
||||
UnityEngine.Debug.Log("Stopping test listener...");
|
||||
_isRunning = false;
|
||||
|
||||
if (_listener != null)
|
||||
{
|
||||
_listener.Stop();
|
||||
}
|
||||
|
||||
if (_listenerThread != null && _listenerThread.IsAlive)
|
||||
{
|
||||
_listenerThread.Join(1000);
|
||||
}
|
||||
|
||||
_hasConnection = false;
|
||||
}
|
||||
|
||||
[ContextMenu("Check Status")]
|
||||
public void CheckStatus()
|
||||
{
|
||||
UnityEngine.Debug.Log("=== SIMULTANEOUS TEST STATUS ===");
|
||||
UnityEngine.Debug.Log("Test Listener Running: " + _isRunning);
|
||||
UnityEngine.Debug.Log("Has Connection: " + _hasConnection);
|
||||
|
||||
if (_networkManager != null)
|
||||
{
|
||||
UnityEngine.Debug.Log("Unity IsServer: " + _networkManager.IsServer);
|
||||
UnityEngine.Debug.Log("Unity IsClient: " + _networkManager.IsClient);
|
||||
UnityEngine.Debug.Log("Unity IsHost: " + _networkManager.IsHost);
|
||||
}
|
||||
|
||||
if (_hasConnection)
|
||||
{
|
||||
UnityEngine.Debug.Log("<color=green>Port IS OPEN - Test listener works!</color>");
|
||||
}
|
||||
|
||||
UnityEngine.Debug.Log("===================================");
|
||||
}
|
||||
|
||||
[ContextMenu("Explanation")]
|
||||
public void ShowExplanation()
|
||||
{
|
||||
UnityEngine.Debug.Log("=== EXPLANATION ===");
|
||||
UnityEngine.Debug.Log("");
|
||||
UnityEngine.Debug.Log("WHAT THIS DOES:");
|
||||
UnityEngine.Debug.Log("Uses EXACT same method as PortListenerTest:");
|
||||
UnityEngine.Debug.Log(" new TcpListener(IPAddress.Any, 40445)");
|
||||
UnityEngine.Debug.Log(" listener.Start()");
|
||||
UnityEngine.Debug.Log("");
|
||||
UnityEngine.Debug.Log("WHY PORTLISTENERTEST WORKS:");
|
||||
UnityEngine.Debug.Log("✓ Successfully binds to port");
|
||||
UnityEngine.Debug.Log("✓ Port is OPEN on yougetsignal");
|
||||
UnityEngine.Debug.Log("✓ OS allows binding");
|
||||
UnityEngine.Debug.Log("✓ Firewall allows binding");
|
||||
UnityEngine.Debug.Log("");
|
||||
UnityEngine.Debug.Log("WHY WE RUN IT WITH UNITY:");
|
||||
UnityEngine.Debug.Log("→ To see if they conflict");
|
||||
UnityEngine.Debug.Log("→ To see if Unity Netcode binds");
|
||||
UnityEngine.Debug.Log("→ To identify what's different");
|
||||
UnityEngine.Debug.Log("");
|
||||
UnityEngine.Debug.Log("EXPECTED RESULTS:");
|
||||
UnityEngine.Debug.Log("If test listener receives connection:");
|
||||
UnityEngine.Debug.Log(" → Port IS OPEN");
|
||||
UnityEngine.Debug.Log(" → Test method WORKS");
|
||||
UnityEngine.Debug.Log(" → Something is wrong with Unity Netcode");
|
||||
UnityEngine.Debug.Log("");
|
||||
UnityEngine.Debug.Log("HOW TO USE:");
|
||||
UnityEngine.Debug.Log("1. Add to scene");
|
||||
UnityEngine.Debug.Log("2. Right-click 'Start Test + Unity Netcode'");
|
||||
UnityEngine.Debug.Log("3. Wait 3 seconds");
|
||||
UnityEngine.Debug.Log("4. See if both start");
|
||||
UnityEngine.Debug.Log("5. Test on yougetsignal");
|
||||
UnityEngine.Debug.Log("=============================");
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
StopTest();
|
||||
}
|
||||
|
||||
private void OnDisable()
|
||||
{
|
||||
StopTest();
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/PortListenerTestSimultaneous.cs.meta
Normal file
2
Assets/Scripts/PortListenerTestSimultaneous.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba79d51f450e07d439690667a6535133
|
||||
7
Assets/Scripts/QUICK_FIX_GUIDE.md.meta
Normal file
7
Assets/Scripts/QUICK_FIX_GUIDE.md.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cf33aade754bf4948841fba12d66d87e
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user