Hi, I want to make a FPS game with 4~50 players in a room. I'm working on Photon bolt and now want a hosting server like server 2.0. I found a guide on Photon's site below and following it.
https://doc.photonengine.com/en-us/bolt/current/demos-and-tutorials/playfab-integration/overview After several minuts I created a new build on Multiplayer, I keep watching it is on "Unhealthy" state.
I went to "Virtual Machines" tap, and saw the state was "TooManyServerRestarts".
I googled about the state, I thought that it would be a problem about heartbeat.
After googling, I knew about MockVmAgent.exe and installed docker and downloaded tools about it.
Below is the answer about my build.
I also attached my "MultiplayerSettings.json" setting below.
I executed "netstat /ano" to find listening ports to change AgentListeningPort, PortMappingsList:NodePort, GamePort:Number on setting.
About above, there were 2 problems.
1. I don't know wheather I should select TCP or UDP port for each ones.
2. I keep watching warning if I change AgentListeningPort. So I didn't change AgentListeningPort even
the port "56001" is not opened.
And I saw "CurrentGameState" kept "StandingBy".
I thought that would be a cause of "Unhealthy".
Let me keep commenting below...
PS C:\PlayFabVmAgent> .\MockVmAgent.exe Thank you for using PlayFab Multiplayer Servers Check this page for debugging tips: https://github.com/PlayFab/gsdkSamples/blob/master/Debugging.md Warning: SessionCookie is not specified. TitleId: A4BA7FB BuildId: 53f60e89-4bea-4219-90e4-95dc2704afef VmId: xcloudwusu4uyz5daouzl:WestUs:258a366f-359f-421e-9c98-55f7c5e03adc:tvmps_1941af7e017f4c2f9c301deca6111c640bd44b43d91c4a518017a3724302107a_d Root output folder: D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54 info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0] User profile is available. Using 'C:\Users\mana1\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. Local Multiplayer Agent is listening on port 56001 Player1, Player2 info: MockPlayFabVmAgent[0] Starting process for session host with instance number 0 and process info: FileName - D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54\ExtAssets\SH0\A0\Dungeon.io.multi.exe, Args - -batchmode -nographics. info: MockPlayFabVmAgent[0] Creating the configuration file at D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54\Config\SH0\gsdkConfig.json info: MockPlayFabVmAgent[0] Started process for session host. Instance Number: 0, UniqueId: 8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9, ProcessId: 7344 info: MockPlayFabVmAgent[0] Waiting for heartbeats from the game server..... info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 84.8853ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 153.2747ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 32.555ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 35.7498ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 12.5016ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 14.2722ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 27.8888ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 30.9549ms 200 application/json; charset=utf-8 PS C:\PlayFabVmAgent>
Below is my MultiplayerSettings.json setting.
{ "RunContainer": false, "OutputFolder": "D:\\Unity_project\\Dungeon.io.multi\\log", "NumHeartBeatsForActivateResponse": 10, "NumHeartBeatsForTerminateResponse": 60, "AgentListeningPort": 56001, "AssetDetails": [ { "MountPath": "C:\\Assets", "LocalFilePath": "C:\\Assets\\pack\\Dungeon.io.multi.zip" } ], "GameCertificateDetails": [], "PortMappingsList": [ [ { "NodePort": 53799, "GamePort": { "Name": "master_server1", "Number": 58219, "Protocol": "UDP" } } ] ], "ProcessStartParameters": { "StartGameCommand": "Dungeon.io.multi.exe -batchmode -nographics" }, "ContainerStartParameters": { "StartGameCommand": "C:\\Assets\\Dungeon.io.multi.exe", "ResourceLimits": { "Cpus": 0, "MemoryGib": 0 }, "ImageDetails": { "Registry": "mcr.microsoft.com", "ImageName": "playfab/multiplayer", "ImageTag": "wsc-10.0.17763.973.1", "Username": "", "Password": "" } }, "SessionConfig": { "SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946", "SessionCookie": null, "InitialPlayers": [ "Player1", "Player2" ] }, "TitleId": "", "BuildId": "00000000-0000-0000-0000-000000000000", "Region": "WestUs" }
Following the sample of Photon bolt, it looks like only call PlayFabMultiplayerAgentAPI.Start() and PlayFabMultiplayerAgentAPI.ReadyForPlayers().
And PlayFabMultiplayerAgentAPI.ReadyForPlayers() function makes CurrentGameState as StandingBy.
So I though, if I want to change Active and Terminating, I should add some more action.
But it's a bit difficult blending 2 solutions(which are totally new for me) I don't know what I should refer to add some more action.
private void PlayFabStart() { Debug.Log("Starting PlayFabMultiplayerAgentAPI"); _connectedPlayers = new List<ConnectedPlayer>(); PlayFabMultiplayerAgentAPI.Start(); PlayFabMultiplayerAgentAPI.IsDebugging = Debugging; PlayFabMultiplayerAgentAPI.OnMaintenanceCallback += OnMaintenance; PlayFabMultiplayerAgentAPI.OnShutDownCallback += OnShutdown; PlayFabMultiplayerAgentAPI.OnServerActiveCallback += OnServerActive; PlayFabMultiplayerAgentAPI.OnAgentErrorCallback += OnAgentError; ConfigurePlayFabLogs(); StartCoroutine(ReadyForPlayers()); } private void ConfigurePlayFabLogs() { var logFolderPath = PlayFabMultiplayerAgentAPI.GetConfigSettings() [PlayFabMultiplayerAgentAPI.LogFolderKey]; BoltLog.Add(new PlayfabLogger(logFolderPath)); } private IEnumerator ReadyForPlayers() { Debug.Log("Starting ReadyForPlayers"); yield return new WaitForSeconds(.5f); PlayFabMultiplayerAgentAPI.ReadyForPlayers(); } // Below function is from PlayFabMultiplayerAgentAPI.cs public static void ReadyForPlayers() { if(CurrentState.CurrentGameState == GameState.Active) { string msg = "Cannot call ReadyForPlayers on an Active server"; throw new Exception(msg); } CurrentState.CurrentGameState = GameState.StandingBy; }
Could you guide me?
,Hi, I want to make a FPS game with 4~50 players in a room. I'm working on Photon bolt and now want a hosting server like server 2.0. I found a guide on Photon's site below and following it.
https://doc.photonengine.com/en-us/bolt/current/demos-and-tutorials/playfab-integration/overview After several minuts I created a new build on Multiplayer, I keep watching it is on "Unhealthy" state.
I went to "Virtual Machines" tap, and saw the state was "TooManyServerRestarts".
I googled about the state, I thought that it would be a problem about heartbeat.
After googling, I knew about MockVmAgent.exe and installed docker and downloaded tools about it.
Below is the answer about my build.
I also attached my "MultiplayerSettings.json" setting below.
I executed "netstat /ano" to find listening ports to change AgentListeningPort, PortMappingsList:NodePort, GamePort:Number on setting.
About above, there were 2 problems.
1. I don't know wheather I should select TCP or UDP port for each ones.
2. I keep watching warning if I change AgentListeningPort. So I didn't change AgentListeningPort even
the port "56001" is not opened.
And I saw "CurrentGameState" kept "StandingBy".
I thought that would be a cause of "Unhealthy".
Let me keep commenting below...
PS C:\PlayFabVmAgent> .\MockVmAgent.exe Thank you for using PlayFab Multiplayer Servers Check this page for debugging tips: https://github.com/PlayFab/gsdkSamples/blob/master/Debugging.md Warning: SessionCookie is not specified. TitleId: A4BA7FB BuildId: 53f60e89-4bea-4219-90e4-95dc2704afef VmId: xcloudwusu4uyz5daouzl:WestUs:258a366f-359f-421e-9c98-55f7c5e03adc:tvmps_1941af7e017f4c2f9c301deca6111c640bd44b43d91c4a518017a3724302107a_d Root output folder: D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54 info: Microsoft.AspNetCore.DataProtection.KeyManagement.XmlKeyManager[0] User profile is available. Using 'C:\Users\mana1\AppData\Local\ASP.NET\DataProtection-Keys' as key repository and Windows DPAPI to encrypt keys at rest. Local Multiplayer Agent is listening on port 56001 Player1, Player2 info: MockPlayFabVmAgent[0] Starting process for session host with instance number 0 and process info: FileName - D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54\ExtAssets\SH0\A0\Dungeon.io.multi.exe, Args - -batchmode -nographics. info: MockPlayFabVmAgent[0] Creating the configuration file at D:\Unity_project\Dungeon.io.multi\log\PlayFabVmAgentOutput\2021-01-21T07-24-54\Config\SH0\gsdkConfig.json info: MockPlayFabVmAgent[0] Started process for session host. Instance Number: 0, UniqueId: 8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9, ProcessId: 7344 info: MockPlayFabVmAgent[0] Waiting for heartbeats from the game server..... info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 84.8853ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 153.2747ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 32.555ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 35.7498ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 12.5016ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 14.2722ms 200 application/json; charset=utf-8 info: Microsoft.AspNetCore.Hosting.Diagnostics[1] Request starting HTTP/1.1 POST http://127.0.0.1:56001/v1/sessionHosts/8689ebda-50e7-43ec-b1fa-3cf2cafa9bf9/heartbeats application/json 78 info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3] Route matched with {action = "ProcessHeartbeat", controller = "SessionHost"}. Executing controller action with signature System.Threading.Tasks.Task`1[Microsoft.AspNetCore.Mvc.IActionResult] ProcessHeartbeat(System.String, Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo) on controller MockVmAgent.Controllers.SessionHostController (MockVmAgent). CurrentGameState: StandingBy info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1] Executing ObjectResult, writing value of type 'Microsoft.Azure.Gaming.AgentInterfaces.SessionHostHeartbeatInfo'. info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2] Executed action MockVmAgent.Controllers.SessionHostController.ProcessHeartbeat (MockVmAgent) in 27.8888ms info: Microsoft.AspNetCore.Hosting.Diagnostics[2] Request finished in 30.9549ms 200 application/json; charset=utf-8 PS C:\PlayFabVmAgent>
Below is my MultiplayerSettings.json setting.
{ "RunContainer": false, "OutputFolder": "D:\\Unity_project\\Dungeon.io.multi\\log", "NumHeartBeatsForActivateResponse": 10, "NumHeartBeatsForTerminateResponse": 60, "AgentListeningPort": 56001, "AssetDetails": [ { "MountPath": "C:\\Assets", "LocalFilePath": "C:\\Assets\\pack\\Dungeon.io.multi.zip" } ], "GameCertificateDetails": [], "PortMappingsList": [ [ { "NodePort": 53799, "GamePort": { "Name": "master_server1", "Number": 58219, "Protocol": "UDP" } } ] ], "ProcessStartParameters": { "StartGameCommand": "Dungeon.io.multi.exe -batchmode -nographics" }, "ContainerStartParameters": { "StartGameCommand": "C:\\Assets\\Dungeon.io.multi.exe", "ResourceLimits": { "Cpus": 0, "MemoryGib": 0 }, "ImageDetails": { "Registry": "mcr.microsoft.com", "ImageName": "playfab/multiplayer", "ImageTag": "wsc-10.0.17763.973.1", "Username": "", "Password": "" } }, "SessionConfig": { "SessionId": "ba67d671-512a-4e7d-a38c-2329ce181946", "SessionCookie": null, "InitialPlayers": [ "Player1", "Player2" ] }, "TitleId": "", "BuildId": "00000000-0000-0000-0000-000000000000", "Region": "WestUs" }
Following the sample of Photon bolt, it looks like only call PlayFabMultiplayerAgentAPI.Start() and PlayFabMultiplayerAgentAPI.ReadyForPlayers().
And PlayFabMultiplayerAgentAPI.ReadyForPlayers() function makes CurrentGameState as StandingBy.
So I though, if I want to change Active and Terminating, I should add some more action.
But it's a bit difficult blending 2 solutions(which are totally new for me) I don't know what I should refer to add some more action.
private void PlayFabStart() { Debug.Log("Starting PlayFabMultiplayerAgentAPI"); _connectedPlayers = new List<ConnectedPlayer>(); PlayFabMultiplayerAgentAPI.Start(); PlayFabMultiplayerAgentAPI.IsDebugging = Debugging; PlayFabMultiplayerAgentAPI.OnMaintenanceCallback += OnMaintenance; PlayFabMultiplayerAgentAPI.OnShutDownCallback += OnShutdown; PlayFabMultiplayerAgentAPI.OnServerActiveCallback += OnServerActive; PlayFabMultiplayerAgentAPI.OnAgentErrorCallback += OnAgentError; ConfigurePlayFabLogs(); StartCoroutine(ReadyForPlayers()); } private void ConfigurePlayFabLogs() { var logFolderPath = PlayFabMultiplayerAgentAPI.GetConfigSettings() [PlayFabMultiplayerAgentAPI.LogFolderKey]; BoltLog.Add(new PlayfabLogger(logFolderPath)); } private IEnumerator ReadyForPlayers() { Debug.Log("Starting ReadyForPlayers"); yield return new WaitForSeconds(.5f); PlayFabMultiplayerAgentAPI.ReadyForPlayers(); } // Below function is from PlayFabMultiplayerAgentAPI.cs public static void ReadyForPlayers() { if(CurrentState.CurrentGameState == GameState.Active) { string msg = "Cannot call ReadyForPlayers on an Active server"; throw new Exception(msg); } CurrentState.CurrentGameState = GameState.StandingBy; }
Could you guide me?