protected override void OnUpdate()
        {
            float deltaTime = Time.DeltaTime;

            Entity playerEntity = this.playerQuery.GetSingletonEntity();
            PlayerBodyAnchorComponent playerBodyAnchorComponent = this.EntityManager.GetComponentData <PlayerBodyAnchorComponent>(playerEntity);

            this.origin      = playerBodyAnchorComponent.RightHandAnchorPosition.Value;
            this.destination = playerBodyAnchorComponent.ShieldBlockDestinationAnchorPosition.Value;

            this.Entities.WithAll <CurrentlyAnimating>().WithAll <ShieldEquippedTag>().ForEach((ref Translation position, ref ItemInfo itemInfo) =>
            {
                if (this.currentDistanceInterpolator <= 1.0f)
                {
                    position.Value = math.lerp(this.origin, this.destination, this.currentDistanceInterpolator);

                    this.currentDistanceInterpolator += deltaTime * itemInfo.Speed;
                }
                else
                {
                    position.Value = this.destination;
                }
            });

            //Clean up when no animation (end animation)
            this.Entities.WithNone <CurrentlyAnimating>().WithAll <ShieldEquippedTag>().ForEach((ref Translation position) =>
            {
                position.Value = this.origin;
                this.currentDistanceInterpolator = 0f;
            });
        }
        protected override void OnUpdate()
        {
            float deltaTime = Time.DeltaTime;

            Entity   playerEntity   = this.playerQuery.GetSingletonEntity();
            Rotation playerRotation = this.EntityManager.GetComponentData <Rotation>(playerEntity);
            PlayerBodyAnchorComponent playerBodyAnchorComponent = this.EntityManager.GetComponentData <PlayerBodyAnchorComponent>(playerEntity);

            this.Entities.WithAll <CurrentlyAnimating>().WithAll <WeaponEquippedTag>().ForEach((Entity weapon, ref Translation position, ref Rotation rotation, ref ItemInfo itemInfo) =>
            {
                switch (itemInfo.PreservedWeaponAttackType)
                {
                case WeaponAttackType.Melee:
                    //Swap destination and origin with even/odd cyclecounter comparison -> swaps everytime when we increment cycleCounter
                    if (this.attackCycleCounter % 2 == 0)
                    {
                        this.originPosition      = playerBodyAnchorComponent.LeftHandAnchorPosition.Value;
                        this.destinationPosition = playerBodyAnchorComponent.WeaponAttackDestinationPosition.Value;
                    }
                    else
                    {
                        this.originPosition      = playerBodyAnchorComponent.WeaponAttackDestinationPosition.Value;
                        this.destinationPosition = playerBodyAnchorComponent.LeftHandAnchorPosition.Value;
                    }

                    position.Value            = math.lerp(this.originPosition, this.destinationPosition, this.currentInterpolator);
                    this.currentInterpolator += deltaTime * itemInfo.Speed;
                    if (this.currentInterpolator >= 1.0f)
                    {
                        this.currentInterpolator = 0f;
                        ++this.attackCycleCounter;

                        if (this.attackCycleCounter >= WeaponAnimationSystem.MeleeAttackCycles)
                        {
                            this.PostUpdateCommands.RemoveComponent <CurrentlyAnimating>(weapon);
                            this.attackCycleCounter = 0;
                        }
                    }
                    break;

                case WeaponAttackType.Ranged:
                    if (this.currentRangedAttackTimeAccumulator >= WeaponAnimationSystem.RangedAttackInterval)
                    {
                        //Get arrow mesh and shoot it in parabolic trajectory
                        this.PostUpdateCommands.CreateEntity(this.EntityManager.CreateRangedAttackAnimationArchetype());

                        this.PostUpdateCommands.SetComponent <Translation>(arrowEntity, new Translation {
                            Value = position.Value
                        });
                        this.PostUpdateCommands.SetComponent <Rotation>(arrowEntity, new Rotation {
                            Value = rotation.Value
                        });

                        this.PostUpdateCommands.SetComponent <NonUniformScale>(arrowEntity, new NonUniformScale {
                            Value = new float3(itemInfo.Range.x, itemInfo.Range.y, itemInfo.Range.z)
                        });

                        this.PostUpdateCommands.SetComponent <PhysicsVelocity>(arrowEntity, new PhysicsVelocity
                        {
                            Linear = new float3(itemInfo.Speed, 0, itemInfo.Speed)
                        });

                        RenderMesh renderMesh = new RenderMesh
                        {
                            mesh     = MeshFactory.Instance.GetOrCreateArrowMesh(),
                            material = WeaponAnimationMaterialFactory.Instance.GetOrCreateWeaponAnimationMaterial(WeaponAnimationMaterialIndex.RangedAttackMaterial)
                        };

                        this.PostUpdateCommands.SetSharedComponent <RenderMesh>(arrowEntity, renderMesh);

                        this.PostUpdateCommands.SetComponent <PhysicsCollider>(arrowEntity, new PhysicsCollider
                        {
                            Value = BoxCollider.Create
                                    (
                                CollisionGeomeotrySingleton.Instance.CreateOrGetBoxGeometry(renderMesh.mesh.bounds.size),
                                CollisionFilterSingleton.Instance.BelongsToWeaponFilter
                                    )
                        });

                        this.PostUpdateCommands.RemoveComponent <CurrentlyAnimating>(weapon);

                        this.currentRangedAttackTimeAccumulator = 0f;
                    }
                    else
                    {
                        this.currentRangedAttackTimeAccumulator += deltaTime;
                    }
                    break;

                //TODO: Properly implement rotation and attack magic weapon
                case WeaponAttackType.Magic:
                    //Swap destination and origin with even/odd cyclecounter comparison -> swaps everytime when we increment cycleCounter
                    //Rotate down 90 degrees starting at player rotation (hence multiplying), then rotate back
                    if (this.attackCycleCounter % 2 == 0)
                    {
                        this.destinationRotation  = math.mul(quaternion.RotateX(90), playerRotation.Value);
                        this.magicAnimationEntity = Entity.Null;
                    }
                    else
                    {
                        this.destinationRotation = math.mul(quaternion.identity, playerRotation.Value);

                        //Start magic attack animation (mesh "shooting" out of magic weapon), start it once, because magicAnimationEntity can either be null or not (initialize once, later on set to null again)
                        if (this.magicAnimationEntity == Entity.Null)
                        {
                            this.magicAnimationEntity = this.PostUpdateCommands.CreateEntity(this.EntityManager.CreateMagicAttackAnimationArchetype());

                            this.PostUpdateCommands.SetComponent <Translation>(magicAnimationEntity, new Translation {
                                Value = position.Value
                            });
                            this.PostUpdateCommands.SetComponent <Rotation>(magicAnimationEntity, new Rotation {
                                Value = rotation.Value
                            });

                            this.PostUpdateCommands.SetComponent <NonUniformScale>(magicAnimationEntity, new NonUniformScale {
                                Value = new float3(itemInfo.Range.x, itemInfo.Range.y, itemInfo.Range.z)
                            });

                            this.PostUpdateCommands.SetComponent <PhysicsCollider>(magicAnimationEntity, new PhysicsCollider
                            {
                                Value = BoxCollider.Create
                                        (
                                    CollisionGeomeotrySingleton.Instance.CreateOrGetBoxGeometry(itemInfo.Range),
                                    CollisionFilterSingleton.Instance.BelongsToWeaponFilter
                                        )
                            });

                            this.PostUpdateCommands.SetSharedComponent <RenderMesh>(magicAnimationEntity, new RenderMesh
                            {
                                mesh     = MeshFactory.Instance.GetOrCreateCube(itemInfo.Range.x, itemInfo.Range.y, itemInfo.Range.z),
                                material = WeaponAnimationMaterialFactory.Instance.GetOrCreateWeaponAnimationMaterial(WeaponAnimationMaterialIndex.MagicAttackMaterial)
                            });
                        }
                    }

                    rotation.Value = math.slerp(rotation.Value, this.destinationRotation, this.currentInterpolator);

                    this.currentInterpolator += deltaTime * itemInfo.Speed;

                    if (this.currentInterpolator >= 1.0f)
                    {
                        this.currentInterpolator = 0f;
                        ++this.attackCycleCounter;

                        if (this.attackCycleCounter >= WeaponAnimationSystem.MagicAttackCycles)
                        {
                            this.PostUpdateCommands.RemoveComponent <CurrentlyAnimating>(weapon);

                            this.attackCycleCounter = 0;

                            if (this.magicAnimationEntity != Entity.Null)
                            {
                                this.PostUpdateCommands.AddComponent <DeletionTag>(magicAnimationEntity);
                                this.magicAnimationEntity = Entity.Null;
                            }
                        }
                    }
                    break;
                }
            });
        }
        protected override void OnUpdate()
        {
            //Prevent this from being null when scene is loaded from another scene (Something about the lifecycle of ECS not behaving well with normal gameobject instantiating -> i can not always guarantee that oncreate receives the gameobject)
            if (this.hudInjectorProxy == null)
            {
                this.hudInjectorProxy = UnityEngine.Object.FindObjectOfType <HUDInjectorProxy>();
            }

            if (this.itemCatalog == null)
            {
                this.itemCatalog = UnityEngine.Object.FindObjectOfType <ItemCatalog>();
            }

            //Assumes there is exactly 1 player
            Entity playerEntity = this.playerQuery.GetSingletonEntity();
            PlayerBodyAnchorComponent playerBodyAnchorComponent = this.EntityManager.GetComponentData <PlayerBodyAnchorComponent>(playerEntity);

            //Are there unequipped weapons in weapon slot? If so equip them
            //Can not do FirstOrDefault and then check for null becaue ItemSlotDTO is a struct -> Have to count them first
            if (this.hudInjectorProxy.WeaponSlotCollectionDTO.ItemSlotDTOs.Count(weapon => weapon.HasItem) > 0)
            {
                if (this.hudInjectorProxy.WeaponSlotCollectionDTO.ItemSlotDTOs.Count(weapon => !weapon.IsEquippedToPlayer) > 0)
                {
                    ItemSlotDTO weaponSlot   = this.hudInjectorProxy.WeaponSlotCollectionDTO.ItemSlotDTOs.First(weapon => weapon.HasItem && !weapon.IsEquippedToPlayer);
                    Entity      weaponEntity = this.EntityManager.CreateEntity(this.EntityManager.CreateEquippedWeaponArchetype());

                    ItemDTO weaponItem = this.itemCatalog.PremadeWeapons.Where(weapon => weapon.ItemInfo.PreservedWeaponType == weaponSlot.OriginalInventoryItem.ItemInfo.PreservedWeaponType).First();

                    //Weapon is always placed in left hand
                    SetComponentDataForEquippableEntity(this.EntityManager, weaponEntity, in weaponItem, in playerBodyAnchorComponent.LeftHandAnchorPosition);

                    weaponSlot.IsEquippedToPlayer = true;

                    //We previously took the first element so element 0 is also the first element
                    this.hudInjectorProxy.WeaponSlotCollectionDTO.ItemSlotDTOs[0] = weaponSlot;
                }
            }
            //Unequip
            else
            {
                NativeArray <Entity> equippedWeapons = this.GetEntityQuery(this.EntityManager.GetEquippedWeaponIdentifier()).ToEntityArray(Allocator.TempJob);

                for (int i = 0; i < equippedWeapons.Length; ++i)
                {
                    this.PostUpdateCommands.AddComponent <DeletionTag>(equippedWeapons[i]);
                }

                equippedWeapons.Dispose();
            }

            //Are there unequipped shields in shield slot? If so equip them
            if (this.hudInjectorProxy.ShieldSlotCollectionDTO.ItemSlotDTOs.Count(shield => shield.HasItem) > 0)
            {
                if (this.hudInjectorProxy.ShieldSlotCollectionDTO.ItemSlotDTOs.Count(shield => !shield.IsEquippedToPlayer) > 0)
                {
                    ItemSlotDTO shieldSlot   = this.hudInjectorProxy.ShieldSlotCollectionDTO.ItemSlotDTOs.First(shield => shield.HasItem && !shield.IsEquippedToPlayer);
                    Entity      shieldEntity = this.EntityManager.CreateEntity(this.EntityManager.CreateEquippedShieldArchetype());

                    ItemDTO shieldItem = this.itemCatalog.PremadeWeapons.Where(weapon => weapon.ItemInfo.PreservedShieldType == shieldSlot.OriginalInventoryItem.ItemInfo.PreservedShieldType).First();

                    //Weapon is always placed in left hand
                    SetComponentDataForEquippableEntity(this.EntityManager, shieldEntity, in shieldItem, in playerBodyAnchorComponent.RightHandAnchorPosition);

                    shieldSlot.IsEquippedToPlayer = true;

                    //We previously took the first element so element 0 is also the first element
                    this.hudInjectorProxy.ShieldSlotCollectionDTO.ItemSlotDTOs[0] = shieldSlot;
                }
            }
            //Unequip
            else
            {
                NativeArray <Entity> equippedShields = this.GetEntityQuery(this.EntityManager.GetEquippedShieldIdentifier()).ToEntityArray(Allocator.TempJob);

                for (int i = 0; i < equippedShields.Length; ++i)
                {
                    this.PostUpdateCommands.AddComponent <DeletionTag>(equippedShields[i]);
                }

                equippedShields.Dispose();
            }
        }