@@ -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