public IEnumerator ObjectInRangeCondition()
        {
            // Given a training with ObjectInRangeCondition,
            TrainingSceneObject testObjectToo         = TestingUtils.CreateSceneObject("TestObjectToo");
            TransformInRangeDetectorProperty detector = testObjectToo.gameObject.AddComponent <TransformInRangeDetectorProperty>();
            TrainingSceneObject testObject            = TestingUtils.CreateSceneObject("TestObject");

            ICourse training1 = new LinearTrainingBuilder("Training")
                                .AddChapter(new LinearChapterBuilder("Chapter")
                                            .AddStep(new BasicStepBuilder("Step")
                                                     .AddCondition(new ObjectInRangeCondition(testObject, detector, 1.5f))))
                                .Build();

            // When we serialize and deserialize it
            ICourse training2 = Serializer.CourseFromByteArray(Serializer.CourseToByteArray(training1));

            // Then that condition's target, detector and range should stay unchanged.
            ObjectInRangeCondition condition1 = training1.Data.FirstChapter.Data.FirstStep.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as ObjectInRangeCondition;
            ObjectInRangeCondition condition2 = training2.Data.FirstChapter.Data.FirstStep.Data.Transitions.Data.Transitions.First().Data.Conditions.First() as ObjectInRangeCondition;

            Assert.IsNotNull(condition1);
            Assert.IsNotNull(condition2);
            Assert.AreEqual(condition1.Data.Range, condition2.Data.Range);
            Assert.AreEqual(condition1.Data.Target.Value, condition2.Data.Target.Value);
            Assert.AreEqual(condition1.Data.DistanceDetector.Value, condition2.Data.DistanceDetector.Value);

            // Cleanup
            TestingUtils.DestroySceneObject(testObjectToo);
            TestingUtils.DestroySceneObject(testObject);

            return(null);
        }
        public IEnumerator DontCompleteWhenWrongObjectEntersRange()
        {
            // In addition to setup phase, also setup an additional object
            GameObject wrongObj = new GameObject("Wrong Object");

            wrongObj.transform.position = PositionFarFromTarget;
            TrainingSceneObject wrongTrainingSceneObject = wrongObj.AddComponent <TrainingSceneObject>();

            // Activate range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            // Move wrong object to the target position
            wrongTrainingSceneObject.transform.position = TargetPositionObject.transform.position;

            float startTime = Time.time;

            while (Time.time < startTime + 0.1f)
            {
                yield return(null);

                condition.Update();
            }

            // Assert that condition is not completed
            UnityEngine.Assertions.Assert.IsFalse(condition.IsCompleted, "TargetInRangeCondition should not be completed!");
        }
        public IEnumerator CompleteWhenTargetObjectIsInsideRange()
        {
            // Activate in range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            // Move tracked object to the target position
            TrackedObject.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget;

            while (condition.IsCompleted == false)
            {
                yield return(null);

                condition.Update();
            }

            // Assert that condition is now completed
            UnityEngine.Assertions.Assert.IsTrue(condition.IsCompleted, "TargetInRangeCondition should be completed!");
        }
        public IEnumerator NotCompletedTest()
        {
            // Activate range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            condition.LifeCycle.Activate();
            yield return(null);

            // Assert that condition is not completed
            UnityEngine.Assertions.Assert.IsFalse(condition.IsCompleted, "TargetInRangeCondition should not be completed!");
        }
        public IEnumerator DontCompleteWhenTargetObjectLeavesRangeEarly()
        {
            // Set the target duration
            const float targetDuration = 0.1f;

            // Activate range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5, targetDuration);

            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            // Move tracked object to the target position
            TrackedObject.transform.position = TargetPositionObject.transform.position;

            float startTime = Time.time;

            while (Time.time < startTime + 0.3f * targetDuration)
            {
                yield return(null);

                condition.Update();
            }

            // Move tracked object away from target position before condition is completed
            TrackedObject.transform.position = PositionFarFromTarget;

            startTime = Time.time;
            while (Time.time < startTime + 0.8f * targetDuration)
            {
                yield return(null);

                condition.Update();
            }

            // Assert that condition is not completed
            UnityEngine.Assertions.Assert.IsFalse(condition.IsCompleted, "TargetInRangeCondition should not be completed!");
        }
        public IEnumerator AutoCompleteActive()
        {
            // Given an object in range condition,
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            // When you activate and autocomplete it,
            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            condition.Autocomplete();

            // Then the condition is complete and the object is moved
            Assert.AreEqual(Stage.Active, condition.LifeCycle.Stage);
            Assert.IsTrue(condition.IsCompleted);
            Assert.IsTrue(TrackedTrainingSceneObject.GameObject.transform.position == TargetTrainingSceneObject.GameObject.transform.position);
        }
        public IEnumerator CompleteWhenTargetObjectIsInsideRangeWithDuration()
        {
            // Set the target duration
            const float targetDuration = 0.1f;

            // Activate in range condition
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5, targetDuration);

            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            // Move tracked object to the target position
            TrackedObject.transform.position = TargetPositionObject.transform.position - PositionOffsetNearTarget;

            yield return(null);

            condition.Update();

            float startTime = Time.time;

            while (condition.IsCompleted == false)
            {
                yield return(null);

                condition.Update();
            }

            float duration = Time.time - startTime;

            // Assert that condition has been completed after the specified duration
            Assert.AreEqual(targetDuration, duration, 0.05f);
            UnityEngine.Assertions.Assert.IsTrue(condition.IsCompleted, "TargetInRangeCondition should be completed!");
        }
        public IEnumerator FastForwardDoesNotCompleteCondition()
        {
            // Given an object in range condition,
            ObjectInRangeCondition condition = new ObjectInRangeCondition(TrackedTrainingSceneObject, TargetTrainingSceneObject.GetProperty <TransformInRangeDetectorProperty>(), 5);

            // When you activate it,
            condition.LifeCycle.Activate();

            while (condition.LifeCycle.Stage != Stage.Active)
            {
                yield return(null);

                condition.Update();
            }

            // When you fast-forward it
            condition.LifeCycle.MarkToFastForward();

            // Then nothing happens.
            Assert.AreEqual(Stage.Active, condition.LifeCycle.Stage);
            Assert.IsFalse(condition.IsCompleted);
            Assert.IsFalse(TrackedTrainingSceneObject.GameObject.transform.position == TargetTrainingSceneObject.GameObject.transform.position);
        }