com.valectric.mooserunner 2.1.16 → 2.1.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -210,14 +210,17 @@ namespace MooseRunner.Internal.Tests
210
210
  /// Also demonstrates SessionRecorder usage: records the test, then asks Gemini to describe what happened.
211
211
  /// When Unity Recorder isn't installed every facade call throws InvalidOperationException with install
212
212
  /// instructions; the catches log the message so all three throw sites surface in the test output.
213
+ /// The Stop and Analyze calls run in a finally block so they fire even when the ghost-cat scenario
214
+ /// fails — important for demonstrating all three throw sites in a customer install.
213
215
  /// </summary>
214
216
  [Test]
215
217
  public async Task TestDying()
216
218
  {
217
- // SessionRecorder soft-dep: start a recording. Throws with install instructions if
218
- // com.unity.recorder isn't installed.
219
219
  SessionInfo recordingSession = null;
220
220
  string outputPath = Path.Combine(Application.dataPath, "../.mooserunner/Recordings/TestDying");
221
+
222
+ // SessionRecorder soft-dep: start a recording. Throws with install instructions if
223
+ // com.unity.recorder isn't installed.
221
224
  try
222
225
  {
223
226
  var cfg = new SessionRecordingConfig(Camera.main, outputPath);
@@ -229,92 +232,90 @@ namespace MooseRunner.Internal.Tests
229
232
  Debug.LogWarning("[SessionRecorder] StartRecordingAsync threw: " + ex.Message);
230
233
  }
231
234
 
232
- // Load the "Ghost_Cat" prefab from the Resources folder
233
- GameObject ghostCatPrefab = Resources.Load<GameObject>("Ghost_Cat");
234
- Assert.IsNotNull(ghostCatPrefab, "The Ghost_Cat prefab could not be found in the Resources folder.");
235
-
236
- // Spawn the "Ghost_Cat" prefab into the scene
237
- GameObject ghostCatInstance =
238
- Object.Instantiate(ghostCatPrefab, new Vector3(0f, 2f, 0f), Quaternion.identity);
239
- Assert.IsNotNull(ghostCatInstance, "Failed to instantiate the Ghost_Cat prefab.");
235
+ try
236
+ {
237
+ // Load the "Ghost_Cat" prefab from the Resources folder
238
+ GameObject ghostCatPrefab = Resources.Load<GameObject>("Ghost_Cat");
239
+ Assert.IsNotNull(ghostCatPrefab, "The Ghost_Cat prefab could not be found in the Resources folder.");
240
240
 
241
- // Get the Enemy component
242
- Enemy enemyComponent = ghostCatInstance.GetComponent<Enemy>();
243
- Assert.IsNotNull(enemyComponent, "The Ghost_Cat instance does not have an Enemy component.");
241
+ // Spawn the "Ghost_Cat" prefab into the scene
242
+ GameObject ghostCatInstance =
243
+ Object.Instantiate(ghostCatPrefab, new Vector3(0f, 2f, 0f), Quaternion.identity);
244
+ Assert.IsNotNull(ghostCatInstance, "Failed to instantiate the Ghost_Cat prefab.");
244
245
 
245
- // Create a box object
246
- GameObject box = GameObject.CreatePrimitive(PrimitiveType.Cube);
247
- box.transform.position =
248
- new Vector3(ghostCatInstance.transform.position.x, 0.5f,
249
- 0.5f); // Position the wall directly in front of the Ghost_Cat
246
+ // Get the Enemy component
247
+ Enemy enemyComponent = ghostCatInstance.GetComponent<Enemy>();
248
+ Assert.IsNotNull(enemyComponent, "The Ghost_Cat instance does not have an Enemy component.");
250
249
 
251
- // Add a Rigidbody and Collider component to ensure collision detection works
252
- box.AddComponent<BoxCollider>();
253
- Rigidbody wallRigidbody = box.AddComponent<Rigidbody>();
254
- wallRigidbody.isKinematic = true;
250
+ // Create a box object
251
+ GameObject box = GameObject.CreatePrimitive(PrimitiveType.Cube);
252
+ box.transform.position =
253
+ new Vector3(ghostCatInstance.transform.position.x, 0.5f,
254
+ 0.5f); // Position the wall directly in front of the Ghost_Cat
255
255
 
256
- // Create a red block simulating fire
257
- GameObject fire = GameObject.CreatePrimitive(PrimitiveType.Cube);
258
- fire.name = "Fire"; // Rename the block to "Fire"
259
- fire.transform.position =
260
- new Vector3(ghostCatInstance.transform.position.x, 0f, 2.5f); // Position the block appropriately
261
- fire.transform.localScale = new Vector3(1f, 1f, 3f); // Scale the box to 2 along the x-axis
256
+ // Add a Rigidbody and Collider component to ensure collision detection works
257
+ box.AddComponent<BoxCollider>();
258
+ Rigidbody wallRigidbody = box.AddComponent<Rigidbody>();
259
+ wallRigidbody.isKinematic = true;
262
260
 
263
- // Change the color to red
264
- fire.GetComponent<Renderer>().material.color = Color.red;
261
+ // Create a red block simulating fire
262
+ GameObject fire = GameObject.CreatePrimitive(PrimitiveType.Cube);
263
+ fire.name = "Fire"; // Rename the block to "Fire"
264
+ fire.transform.position =
265
+ new Vector3(ghostCatInstance.transform.position.x, 0f, 2.5f);
266
+ fire.transform.localScale = new Vector3(1f, 1f, 3f);
265
267
 
266
- // Add a Box Collider to detect collisions
267
- BoxCollider collider = fire.AddComponent<BoxCollider>();
268
- collider.isTrigger = true; // Set the collider to be a trigger
268
+ fire.GetComponent<Renderer>().material.color = Color.red;
269
269
 
270
- // Add a custom FireComponent to handle collision logic
271
- fire.AddComponent<FireComponent>();
270
+ BoxCollider collider = fire.AddComponent<BoxCollider>();
271
+ collider.isTrigger = true;
272
272
 
273
- // Start the Ghost_Cat moving towards the wall
274
- enemyComponent.moveForward = true;
273
+ fire.AddComponent<FireComponent>();
275
274
 
276
- // Wait for the next frame to begin the simulation
277
- await Task.Yield();
275
+ enemyComponent.moveForward = true;
278
276
 
279
- // Simulate falling for 7 seconds
280
- float initialY = ghostCatInstance.transform.position.y;
281
- await WaitForSecondsUnity(7f);
277
+ await Task.Yield();
282
278
 
283
- // Stop the character after simulation ends
284
- enemyComponent.moveForward = false;
279
+ float initialY = ghostCatInstance.transform.position.y;
280
+ await WaitForSecondsUnity(7f);
285
281
 
286
- // SessionRecorder soft-dep: stop recording. Throws the same install-instruction
287
- // message when Recorder isn't installed.
288
- try
289
- {
290
- SessionRecorderFacade.Instance.StopRecording();
291
- Debug.Log("[SessionRecorder] Stopped recording");
292
- }
293
- catch (InvalidOperationException ex)
294
- {
295
- Debug.LogWarning("[SessionRecorder] StopRecording threw: " + ex.Message);
296
- }
282
+ enemyComponent.moveForward = false;
297
283
 
298
- // SessionRecorder soft-dep: video analysis via Gemini. Throws the install-instruction
299
- // message when Recorder isn't installed (different from a Gemini-not-configured error
300
- // — that one only surfaces once we get past the Recorder gate).
301
- try
302
- {
303
- string sessionPath = recordingSession?.SessionPath ?? outputPath;
304
- var result = await SessionRecorderFacade.Instance.AnalyzeVideoSegmentAsync(
305
- sessionPath, 0.0, 5.0,
306
- "Did the Ghost_Cat catch fire and die?",
307
- CancellationToken.None);
308
- Debug.Log("[SessionRecorder] Gemini analysis: " + result.Summary);
284
+ Assert.IsTrue(ghostCatInstance == null || !ghostCatInstance.activeSelf,
285
+ "The Ghost_Cat was not destroyed or deactivated.");
309
286
  }
310
- catch (InvalidOperationException ex)
287
+ finally
311
288
  {
312
- Debug.LogWarning("[SessionRecorder] AnalyzeVideoSegmentAsync threw: " + ex.Message);
289
+ // SessionRecorder soft-dep: stop recording. Throws the same install-instruction
290
+ // message when Recorder isn't installed. In finally so it fires even when the
291
+ // scenario above failed (e.g. prefab/component resolution issues).
292
+ try
293
+ {
294
+ SessionRecorderFacade.Instance.StopRecording();
295
+ Debug.Log("[SessionRecorder] Stopped recording");
296
+ }
297
+ catch (InvalidOperationException ex)
298
+ {
299
+ Debug.LogWarning("[SessionRecorder] StopRecording threw: " + ex.Message);
300
+ }
301
+
302
+ // SessionRecorder soft-dep: video analysis via Gemini. Same install-instruction
303
+ // message when Recorder isn't installed (different from a Gemini-not-configured
304
+ // error — that one only surfaces once we get past the Recorder gate).
305
+ try
306
+ {
307
+ string sessionPath = recordingSession?.SessionPath ?? outputPath;
308
+ var result = await SessionRecorderFacade.Instance.AnalyzeVideoSegmentAsync(
309
+ sessionPath, 0.0, 5.0,
310
+ "Did the Ghost_Cat catch fire and die?",
311
+ CancellationToken.None);
312
+ Debug.Log("[SessionRecorder] Gemini analysis: " + result.Summary);
313
+ }
314
+ catch (InvalidOperationException ex)
315
+ {
316
+ Debug.LogWarning("[SessionRecorder] AnalyzeVideoSegmentAsync threw: " + ex.Message);
317
+ }
313
318
  }
314
-
315
- // Check if the entity is destroyed or marked as "dead"
316
- Assert.IsTrue(ghostCatInstance == null || !ghostCatInstance.activeSelf,
317
- "The Ghost_Cat was not destroyed or deactivated.");
318
319
  }
319
320
 
320
321
  /// <summary>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.valectric.mooserunner",
3
- "version": "2.1.16",
3
+ "version": "2.1.17",
4
4
  "displayName": "MooseRunner",
5
5
  "description": "MooseRunner boosts PlayMode testing with Hot Reload, MCP for AIs, timescale control, and Task support. It enables rapid iteration, auto test reruns, full documentation and dedicated support.",
6
6
  "unity": "6000.2",