Quellcode durchsuchen

Demo Statistics Component

Signed-off-by: Adam Dabrowski <[email protected]>
Adam Dabrowski vor 2 Jahren
Ursprung
Commit
95fc98ce7c

+ 56 - 1
Project/Assets/Importer/apple_kraken_5.prefab

@@ -2457,7 +2457,8 @@
                             "assetHint": "prefabs/apple_crate.spawnable"
                         },
                         "Capacity": 50,
-                        "CrateDropPoint": "Entity_[5494828217205]"
+                        "CrateDropPoint": "Entity_[5494828217205]",
+                        "UiEntity": "Entity_[5286907825968]"
                     }
                 },
                 "Component_[12724369969007930765]": {
@@ -3763,6 +3764,60 @@
                 }
             }
         },
+        "Entity_[5286907825968]": {
+            "Id": "Entity_[5286907825968]",
+            "Name": "Ui",
+            "Components": {
+                "Component_[10241251369859239566]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 10241251369859239566
+                },
+                "Component_[11465251640864354376]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 11465251640864354376
+                },
+                "Component_[12565340982288084460]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 12565340982288084460
+                },
+                "Component_[12663538255353574993]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 12663538255353574993
+                },
+                "Component_[15097666237341457527]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 15097666237341457527
+                },
+                "Component_[15799199674941686217]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 15799199674941686217,
+                    "m_template": {
+                        "$type": "UiCanvasAssetRefComponent",
+                        "CanvasAssetRef": {
+                            "AssetPath": "ui/gamecanvas.uicanvas"
+                        },
+                        "IsAutoLoad": true
+                    }
+                },
+                "Component_[18129706037953483051]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 18129706037953483051,
+                    "Parent Entity": "Entity_[126373983206044]"
+                },
+                "Component_[4946259882969052376]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 4946259882969052376
+                },
+                "Component_[5951762884545543629]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 5951762884545543629
+                },
+                "Component_[9445786852124677420]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 9445786852124677420
+                }
+            }
+        },
         "Entity_[5494828217205]": {
             "Id": "Entity_[5494828217205]",
             "Name": "CrateDrop",

+ 8 - 3
Project/Gem/Source/ApplePicker/ApplePickerComponent.cpp

@@ -8,6 +8,7 @@
 
 #include "ApplePickerComponent.h"
 #include "ApplePickingRequests.h"
+#include "DemoStatistics/DemoStatisticsNotifications.h"
 #include "FruitStorage/FruitStorageBus.h"
 #include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentBus.h>
 #include <AtomLyIntegration/CommonFeatures/Mesh/MeshComponentConstants.h>
@@ -201,12 +202,12 @@ namespace AppleKraken
                     ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
                     ->Attribute(AZ::Edit::Attributes::Category, "AppleKraken")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::EntityId,
+                        AZ::Edit::UIHandlers::Default,
                         &ApplePickerComponent::m_triggerServiceTopic,
                         "Trigger",
                         "ROS2 service name for gathering trigger")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::EntityId,
+                        AZ::Edit::UIHandlers::Default,
                         &ApplePickerComponent::m_cancelServiceTopic,
                         "Cancel",
                         "ROS2 service name to cancel ongoing gathering")
@@ -270,8 +271,9 @@ namespace AppleKraken
             AZ_Warning("ApplePicker", false, "Fruit storage entity not set, assuming same entity");
             m_fruitStorageEntityId = GetEntityId();
         }
-        Tags applePickingEventTags = { "automated_picking" };
+        Tags applePickingEventTags = { kPickingAutomatedEventTag };
         FruitStorageRequestsBus::Event(m_fruitStorageEntityId, &FruitStorageRequests::AddApple, applePickingEventTags);
+        DemoStatisticsNotificationBus::Broadcast(&DemoStatisticsNotifications::AddApple, applePickingEventTags);
         PickNextApple();
     }
 
@@ -285,6 +287,9 @@ namespace AppleKraken
         AZ_TracePrintf(
             "ApplePicker", "%s. Picking failed due to: %s\n", Internal::CurrentTaskString(m_currentAppleTasks).c_str(), reason.c_str());
         m_currentAppleTasks.pop();
+
+        Tags applePickingEventTags = { kPickingFailedEventTag, kPickingAutomatedEventTag };
+        DemoStatisticsNotificationBus::Broadcast(&DemoStatisticsNotifications::AddApple, applePickingEventTags);
         PickNextApple();
     }
 

+ 0 - 1
Project/Gem/Source/ApplePicker/ApplePickingNotifications.h

@@ -9,7 +9,6 @@
 
 #include "PickingStructs.h"
 #include <AzCore/EBus/EBus.h>
-#include <AzCore/RTTI/BehaviorContext.h>
 
 namespace AppleKraken
 {

+ 6 - 6
Project/Gem/Source/ApplePicker/KrakenEffectorComponent.cpp

@@ -69,7 +69,7 @@ namespace AppleKraken
         if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
         {
             serialize->Class<KrakenEffectorComponent, AZ::Component>()
-                ->Version(3)
+                ->Version(4)
                 ->Field("ReachEntity", &KrakenEffectorComponent::m_reachEntity)
                 ->Field("ManipulatorEntity", &KrakenEffectorComponent::m_manipulatorEntity)
                 ->Field("AppleProbe", &KrakenEffectorComponent::m_appleProbe)
@@ -83,24 +83,24 @@ namespace AppleKraken
                     ->Attribute(AZ::Edit::Attributes::Category, "AppleKraken")
                     ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
                     ->DataElement(
-                        AZ::Edit::UIHandlers::Default,
+                        AZ::Edit::UIHandlers::EntityId,
                         &KrakenEffectorComponent::m_reachEntity,
                         "Kraken Reach entity",
                         "Kraken entity with box shape to set reach area")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::Default,
+                        AZ::Edit::UIHandlers::EntityId,
                         &KrakenEffectorComponent::m_manipulatorEntity,
                         "Entity with manipulator",
                         "The entity that has a component handling events from ManipulatorRequestBus")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::Default, &KrakenEffectorComponent::m_appleProbe, "Entity to probe apples", "Sucking collider")
+                        AZ::Edit::UIHandlers::EntityId, &KrakenEffectorComponent::m_appleProbe, "Entity to probe apples", "Sucking collider")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::Default,
+                        AZ::Edit::UIHandlers::EntityId,
                         &KrakenEffectorComponent::m_rootEntityToFreeze,
                         "RootManipulatorFreeze",
                         "RootManipulatorFreeze to freeze during robot movement")
                     ->DataElement(
-                        AZ::Edit::UIHandlers::Default,
+                        AZ::Edit::UIHandlers::EntityId,
                         &KrakenEffectorComponent::m_baseLinkToKinematic,
                         "BaseLinkToKinematic",
                         "BaseLinkToKinematic during manipulator movement")

+ 20 - 0
Project/Gem/Source/DemoStatistics/AppleEvent.h

@@ -0,0 +1,20 @@
+/*
+* Copyright (c) Contributors to the Open 3D Engine Project.
+* For complete copyright and license terms please see the LICENSE at the root of this distribution.
+*
+* SPDX-License-Identifier: Apache-2.0 OR MIT
+*
+*/
+#pragma once
+
+#include <AzCore/std/containers/vector.h>
+#include <AzCore/std/string/string.h>
+
+namespace AppleKraken
+{
+   using Tags = AZStd::vector<AZStd::string>;
+   using AppleEvent = Tags;
+
+   const AZStd::string kPickingFailedEventTag = "failed";
+   const AZStd::string kPickingAutomatedEventTag = "automated";
+} // namespace AppleKraken

+ 113 - 0
Project/Gem/Source/DemoStatistics/DemoStatisticsComponent.cpp

@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+
+#include "DemoStatisticsComponent.h"
+#include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Serialization/EditContextConstants.inl>
+#include <AzCore/Serialization/SerializeContext.h>
+#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
+#include <LyShine/Bus/UiCanvasBus.h>
+#include <LyShine/Bus/UiTextBus.h>
+#include <LyShine/Bus/World/UiCanvasRefBus.h>
+
+namespace AppleKraken
+{
+    void DemoStatisticsComponent::Activate()
+    {
+        AZ::TickBus::Handler::BusConnect();
+        DemoStatisticsNotificationBus::Handler::BusConnect();
+        m_applesGathered = 0;
+        m_applesFailed = 0;
+    }
+
+    void DemoStatisticsComponent::Deactivate()
+    {
+        DemoStatisticsNotificationBus::Handler::BusDisconnect();
+        AZ::TickBus::Handler::BusDisconnect();
+    }
+
+    void DemoStatisticsComponent::Reflect(AZ::ReflectContext* context)
+    {
+        if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
+        {
+            serialize->Class<DemoStatisticsComponent, AZ::Component>()->Version(1)->Field(
+                "UiEntity", &DemoStatisticsComponent::m_uiEntity);
+
+            if (AZ::EditContext* ec = serialize->GetEditContext())
+            {
+                ec->Class<DemoStatisticsComponent>("Demo Statistics", "Demo statistics for picked apples")
+                    ->ClassElement(AZ::Edit::ClassElements::EditorData, "Handles counting of interesting events and their UI")
+                    ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
+                    ->Attribute(AZ::Edit::Attributes::Category, "AppleKraken")
+                    ->DataElement(
+                        AZ::Edit::UIHandlers::EntityId,
+                        &DemoStatisticsComponent::m_uiEntity,
+                        "Entity with Ui canvas reference ",
+                        "Element which will display the text of statistics");
+            }
+        }
+    }
+
+    void DemoStatisticsComponent::AddApple(const AppleEvent& appleEvent)
+    {
+        if (IsFailed(appleEvent))
+        {
+            m_applesFailed++;
+            return;
+        }
+
+        m_applesGathered++;
+    }
+
+    bool DemoStatisticsComponent::IsFailed(const Tags& tags)
+    {
+        return HasTag(tags, kPickingFailedEventTag);
+    }
+
+    // TODO Currently not used, but will be soon
+    bool DemoStatisticsComponent::IsAutomated(const Tags& tags)
+    {
+        return HasTag(tags, kPickingAutomatedEventTag);
+    }
+
+    bool DemoStatisticsComponent::HasTag(const AppleEvent& appleEvent, const AZStd::string& tag)
+    {
+        return AZStd::find(appleEvent.cbegin(), appleEvent.cend(), tag) != appleEvent.cend();
+    }
+
+    void DemoStatisticsComponent::DisplayNumberOfApples()
+    {
+        UpdateTextField(m_appleGatheredElementName, "Apples gathered: ", m_applesGathered);
+        UpdateTextField(m_appleFailedElementName, "Attempts failed:", m_applesFailed);
+    }
+
+    void DemoStatisticsComponent::UpdateTextField(const AZStd::string& fieldName, const AZStd::string& label, uint16_t counter)
+    {
+        AZ::EntityId uiCanvas;
+        EBUS_EVENT_ID_RESULT(uiCanvas, m_uiEntity, UiCanvasRefBus, GetCanvas);
+        if (!uiCanvas.IsValid())
+        {
+            AZ_Warning("DemoStatisticsComponent", false, "%s does not have a UiCanvasRef attached\n", m_uiEntity.ToString().c_str());
+            return;
+        }
+
+        AZ::EntityId uiTextEntity;
+        UiCanvasBus::EventResult(uiTextEntity, uiCanvas, &UiCanvasInterface::FindElementEntityIdByName, fieldName);
+        if (!uiTextEntity.IsValid())
+        {
+            AZ_Warning("DemoStatisticsComponent", false, "ui canvas doest not have a %s field\n", fieldName.c_str());
+            return;
+        }
+        UiTextBus::Event(uiTextEntity, &UiTextInterface::SetText, AZStd::string::format("%s %d", label.c_str(), counter));
+    }
+
+    void DemoStatisticsComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
+    {
+        DisplayNumberOfApples();
+    }
+} // namespace AppleKraken

+ 48 - 0
Project/Gem/Source/DemoStatistics/DemoStatisticsComponent.h

@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) Contributors to the Open 3D Engine Project.
+ * For complete copyright and license terms please see the LICENSE at the root of this distribution.
+ *
+ * SPDX-License-Identifier: Apache-2.0 OR MIT
+ *
+ */
+#pragma once
+
+#include "DemoStatisticsNotifications.h"
+#include <AzCore/Component/Component.h>
+#include <AzCore/Component/EntityId.h>
+#include <AzCore/Component/TickBus.h>
+
+namespace AppleKraken
+{
+    //! Component responsible for holding simulation statistics such as failed and picked apples, globally.
+    class DemoStatisticsComponent
+        : public AZ::Component
+        , private DemoStatisticsNotificationBus::Handler
+        , private AZ::TickBus::Handler
+    {
+    public:
+        AZ_COMPONENT(DemoStatisticsComponent, "{C421B635-8B7A-479A-8617-86F5F1ACC4AE}");
+
+        DemoStatisticsComponent() = default;
+        ~DemoStatisticsComponent() = default;
+        void Activate() override;
+        void Deactivate() override;
+        static void Reflect(AZ::ReflectContext* context);
+
+    private:
+        void DisplayNumberOfApples();
+        void AddApple(const AppleEvent& appleEvent) override;
+        void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
+
+        bool HasTag(const AppleEvent& appleEvent, const AZStd::string& tag);
+        bool IsFailed(const Tags& tags);
+        bool IsAutomated(const Tags& tags);
+
+        void UpdateTextField(const AZStd::string& fieldName, const AZStd::string& label, uint16_t counter);
+        const AZStd::string m_appleGatheredElementName = "ApplesGathered";
+        const AZStd::string m_appleFailedElementName = "ApplesFailed";
+        AZ::EntityId m_uiEntity;
+        uint16_t m_applesGathered = 0;
+        uint16_t m_applesFailed = 0;
+    };
+} // namespace AppleKraken

+ 28 - 0
Project/Gem/Source/DemoStatistics/DemoStatisticsNotifications.h

@@ -0,0 +1,28 @@
+/*
+* Copyright (c) Contributors to the Open 3D Engine Project.
+* For complete copyright and license terms please see the LICENSE at the root of this distribution.
+*
+* SPDX-License-Identifier: Apache-2.0 OR MIT
+*
+*/
+#pragma once
+
+#include "AppleEvent.h"
+#include <AzCore/EBus/EBus.h>
+
+namespace AppleKraken
+{
+   using Tags = AZStd::vector<AZStd::string>;
+   using ApplesGatheredByTag = AZStd::unordered_map<AZStd::string, uint32_t>;
+
+   //! Interface to notify about statistical events
+   class DemoStatisticsNotifications : public AZ::EBusTraits
+   {
+   public:
+       static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
+       virtual ~DemoStatisticsNotifications() = default;
+       virtual void AddApple(const AppleEvent& appleEvent) = 0;
+   };
+
+   using DemoStatisticsNotificationBus = AZ::EBus<DemoStatisticsNotifications>;
+} // namespace AppleKraken

+ 6 - 7
Project/Gem/Source/FruitStorage/FruitStorageBus.h

@@ -7,22 +7,21 @@
  */
 #pragma once
 
-#include <AzCore/Component/ComponentBus.h>
+#include "../DemoStatistics/AppleEvent.h"
+#include <AzCore/Component/EntityId.h>
 #include <AzCore/EBus/EBus.h>
-#include <AzCore/Math/Transform.h>
-#include <AzCore/RTTI/BehaviorContext.h>
+#include <AzCore/EBus/Event.h>
 
 namespace AppleKraken
 {
-    using Tags = AZStd::vector<AZStd::string>;
     using ApplesGatheredByTag = AZStd::unordered_map<AZStd::string, uint32_t>;
 
     //! Interface handing fruits storage requests
-    class FruitStorageRequests : public AZ::ComponentBus
+    class FruitStorageRequests : public AZ::EBusTraits
     {
     public:
-        AZ_RTTI(SpawnerRequests, "{129EAABF-706E-4DC1-B272-93EEACE3E893}");
-        static constexpr AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Multiple;
+        static constexpr AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::ById;
+        using BusIdType = AZ::EntityId;
 
         virtual ~FruitStorageRequests() = default;
 

+ 5 - 77
Project/Gem/Source/FruitStorage/FruitStorageComponent.cpp

@@ -9,42 +9,20 @@
 #include "FruitStorageComponent.h"
 #include "FruitStorageBus.h"
 #include <AzCore/Serialization/EditContext.h>
+#include <AzCore/Serialization/EditContextConstants.inl>
+#include <AzCore/Serialization/SerializeContext.h>
 #include <AzFramework/Components/TransformComponent.h>
 #include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
-#include <LyShine/Bus/UiCanvasBus.h>
-#include <LyShine/Bus/UiTextBus.h>
-#include <LyShine/Bus/World/UiCanvasRefBus.h>
 
 namespace AppleKraken
 {
-
-    FruitStorageComponent::FruitStorageComponent()
-    {
-
-        m_postSimulateHandler = AzPhysics::SystemEvents::OnPostsimulateEvent::Handler(
-        [this](float deltaTime)
-        {
-            AZ_Printf("FruitStorageComponent", "FruitStorageComponentClear\n");
-            AppleKraken::FruitStorageComponent::ResetCounter();
-            m_postSimulateHandler.Disconnect();
-        });
-    }
-
     void FruitStorageComponent::Activate()
     {
         FruitStorageRequestsBus::Handler::BusConnect(GetEntityId());
-        AZ::TickBus::Handler::BusConnect();
-        auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get();
-        if (physicsSystem)
-        {
-            physicsSystem->RegisterPostSimulateEvent(m_postSimulateHandler);
-        }
-
     }
 
     void FruitStorageComponent::Deactivate()
     {
-
         FruitStorageRequestsBus::Handler::BusDisconnect(GetEntityId());
     }
 
@@ -53,12 +31,10 @@ namespace AppleKraken
         if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
         {
             serialize->Class<FruitStorageComponent, AZ::Component>()
-                ->Version(2)
+                ->Version(3)
                 ->Field("Crate", &FruitStorageComponent::m_crateSpawnable)
                 ->Field("Capacity", &FruitStorageComponent::m_crateCapacity)
-                ->Field("CrateDropPoint", &FruitStorageComponent::m_crateDropPoint)
-                ->Field("UiEntity", &FruitStorageComponent::m_ui_entity);
-
+                ->Field("CrateDropPoint", &FruitStorageComponent::m_crateDropPoint);
 
             if (AZ::EditContext* ec = serialize->GetEditContext())
             {
@@ -72,13 +48,7 @@ namespace AppleKraken
                         AZ::Edit::UIHandlers::EntityId,
                         &FruitStorageComponent::m_crateDropPoint,
                         "Crate drop point",
-                        "Place this entity behind the robot")
-                    ->DataElement(
-                            AZ::Edit::UIHandlers::EntityId,
-                            &FruitStorageComponent::m_ui_entity,
-                            "Entity with Ui canvas reference ",
-                            "Entity with UI canvas, that contains text element named ");
-
+                        "Place this entity behind the robot");
             }
         }
     }
@@ -165,47 +135,5 @@ namespace AppleKraken
             SpawnCrate();
             m_applesInStorage = 0;
         }
-
-        m_allApplesGathered++;
-        displayNumberOfApples(m_allApplesGathered);
     }
-
-    void FruitStorageComponent::displayNumberOfApples(int num){
-        AZ_Printf("FruitStorageComponent",  "displayNumberOfApples %d \n", num);
-        AZ::EntityId ui_canvas;
-
-        EBUS_EVENT_ID_RESULT(ui_canvas, m_ui_entity, UiCanvasRefBus, GetCanvas);
-        if (!ui_canvas.IsValid())
-        {
-            AZ_Warning("FruitStorageComponent", false, "%s doest not have UiCanvasRef\n", m_ui_entity.ToString().c_str());
-            return;
-        }
-
-        AZ::EntityId ui_text_entity;
-        UiCanvasBus::EventResult(ui_text_entity,
-                                 ui_canvas,
-                                 &UiCanvasInterface::FindElementEntityIdByName,
-                                 kAppleGatheredElementName);
-        if (!ui_text_entity.IsValid())
-        {
-            AZ_Warning("FruitStorageComponent", false,  "ui canvas doest not have %s \n", kAppleGatheredElementName.c_str());
-            return;
-        }
-        AZStd::string t = "Apples gathered : " + AZStd::to_string(num);
-        UiTextBus::Event(ui_text_entity, &UiTextInterface::SetText, t);
-    }
-
-    void FruitStorageComponent::OnTick([[maybe_unused]] float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
-    {
-        displayNumberOfApples(m_allApplesGathered);
-        AZ::TickBus::Handler::BusDisconnect();
-    }
-
-    void FruitStorageComponent::ResetCounter(){
-        FruitStorageComponent::m_allApplesGathered.store(0);
-    }
-
-    const AZStd::string FruitStorageComponent::kAppleGatheredElementName{"AppleGatheredElement"};
-    AZStd::atomic_int32_t FruitStorageComponent::m_allApplesGathered {0};
-
 } // namespace AppleKraken

+ 2 - 13
Project/Gem/Source/FruitStorage/FruitStorageComponent.h

@@ -19,13 +19,10 @@ namespace AppleKraken
     class FruitStorageComponent
         : public AZ::Component
         , public FruitStorageRequestsBus::Handler
-        , public AZ::TickBus::Handler
     {
     public:
-        AZ_COMPONENT(FruitStorageComponent, "{9AC0B456-9C29-4EDD-AD25-6FAA57D253C5}", AZ::Component, FruitStorageRequestsBus::Handler);
-
-        // AZ::Component interface implementation.
-        FruitStorageComponent();
+        AZ_COMPONENT(FruitStorageComponent, "{9AC0B456-9C29-4EDD-AD25-6FAA57D253C5}", AZ::Component);
+        FruitStorageComponent() = default;
         ~FruitStorageComponent() = default;
         void Activate() override;
         void Deactivate() override;
@@ -35,23 +32,15 @@ namespace AppleKraken
         uint32_t GetCurrentStorageAppleCount() const override;
         void AddApple(const Tags& tags = {}) override;
 
-        static void ResetCounter();
-
     private:
         void SpawnCrate();
         void PreSpawn(AzFramework::EntitySpawnTicket::Id, AzFramework::SpawnableEntityContainerView);
-        void displayNumberOfApples(int num);
-        void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
         AZ::Data::Asset<AzFramework::Spawnable> m_crateSpawnable;
         AzFramework::EntitySpawnTicket m_crateTicket;
         AZ::EntityId m_crateDropPoint;
         uint32_t m_crateCapacity = 0;
         uint32_t m_applesGathered = 0;
         uint32_t m_applesInStorage = 0;
-        static AZStd::atomic_int32_t m_allApplesGathered;
         ApplesGatheredByTag m_tagsStored;
-        AZ::EntityId m_ui_entity;
-        const static AZStd::string kAppleGatheredElementName;
-        AzPhysics::SystemEvents::OnPostsimulateEvent ::Handler m_postSimulateHandler;
     };
 } // namespace AppleKraken

+ 3 - 1
Project/Gem/Source/ROSConDemoModule.cpp

@@ -9,6 +9,7 @@
 #include "ApplePicker/ApplePickerComponent.h"
 #include "ApplePicker/GatheringRowComponent.h"
 #include "ApplePicker/KrakenEffectorComponent.h"
+#include "DemoStatistics/DemoStatisticsComponent.h"
 #include "FruitStorage/FruitStorageComponent.h"
 #include "ROSConDemoSystemComponent.h"
 #include <AzCore/Memory/SystemAllocator.h>
@@ -31,7 +32,8 @@ namespace ROSConDemo
                   AppleKraken::ApplePickerComponent::CreateDescriptor(),
                   AppleKraken::GatheringRowComponent::CreateDescriptor(),
                   AppleKraken::KrakenEffectorComponent::CreateDescriptor(),
-                  AppleKraken::FruitStorageComponent::CreateDescriptor() });
+                  AppleKraken::FruitStorageComponent::CreateDescriptor(),
+                  AppleKraken::DemoStatisticsComponent::CreateDescriptor() });
         }
 
         AZ::ComponentTypeList GetRequiredSystemComponents() const override

+ 0 - 4
Project/Gem/Source/ROSConDemoSystemComponent.cpp

@@ -81,10 +81,6 @@ namespace ROSConDemo
         }
     }
 
-    void ROSConDemoSystemComponent::Init()
-    {
-    }
-
     void ROSConDemoSystemComponent::Activate()
     {   // TODO - the service should probably only be created in Game Mode
         ROSConDemoRequestBus::Handler::BusConnect();

+ 0 - 1
Project/Gem/Source/ROSConDemoSystemComponent.h

@@ -36,7 +36,6 @@ namespace ROSConDemo
         ~ROSConDemoSystemComponent();
 
     protected:
-        void Init() override;
         void Activate() override;
         void Deactivate() override;
 

+ 4 - 0
Project/Gem/roscondemo_files.cmake

@@ -13,6 +13,10 @@ set(FILES
         Source/ApplePicker/KrakenEffectorComponent.cpp
         Source/ApplePicker/KrakenEffectorComponent.h
         Source/ApplePicker/PickingStructs.h
+        Source/DemoStatistics/AppleEvent.h
+        Source/DemoStatistics/DemoStatisticsComponent.cpp
+        Source/DemoStatistics/DemoStatisticsComponent.h
+        Source/DemoStatistics/DemoStatisticsNotifications.h
         Source/FruitStorage/FruitStorageComponent.cpp
         Source/FruitStorage/FruitStorageComponent.h
         Source/FruitStorage/FruitStorageBus.h

+ 71 - 3
Project/Levels/playground/playground.prefab

@@ -25,7 +25,8 @@
                     "Entity_[1176639161715]",
                     "Instance_[12778335461144]/ContainerEntity",
                     "Instance_[5387454034805]/ContainerEntity",
-                    "Entity_[5326069303457]"
+                    "Entity_[5326069303457]",
+                    "Entity_[10454073709875]"
                 ]
             },
             "Component_[15230859088967841193]": {
@@ -61,6 +62,68 @@
         }
     },
     "Entities": {
+        "Entity_[10454073709875]": {
+            "Id": "Entity_[10454073709875]",
+            "Name": "DemoStatistics",
+            "Components": {
+                "Component_[10344265962619282103]": {
+                    "$type": "EditorEntityIconComponent",
+                    "Id": 10344265962619282103
+                },
+                "Component_[10791052972920696391]": {
+                    "$type": "{27F1E1A1-8D9D-4C3B-BD3A-AFB9762449C0} TransformComponent",
+                    "Id": 10791052972920696391,
+                    "Parent Entity": "Entity_[1146574390643]"
+                },
+                "Component_[11639396393250169885]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 11639396393250169885,
+                    "m_template": {
+                        "$type": "UiCanvasAssetRefComponent",
+                        "CanvasAssetRef": {
+                            "AssetPath": "ui/gamecanvas.uicanvas"
+                        },
+                        "IsAutoLoad": true
+                    }
+                },
+                "Component_[13085149962651906046]": {
+                    "$type": "EditorVisibilityComponent",
+                    "Id": 13085149962651906046
+                },
+                "Component_[14137431962977352887]": {
+                    "$type": "GenericComponentWrapper",
+                    "Id": 14137431962977352887,
+                    "m_template": {
+                        "$type": "DemoStatisticsComponent",
+                        "UiEntity": "Entity_[10454073709875]"
+                    }
+                },
+                "Component_[14695336353652957010]": {
+                    "$type": "EditorPendingCompositionComponent",
+                    "Id": 14695336353652957010
+                },
+                "Component_[17896215333811970161]": {
+                    "$type": "EditorLockComponent",
+                    "Id": 17896215333811970161
+                },
+                "Component_[18432948663577060977]": {
+                    "$type": "EditorInspectorComponent",
+                    "Id": 18432948663577060977
+                },
+                "Component_[2736042584132409731]": {
+                    "$type": "EditorDisabledCompositionComponent",
+                    "Id": 2736042584132409731
+                },
+                "Component_[3599028277973095726]": {
+                    "$type": "EditorOnlyEntityComponent",
+                    "Id": 3599028277973095726
+                },
+                "Component_[3934081295968843641]": {
+                    "$type": "EditorEntitySortComponent",
+                    "Id": 3934081295968843641
+                }
+            }
+        },
         "Entity_[1155164325235]": {
             "Id": "Entity_[1155164325235]",
             "Name": "Sun",
@@ -642,7 +705,7 @@
                     "Controller": {
                         "Configuration": {
                             "Field of View": 60.0,
-                            "EditorEntityId": 2161920439331080165
+                            "EditorEntityId": 5408993834409404554
                         }
                     }
                 },
@@ -765,12 +828,17 @@
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[16951455423041694634]/Transform Data/Translate/0",
-                    "value": 0.7298018932342529
+                    "value": -0.8331530094146729
                 },
                 {
                     "op": "replace",
                     "path": "/ContainerEntity/Components/Component_[16951455423041694634]/Transform Data/Translate/1",
                     "value": -0.1501479148864746
+                },
+                {
+                    "op": "replace",
+                    "path": "/Entities/Entity_[453802196716717]/Components/Component_[12122484710959107959]/Controller/Configuration/EditorEntityId",
+                    "value": 5742386901174006490
                 }
             ]
         }

+ 87 - 6
Project/Ui/GameCanvas.uicanvas

@@ -14,7 +14,7 @@
 					<Class name="EntityId" field="RootElement" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
 						<Class name="AZ::u64" field="id" value="10473912733319" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 					</Class>
-					<Class name="unsigned int" field="LastElement" value="5" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+					<Class name="unsigned int" field="LastElement" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
 					<Class name="Vector2" field="CanvasSize" value="1280.0000000 720.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
 					<Class name="bool" field="IsSnapEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 					<Class name="int" field="DrawOrder" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
@@ -116,6 +116,12 @@
 											</Class>
 											<Class name="AZ::u64" field="SortIndex" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 										</Class>
+										<Class name="ChildEntityIdOrderEntry" field="element" version="1" type="{D6F3CC55-6C7C-4D64-818F-FA3378EC8DA2}">
+											<Class name="EntityId" field="ChildEntityId" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+												<Class name="AZ::u64" field="id" value="5314711528492" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+											</Class>
+											<Class name="AZ::u64" field="SortIndex" value="1" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
 									</Class>
 								</Class>
 							</Class>
@@ -126,7 +132,7 @@
 							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
 								<Class name="AZ::u64" field="id" value="10491092602503" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 							</Class>
-							<Class name="AZStd::string" field="Name" value="AppleGatheredElement" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::string" field="Name" value="ApplesGathered" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
 								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
 									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
@@ -173,18 +179,93 @@
 									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
 										<Class name="AZ::u64" field="Id" value="232720424535605160" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
 									</Class>
-									<Class name="AZStd::string" field="Text" value="AppleGatheredElement" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="AZStd::string" field="Text" value="0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="Color" field="Color" value="1.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
+									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
+										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
+											<Class name="AZStd::string" field="AssetPath" value="fonts/default.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+										</Class>
+									</Class>
+									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="unsigned int" field="EffectIndex" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="int" field="TextHAlignment" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="CharacterSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="LineSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="int" field="OverflowMode" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="WrapTextSetting" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="ShrinkToFit" value="2" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="float" field="MinShrinkScale" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+								</Class>
+							</Class>
+							<Class name="bool" field="IsDependencyReady" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+							<Class name="bool" field="IsRuntimeActive" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+						</Class>
+						<Class name="AZ::Entity" field="element" version="2" type="{75651658-8663-478D-9090-2432DFCAFA44}">
+							<Class name="EntityId" field="Id" version="1" type="{6383F1D3-BB27-4E6B-A49A-6409B2059EAA}">
+								<Class name="AZ::u64" field="id" value="5314711528492" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+							</Class>
+							<Class name="AZStd::string" field="Name" value="ApplesFailed" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+							<Class name="AZStd::vector&lt;AZ::Component*, allocator&gt;" field="Components" type="{13D58FF9-1088-5C69-9A1F-C2A144B57B78}">
+								<Class name="EditorOnlyEntityComponent" field="element" type="{22A16F1D-6D49-422D-AAE9-91AE45B5D3E7}">
+									<Class name="EditorComponentBase" field="BaseClass1" version="1" type="{D5346BD4-7F20-444E-B370-327ACD03D4A0}">
+										<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+											<Class name="AZ::u64" field="Id" value="5025600029261391577" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+										</Class>
+									</Class>
+									<Class name="bool" field="IsEditorOnly" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+								</Class>
+								<Class name="UiTransform2dComponent" field="element" version="3" type="{2751A5A5-3291-4A4D-9FC0-9CB0EB8D1DE6}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="6280594580484317939" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="Anchors" field="Anchors" type="{65D4346C-FB16-4CB0-9BDC-1185B122C4A9}">
+										<Class name="float" field="left" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="0.0500000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="0.1500000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Offsets" field="Offsets" type="{F681BA9D-245C-4630-B20E-05DD752FAD57}">
+										<Class name="float" field="left" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="top" value="-0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="right" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+										<Class name="float" field="bottom" value="100.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									</Class>
+									<Class name="Vector2" field="Pivot" value="0.5000000 0.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="float" field="Rotation" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="Vector2" field="Scale" value="1.0000000 1.0000000" type="{3D80F623-C85C-4741-90D0-E4E66164E6BF}"/>
+									<Class name="int" field="ScaleToDevice" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+								</Class>
+								<Class name="UiElementComponent" field="element" version="3" type="{4A97D63E-CE7A-45B6-AAE4-102DB4334688}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="10315192711004539137" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="unsigned int" field="Id" value="6" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
+									<Class name="bool" field="IsEnabled" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsVisibleInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectableInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsSelectedInEditor" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="bool" field="IsExpandedInEditor" value="true" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
+									<Class name="AZStd::vector&lt;ChildEntityIdOrderEntry, allocator&gt;" field="ChildEntityIdOrder" type="{0DE523D9-AEAE-5FC4-9D40-967A2E2B8A62}"/>
+								</Class>
+								<Class name="UiTextComponent" field="element" version="9" type="{5B3FB2A7-5DC4-4033-A970-001CEC85B6C4}">
+									<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
+										<Class name="AZ::u64" field="Id" value="232720424535605160" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
+									</Class>
+									<Class name="AZStd::string" field="Text" value="0" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 									<Class name="bool" field="MarkupEnabled" value="false" type="{A0CA880C-AFE4-43CB-926C-59AC48496112}"/>
 									<Class name="Color" field="Color" value="1.0000000 0.0000000 0.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
 									<Class name="float" field="Alpha" value="1.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="SimpleAssetReference&lt;FontAsset&gt;" field="FontFileName" version="1" type="{4953F80A-F59C-5F38-9E84-AFEB8F438CC4}">
 										<Class name="SimpleAssetReferenceBase" field="BaseClass1" version="1" type="{E16CA6C5-5C78-4AD9-8E9B-F8C1FB4D1DB8}">
-											<Class name="AZStd::string" field="AssetPath" value="default-ui" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
+											<Class name="AZStd::string" field="AssetPath" value="fonts/default.font" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
 										</Class>
 									</Class>
-									<Class name="float" field="FontSize" value="64.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
+									<Class name="float" field="FontSize" value="32.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="unsigned int" field="EffectIndex" value="1" type="{43DA906B-7DEF-4CA8-9790-854106D3F983}"/>
-									<Class name="int" field="TextHAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
+									<Class name="int" field="TextHAlignment" value="0" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 									<Class name="int" field="TextVAlignment" value="1" type="{72039442-EB38-4D42-A1AD-CB68F7E0EEF6}"/>
 									<Class name="float" field="CharacterSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
 									<Class name="float" field="LineSpacing" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>