@@ -64,8 +64,8 @@ public RpcCommunicator(CommunicatorInitParameters communicatorInitParameters)
64
64
65
65
internal static bool CheckCommunicationVersionsAreCompatible(
66
66
string unityCommunicationVersion,
67
- string pythonApiVersion,
68
- string pythonLibraryVersion )
67
+ string pythonApiVersion
68
+ )
69
69
{
70
70
var unityVersion = new Version(unityCommunicationVersion);
71
71
var pythonVersion = new Version(pythonApiVersion);
@@ -92,9 +92,10 @@ internal static bool CheckCommunicationVersionsAreCompatible(
92
92
/// Sends the initialization parameters through the Communicator.
93
93
/// Is used by the academy to send initialization parameters to the communicator.
94
94
/// </summary>
95
- /// <returns>The External Initialization Parameters received .</returns>
95
+ /// <returns>Whether the connection was successful .</returns>
96
96
/// <param name="initParameters">The Unity Initialization Parameters to be sent.</param>
97
- public UnityRLInitParameters Initialize(CommunicatorInitParameters initParameters)
97
+ /// <param name="initParametersOut">The External Initialization Parameters received.</param>
98
+ public bool Initialize(CommunicatorInitParameters initParameters, out UnityRLInitParameters initParametersOut)
98
99
{
99
100
var academyParameters = new UnityRLInitializationOutputProto
100
101
{
@@ -113,62 +114,75 @@ public UnityRLInitParameters Initialize(CommunicatorInitParameters initParameter
113
114
{
114
115
RlInitializationOutput = academyParameters
115
116
},
116
- out input);
117
-
118
- var pythonPackageVersion = initializationInput.RlInitializationInput.PackageVersion;
119
- var pythonCommunicationVersion = initializationInput.RlInitializationInput.CommunicationVersion;
120
- var unityCommunicationVersion = initParameters.unityCommunicationVersion;
121
-
122
- TrainingAnalytics.SetTrainerInformation(pythonPackageVersion, pythonCommunicationVersion);
123
-
124
- var communicationIsCompatible = CheckCommunicationVersionsAreCompatible(unityCommunicationVersion,
125
- pythonCommunicationVersion,
126
- pythonPackageVersion);
127
-
128
- // Initialization succeeded part-way. The most likely cause is a mismatch between the communicator
129
- // API strings, so log an explicit warning if that's the case.
130
- if (initializationInput != null && input == null)
117
+ out input
118
+ );
119
+ }
120
+ catch (Exception ex)
121
+ {
122
+ if (ex is RpcException rpcException)
131
123
{
132
- if (!communicationIsCompatible)
133
- {
134
- Debug.LogWarningFormat(
135
- "Communication protocol between python ({0}) and Unity ({1}) have different " +
136
- "versions which make them incompatible. Python library version: {2}.",
137
- pythonCommunicationVersion, initParameters.unityCommunicationVersion,
138
- pythonPackageVersion
139
- );
140
- }
141
- else
124
+
125
+ switch (rpcException.Status.StatusCode)
142
126
{
143
- Debug.LogWarningFormat(
144
- "Unknown communication error between Python. Python communication protocol: {0}, " +
145
- "Python library version: {1}.",
146
- pythonCommunicationVersion,
147
- pythonPackageVersion
148
- );
127
+ case StatusCode.Unavailable:
128
+ // This is the common case where there's no trainer to connect to.
129
+ break;
130
+ case StatusCode.DeadlineExceeded:
131
+ // We don't currently set a deadline for connection, but likely will in the future.
132
+ break;
133
+ default:
134
+ Debug.Log($"Unexpected gRPC exception when trying to initialize communication: {rpcException}");
135
+ break;
149
136
}
150
-
151
- throw new UnityAgentsException("ICommunicator.Initialize() failed.");
152
137
}
138
+ else
139
+ {
140
+ Debug.Log($"Unexpected exception when trying to initialize communication: {ex}");
141
+ }
142
+ initParametersOut = new UnityRLInitParameters();
143
+ return false;
153
144
}
154
- catch
155
- {
156
- var exceptionMessage = "The Communicator was unable to connect. Please make sure the External " +
157
- "process is ready to accept communication with Unity.";
158
145
159
- // Check for common error condition and add details to the exception message.
160
- var httpProxy = Environment.GetEnvironmentVariable("HTTP_PROXY");
161
- var httpsProxy = Environment.GetEnvironmentVariable("HTTPS_PROXY");
162
- if (httpProxy != null || httpsProxy != null)
146
+ var pythonPackageVersion = initializationInput.RlInitializationInput.PackageVersion;
147
+ var pythonCommunicationVersion = initializationInput.RlInitializationInput.CommunicationVersion;
148
+
149
+ TrainingAnalytics.SetTrainerInformation(pythonPackageVersion, pythonCommunicationVersion);
150
+
151
+ var communicationIsCompatible = CheckCommunicationVersionsAreCompatible(
152
+ initParameters.unityCommunicationVersion,
153
+ pythonCommunicationVersion
154
+ );
155
+
156
+ // Initialization succeeded part-way. The most likely cause is a mismatch between the communicator
157
+ // API strings, so log an explicit warning if that's the case.
158
+ if (initializationInput != null && input == null)
159
+ {
160
+ if (!communicationIsCompatible)
161
+ {
162
+ Debug.LogWarningFormat(
163
+ "Communication protocol between python ({0}) and Unity ({1}) have different " +
164
+ "versions which make them incompatible. Python library version: {2}.",
165
+ pythonCommunicationVersion, initParameters.unityCommunicationVersion,
166
+ pythonPackageVersion
167
+ );
168
+ }
169
+ else
163
170
{
164
- exceptionMessage += " Try removing HTTP_PROXY and HTTPS_PROXY from the" +
165
- "environment variables and try again.";
171
+ Debug.LogWarningFormat(
172
+ "Unknown communication error between Python. Python communication protocol: {0}, " +
173
+ "Python library version: {1}.",
174
+ pythonCommunicationVersion,
175
+ pythonPackageVersion
176
+ );
166
177
}
167
- throw new UnityAgentsException(exceptionMessage);
178
+
179
+ initParametersOut = new UnityRLInitParameters();
180
+ return false;
168
181
}
169
182
170
183
UpdateEnvironmentWithInput(input.RlInput);
171
- return initializationInput.RlInitializationInput.ToUnityRLInitParameters();
184
+ initParametersOut = initializationInput.RlInitializationInput.ToUnityRLInitParameters();
185
+ return true;
172
186
}
173
187
174
188
/// <summary>
@@ -197,8 +211,7 @@ void UpdateEnvironmentWithInput(UnityRLInputProto rlInput)
197
211
SendCommandEvent(rlInput.Command);
198
212
}
199
213
200
- UnityInputProto Initialize(UnityOutputProto unityOutput,
201
- out UnityInputProto unityInput)
214
+ UnityInputProto Initialize(UnityOutputProto unityOutput, out UnityInputProto unityInput)
202
215
{
203
216
#if UNITY_EDITOR || UNITY_STANDALONE_WIN || UNITY_STANDALONE_OSX || UNITY_STANDALONE_LINUX
204
217
m_IsOpen = true;
@@ -220,8 +233,7 @@ UnityInputProto Initialize(UnityOutputProto unityOutput,
220
233
}
221
234
return result.UnityInput;
222
235
#else
223
- throw new UnityAgentsException(
224
- "You cannot perform training on this platform.");
236
+ throw new UnityAgentsException("You cannot perform training on this platform.");
225
237
#endif
226
238
}
227
239
@@ -456,33 +468,34 @@ UnityInputProto Exchange(UnityOutputProto unityOutput)
456
468
QuitCommandReceived?.Invoke();
457
469
return message.UnityInput;
458
470
}
459
- catch (RpcException rpcException )
471
+ catch (Exception ex )
460
472
{
461
- // Log more verbose errors if they're something the user can possibly do something about.
462
- switch (rpcException.Status.StatusCode)
473
+ if (ex is RpcException rpcException)
474
+ {
475
+ // Log more verbose errors if they're something the user can possibly do something about.
476
+ switch (rpcException.Status.StatusCode)
477
+ {
478
+ case StatusCode.Unavailable:
479
+ // This can happen when python disconnects. Ignore it to avoid noisy logs.
480
+ break;
481
+ case StatusCode.ResourceExhausted:
482
+ // This happens is the message body is too large. There's no way to
483
+ // gracefully handle this, but at least we can show the message and the
484
+ // user can try to reduce the number of agents or observation sizes.
485
+ Debug.LogError($"GRPC Exception: {rpcException.Message}. Disconnecting from trainer.");
486
+ break;
487
+ default:
488
+ // Other unknown errors. Log at INFO level.
489
+ Debug.Log($"GRPC Exception: {rpcException.Message}. Disconnecting from trainer.");
490
+ break;
491
+ }
492
+ }
493
+ else
463
494
{
464
- case StatusCode.Unavailable:
465
- // This can happen when python disconnects. Ignore it to avoid noisy logs.
466
- break;
467
- case StatusCode.ResourceExhausted:
468
- // This happens is the message body is too large. There's no way to
469
- // gracefully handle this, but at least we can show the message and the
470
- // user can try to reduce the number of agents or observation sizes.
471
- Debug.LogError($"GRPC Exception: {rpcException.Message}. Disconnecting from trainer.");
472
- break;
473
- default:
474
- // Other unknown errors. Log at INFO level.
475
- Debug.Log($"GRPC Exception: {rpcException.Message}. Disconnecting from trainer.");
476
- break;
495
+ // Fall-through for other error types
496
+ Debug.LogError($"Communication Exception: {ex.Message}. Disconnecting from trainer.");
477
497
}
478
- m_IsOpen = false;
479
- QuitCommandReceived?.Invoke();
480
- return null;
481
- }
482
- catch (Exception ex)
483
- {
484
- // Fall-through for other error types
485
- Debug.LogError($"GRPC Exception: {ex.Message}. Disconnecting from trainer.");
498
+
486
499
m_IsOpen = false;
487
500
QuitCommandReceived?.Invoke();
488
501
return null;
0 commit comments