diff --git a/Assembly-CSharp.csproj b/Assembly-CSharp.csproj index 8e4cb8b..5360f65 100644 --- a/Assembly-CSharp.csproj +++ b/Assembly-CSharp.csproj @@ -105,6 +105,7 @@ + diff --git a/Assets/Scripts/CONNECTION_TROUBLESHOOTING.md b/Assets/Scripts/CONNECTION_TROUBLESHOOTING.md new file mode 100644 index 0000000..1357b4b --- /dev/null +++ b/Assets/Scripts/CONNECTION_TROUBLESHOOTING.md @@ -0,0 +1,163 @@ +# 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) diff --git a/Assets/Scripts/ConnectionDiagnostics.cs b/Assets/Scripts/ConnectionDiagnostics.cs new file mode 100644 index 0000000..c8da6e0 --- /dev/null +++ b/Assets/Scripts/ConnectionDiagnostics.cs @@ -0,0 +1,310 @@ +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("=== RUNNING CONNECTION DIAGNOSTICS ==="); + + InitializeComponents(); + CheckNetworkManager(); + CheckTransport(); + CheckPlayerPrefab(); + CheckConnectionApproval(); + + if (autoFixIssues) + { + FixCommonIssues(); + } + + GenerateReport(); + Debug.Log("=== DIAGNOSTICS COMPLETE ==="); + } + + private void InitializeComponents() + { + _networkManager = NetworkManager.Singleton; + if (_networkManager == null) + { + Debug.LogError("[Diagnostics] NetworkManager not found!"); + return; + } + + _transport = _networkManager.GetComponent(); + if (_transport == null) + { + Debug.LogError("[Diagnostics] UnityTransport not found!"); + return; + } + } + + private void CheckNetworkManager() + { + Debug.Log("[1/5] Checking NetworkManager..."); + + 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("[2/5] Checking UnityTransport..."); + + 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("[3/5] Checking Player Prefab..."); + + 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(); + if (networkObject == null) + { + Debug.LogError("✗ Player Prefab has no NetworkObject component!"); + } + else + { + Debug.Log("✓ Player Prefab has NetworkObject"); + } + } + + private void CheckConnectionApproval() + { + Debug.Log("[4/5] Checking Connection Approval..."); + + 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(); + 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("[5/5] Fixing Common Issues..."); + + 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("=== DIAGNOSTICS REPORT ==="); + + string status = GetOverallStatus(); + Color color = GetStatusColor(status); + + Debug.Log("" + status + ""); + + 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("======================="); + } + } +} diff --git a/Assets/Scripts/IMMEDIATE_FIX.md b/Assets/Scripts/IMMEDIATE_FIX.md new file mode 100644 index 0000000..31341c6 --- /dev/null +++ b/Assets/Scripts/IMMEDIATE_FIX.md @@ -0,0 +1,164 @@ +# 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 +[NetworkDebugger] TRANSPORT FAILURE! +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! 🎮 diff --git a/Assets/Scripts/NetworkConnectionFixer.cs b/Assets/Scripts/NetworkConnectionFixer.cs new file mode 100644 index 0000000..517f44b --- /dev/null +++ b/Assets/Scripts/NetworkConnectionFixer.cs @@ -0,0 +1,159 @@ +using UnityEngine; +using Unity.Netcode; +using Unity.Netcode.Transports.UTP; + +namespace Northbound +{ + /// + /// Fixes common network connection issues with Unity Netcode + /// + 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(); + 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("============================="); + } + } +} diff --git a/Assets/Scripts/NetworkDebugger.cs b/Assets/Scripts/NetworkDebugger.cs new file mode 100644 index 0000000..85c32ef --- /dev/null +++ b/Assets/Scripts/NetworkDebugger.cs @@ -0,0 +1,255 @@ +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(); + 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("[NetworkDebugger] Server Started Successfully"); + 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("[NetworkDebugger] Client Connected: " + clientId + ""); + 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("[NetworkDebugger] Client Disconnected: " + clientId + ""); + Debug.Log("Reason: Check logs above for details"); + } + + private void OnConnectionApproval(NetworkManager.ConnectionApprovalRequest request, + NetworkManager.ConnectionApprovalResponse response) + { + Debug.Log("[NetworkDebugger] Connection Approval Request from Client " + request.ClientNetworkId + ""); + Debug.Log(" Payload Length: " + request.Payload.Length); + Debug.Log(" Client ID: " + request.ClientNetworkId); + + LogApprovalResponse(response); + } + + private void LogApprovalResponse(NetworkManager.ConnectionApprovalResponse response) + { + Debug.Log("[NetworkDebugger] Approval Response:"); + 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("[NetworkDebugger] TRANSPORT FAILURE!"); + 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("[NetworkDebugger] Host Mode - " + Time.time.ToString("F2") + "s"); + 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("[NetworkDebugger] Client Not Connected - " + Time.time.ToString("F2") + "s"); + 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("[NetworkDebugger] Port Binding Test:"); + 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("================================"); + } + } +} diff --git a/Assets/Scripts/NetworkDebugger.cs.meta b/Assets/Scripts/NetworkDebugger.cs.meta new file mode 100644 index 0000000..aacf090 --- /dev/null +++ b/Assets/Scripts/NetworkDebugger.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 9abd8738f93d60a4fa097fdaf9349865 \ No newline at end of file diff --git a/Assets/Scripts/QUICK_FIX_GUIDE.md b/Assets/Scripts/QUICK_FIX_GUIDE.md new file mode 100644 index 0000000..5d91c00 --- /dev/null +++ b/Assets/Scripts/QUICK_FIX_GUIDE.md @@ -0,0 +1,160 @@ +# Quick Fix Guide for "Failed to Connect to Server" + +## Your Issue: Teammate sees "CONNECTED" but can't join + +This is likely a **Firewall** issue even with port forwarding. + +## Immediate Actions (Try in Order) + +### 1. Disable Windows Firewall Temporarily (Test Only) +``` +Windows Security → Firewall & network protection → Private network → Microsoft Defender Firewall: OFF +Public network → Microsoft Defender Firewall: OFF +``` +Then test connection. If it works, re-enable and create specific rule for Unity. + +### 2. Add Unity Exclusion to Firewall +Run these commands as Administrator in PowerShell/CMD: + +``` +# Allow Unity Editor +netsh advfirewall firewall add rule name="Unity Editor" dir=in action=allow program="%ProgramFiles%\Unity\Hub\Editor\*\Unity.exe" enable=yes + +# Allow your built executable (replace 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 +``` + +### 3. Verify Port Forwarding is Working +Go to: https://www.yougetsignal.com/tools/open-ports/ +- Enter your PUBLIC IP (what you give to teammate) +- Enter port 7777 +- Click "Check Port" + +**Expected:** "Port 7777 is open on [YOUR PUBLIC IP]" +**If closed:** Port forwarding is incorrect + +### 4. Add Debug Scripts to Scene +Add these components to your NetworkManager GameObject: +1. **ConnectionDiagnostics** - Checks for configuration issues +2. **NetworkDebugger** - Shows detailed connection logs +3. **NetworkConnectionFixer** - Fixes common timeout issues + +Right-click each and select "Run Diagnostics" or "Fix All Known Issues" + +## What to Check in Console + +### Host Should See: +``` +✓ [NetworkConnectionFixer] Network fixes applied +✓ [ConnectionDiagnostics] System Healthy +✓ [NetworkDebugger] Server Started Successfully +✓ [NetworkDebugger] Listening on: 0.0.0.0:7777 +✓ [NetworkDebugger] Client Connected: [ID] +✓ [ConnectionHandler] 클라이언트 [ID] 승인됨. 수동 스폰으로 대기. +``` + +### Client Should See: +``` +✓ [NetworkConnectionFixer] Network fixes applied +✓ [ConnectionDiagnostics] System Healthy +✓ [NetworkDebugger] Connection Approval Request from Client [ID] +✓ [NetworkDebugger] Approval Response: Approved: true +``` + +## If Still Not Working + +### Check These Settings: + +**On NetworkManager GameObject:** +- [ ] Player Prefab assigned +- [ ] Network Prefabs list populated +- [ ] Transport component = Unity Transport (UTP) + +**On Unity Transport Component:** +- [ ] ConnectionData.Port = 7777 (or your port) +- [ ] ConnectionData.Address = **0.0.0.0** for Host +- [ ] Connect Timeout MS = 15000 +- [ ] Max Connect Attempts = 10 + +**In NetworkManager Inspector (Network Config):** +- [ ] Connection Approval = **checked** +- [ ] Enable Scene Management = **checked** + +## Common Mistakes + +❌ Using 127.0.0.1 or 192.168.x.x for teammate +✓ Use your PUBLIC IP for teammate + +❌ Firewall blocking Unity +✓ Add exception for Unity and your game + +❌ Port not actually forwarded +✓ Verify with online port checker + +❌ Wrong transport address on host +✓ Host should use 0.0.0.0, client uses YOUR public IP + +❌ Player prefab missing NetworkObject +✓ Ensure player prefab has NetworkObject component + +## Quick Test Sequence + +1. **Test Local:** + - Start Host (connect to 127.0.0.1 from same instance) + - If this fails: Project setup issue + +2. **Test LAN:** + - Use 192.168.x.x (local network IP) + - If this fails: Network/Firewall issue + +3. **Test Internet:** + - Use public IP + - If this fails: Port forwarding issue + +## Console Commands for Diagnostics + +Add this to a MonoBehaviour: +```csharp +[ContextMenu("Check Everything")] +void CheckEverything() +{ + Debug.Log("IsServer: " + NetworkManager.Singleton.IsServer); + Debug.Log("IsClient: " + NetworkManager.Singleton.IsClient); + Debug.Log("ConnectedClients: " + NetworkManager.Singleton.ConnectedClients.Count); + Debug.Log("Local IP: " + NetworkUtility.GetLocalIPv4()); +} +``` + +## Last Resort Solutions + +1. **Use VPN/Hamachi** + - Creates virtual LAN between you and teammate + - No port forwarding needed + - Both connect to VPN IP + +2. **Use Unity Relay** + - Built into Unity Netcode + - Bypasses NAT/Firewall completely + - Requires Unity Services account + +3. **Host on Cloud Server** + - AWS/Azure/Google Cloud + - Static IP, no port forwarding + - More reliable + +## Share These for Help + +If still broken, share: +1. Full Console log (Host and Client) +2. Screenshot: NetworkManager inspector +3. Screenshot: Unity Transport settings +4. Port checker result screenshot +5. Windows Firewall rules screenshot + +--- + +**Most likely issue:** Windows Firewall is blocking even with port forwarding. +**Fix:** Run firewall commands in step 2.