com.valectric.mooserunner 2.1.15 → 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.
@@ -6,9 +6,12 @@
6
6
  "MooseRunner.Demo.Support",
7
7
  "UniTask",
8
8
  "MooseRunner.helper",
9
+ "MooseRunner.Editor",
9
10
  "MooseRunner.Runtime"
10
11
  ],
11
- "includePlatforms": [],
12
+ "includePlatforms": [
13
+ "Editor"
14
+ ],
12
15
  "excludePlatforms": [],
13
16
  "allowUnsafeCode": false,
14
17
  "precompiledReferences": [
@@ -5,6 +5,9 @@ using System.Collections;
5
5
  using Object = UnityEngine.Object;
6
6
  using MooseRunner.Multiplaytest;
7
7
  using MooseRunner.helper;
8
+ using MooseRunner.SessionRecorder;
9
+ using System.IO;
10
+ using System.Threading;
8
11
  using System.Threading.Tasks;
9
12
 
10
13
  namespace MooseRunner.Internal.Tests
@@ -204,67 +207,115 @@ namespace MooseRunner.Internal.Tests
204
207
 
205
208
  /// <summary>
206
209
  /// Tests the "Dying" mechanic, ensuring the entity is destroyed or marked dead when health reaches zero.
210
+ /// Also demonstrates SessionRecorder usage: records the test, then asks Gemini to describe what happened.
211
+ /// When Unity Recorder isn't installed every facade call throws InvalidOperationException with install
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.
207
215
  /// </summary>
208
216
  [Test]
209
217
  public async Task TestDying()
210
218
  {
211
- // Load the "Ghost_Cat" prefab from the Resources folder
212
- GameObject ghostCatPrefab = Resources.Load<GameObject>("Ghost_Cat");
213
- Assert.IsNotNull(ghostCatPrefab, "The Ghost_Cat prefab could not be found in the Resources folder.");
219
+ SessionInfo recordingSession = null;
220
+ string outputPath = Path.Combine(Application.dataPath, "../.mooserunner/Recordings/TestDying");
214
221
 
215
- // Spawn the "Ghost_Cat" prefab into the scene
216
- GameObject ghostCatInstance =
217
- Object.Instantiate(ghostCatPrefab, new Vector3(0f, 2f, 0f), Quaternion.identity);
218
- Assert.IsNotNull(ghostCatInstance, "Failed to instantiate the Ghost_Cat prefab.");
222
+ // SessionRecorder soft-dep: start a recording. Throws with install instructions if
223
+ // com.unity.recorder isn't installed.
224
+ try
225
+ {
226
+ var cfg = new SessionRecordingConfig(Camera.main, outputPath);
227
+ recordingSession = await SessionRecorderFacade.Instance.StartRecordingAsync(cfg, CancellationToken.None);
228
+ Debug.Log("[SessionRecorder] Started recording: " + recordingSession.SessionPath);
229
+ }
230
+ catch (InvalidOperationException ex)
231
+ {
232
+ Debug.LogWarning("[SessionRecorder] StartRecordingAsync threw: " + ex.Message);
233
+ }
219
234
 
220
- // Get the Enemy component
221
- Enemy enemyComponent = ghostCatInstance.GetComponent<Enemy>();
222
- Assert.IsNotNull(enemyComponent, "The Ghost_Cat instance does not have an Enemy component.");
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.");
223
240
 
224
- // Create a box object
225
- GameObject box = GameObject.CreatePrimitive(PrimitiveType.Cube);
226
- box.transform.position =
227
- new Vector3(ghostCatInstance.transform.position.x, 0.5f,
228
- 0.5f); // Position the wall directly in front of the Ghost_Cat
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.");
229
245
 
230
- // Add a Rigidbody and Collider component to ensure collision detection works
231
- box.AddComponent<BoxCollider>();
232
- Rigidbody wallRigidbody = box.AddComponent<Rigidbody>();
233
- wallRigidbody.isKinematic = true;
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.");
234
249
 
235
- // Create a red block simulating fire
236
- GameObject fire = GameObject.CreatePrimitive(PrimitiveType.Cube);
237
- fire.name = "Fire"; // Rename the block to "Fire"
238
- fire.transform.position =
239
- new Vector3(ghostCatInstance.transform.position.x, 0f, 2.5f); // Position the block appropriately
240
- fire.transform.localScale = new Vector3(1f, 1f, 3f); // Scale the box to 2 along the x-axis
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
241
255
 
242
- // Change the color to red
243
- fire.GetComponent<Renderer>().material.color = Color.red;
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;
244
260
 
245
- // Add a Box Collider to detect collisions
246
- BoxCollider collider = fire.AddComponent<BoxCollider>();
247
- collider.isTrigger = true; // Set the collider to be a trigger
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);
248
267
 
249
- // Add a custom FireComponent to handle collision logic
250
- fire.AddComponent<FireComponent>();
268
+ fire.GetComponent<Renderer>().material.color = Color.red;
251
269
 
252
- // Start the Ghost_Cat moving towards the wall
253
- enemyComponent.moveForward = true;
270
+ BoxCollider collider = fire.AddComponent<BoxCollider>();
271
+ collider.isTrigger = true;
254
272
 
255
- // Wait for the next frame to begin the simulation
256
- await Task.Yield();
273
+ fire.AddComponent<FireComponent>();
257
274
 
258
- // Simulate falling for 7 seconds
259
- float initialY = ghostCatInstance.transform.position.y;
260
- await WaitForSecondsUnity(7f);
275
+ enemyComponent.moveForward = true;
261
276
 
262
- // Stop the character after simulation ends
263
- enemyComponent.moveForward = false;
277
+ await Task.Yield();
264
278
 
265
- // Check if the entity is destroyed or marked as "dead"
266
- Assert.IsTrue(ghostCatInstance == null || !ghostCatInstance.activeSelf,
267
- "The Ghost_Cat was not destroyed or deactivated.");
279
+ float initialY = ghostCatInstance.transform.position.y;
280
+ await WaitForSecondsUnity(7f);
281
+
282
+ enemyComponent.moveForward = false;
283
+
284
+ Assert.IsTrue(ghostCatInstance == null || !ghostCatInstance.activeSelf,
285
+ "The Ghost_Cat was not destroyed or deactivated.");
286
+ }
287
+ finally
288
+ {
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
+ }
318
+ }
268
319
  }
269
320
 
270
321
  /// <summary>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "com.valectric.mooserunner",
3
- "version": "2.1.15",
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",