diff --git a/Assets/Scripts/Config/GameEnvironmentConfig.cs b/Assets/Scripts/Config/GameEnvironmentConfig.cs
index f7088ea7fa12c3ccb08bca042f09759fb73d4db0..301e610efaf727fd52009468fccda2ec95fcb01f 100644
--- a/Assets/Scripts/Config/GameEnvironmentConfig.cs
+++ b/Assets/Scripts/Config/GameEnvironmentConfig.cs
@@ -1,8 +1,12 @@
 public static class GameEnvironmentConfig{
     // Tags
-    public static string UNTAGGED_TAG = "Untagged";
-    public static string PLAYER_TAG = "Player";
-    public static string ENEMY_TAG = "Enemy";
-    public static string COLLECTIBLES_TAG = "Collectibles";
-    public static string GROUND_TAG = "Ground";
+    public static string TAG_UNTAGGED = "Untagged";
+    public static string TAG_PLAYER = "Player";
+    public static string TAG_ENEMY = "Enemy";
+    public static string TAG_COLLECTIBLES = "Collectibles";
+    public static string TAG_GROUND = "Ground";
+
+    // Layers
+    public static string LAYER_ENEMY_HITBOX = "EnemyHitbox";
+    public static string LAYER_PLAYER_HITBOX = "PlayerHitbox";
 }
\ No newline at end of file
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
index a0d413b9786b856b44722ea5e0251cb3490aa3f9..f7af76016b8c5854b6c91d600d35f5ec32c50fb4 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackEntity.cs
@@ -1,7 +1,7 @@
 using System;
 using UnityEngine;
 
-public class AttackEntity : RigidEntity, IDamaging, IKnockback{
+public class AttackEntity : RigidEntity, IAttack{
     // Attributes
     [SerializeField] private float damage;
     [SerializeField] private float knockbackPower;
diff --git a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
index ae4645b83965b89eb333d46548e88d6d1681a226..769e801f5188c798a1c9390e35ee5d732e57d968 100644
--- a/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/Entity-Object/AttackObject.cs
@@ -1,7 +1,7 @@
 using System;
 using UnityEngine;
 
-public class AttackObject : MonoBehaviour, IDamaging, IKnockback{
+public class AttackObject : MonoBehaviour, IAttack{
     // Attributes
     [SerializeField] private float damage;
     [SerializeField] private float knockbackPower;
diff --git a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
index 44ea16ac0d01d70be2147afb30fbd1a471b04646..93c2da98e82d2565f34324b2effcc6868f214967 100644
--- a/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
+++ b/Assets/Scripts/Library/BaseClasses/WeaponObject.cs
@@ -4,10 +4,15 @@ using UnityEngine;
 public abstract class WeaponObject : MonoBehaviour {
     // Attributes
     [SerializeField] private float baseDamage;
+    [SerializeField] private float baseKnockbackPower;
     public float BaseDamage { 
         get => baseDamage;
         set => baseDamage = value;
     }
+    public float BaseKnockbackPower { 
+        get => baseKnockbackPower;
+        set => BaseKnockbackPower = value;
+    }
 
     // Functions
     public abstract void Attack();
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs b/Assets/Scripts/Library/Enum/AttackObjectType.cs
new file mode 100644
index 0000000000000000000000000000000000000000..72282390b23821b14999ce34dadf5be62fd4a152
--- /dev/null
+++ b/Assets/Scripts/Library/Enum/AttackObjectType.cs
@@ -0,0 +1,4 @@
+public enum AttackObjectType {
+    PLAYER,
+    ENEMY,
+}
diff --git a/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta b/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..a494c18c8bdc6f00daa60591c7d721bafbdf36b7
--- /dev/null
+++ b/Assets/Scripts/Library/Enum/AttackObjectType.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 26aa78311840dbc4d80cd73c43fe9bcf
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/Interfaces/IAttack.cs b/Assets/Scripts/Library/Interfaces/IAttack.cs
new file mode 100644
index 0000000000000000000000000000000000000000..3076aabbf95bfe87a8c71e6d2584c41acc3ac4ad
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAttack.cs
@@ -0,0 +1 @@
+public interface IAttack : IDamaging, IKnockback{}
\ No newline at end of file
diff --git a/Assets/Scripts/Library/Interfaces/IAttack.cs.meta b/Assets/Scripts/Library/Interfaces/IAttack.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..032c39d8a64a984a1cdaf08e9c31004ab47982ed
--- /dev/null
+++ b/Assets/Scripts/Library/Interfaces/IAttack.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 6b2ca8f784afa944a8843724ccc1ea6b
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Library/Util/ObjectFactory.cs b/Assets/Scripts/Library/Util/ObjectFactory.cs
index a12733365f91cdf07f780164d307e5dc852fc8fc..f63ec3600757069ddcf023724b61895e67954f3b 100644
--- a/Assets/Scripts/Library/Util/ObjectFactory.cs
+++ b/Assets/Scripts/Library/Util/ObjectFactory.cs
@@ -1,3 +1,87 @@
+using System.Collections;
+using UnityEditor.Experimental.GraphView;
+using UnityEngine;
+
 public static class ObjectFactory{
-    
+    public static GameObject CreateObject(
+        GameObject gameObject,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ){
+        GameObject returnObject = parent == null? GameObject.Instantiate(gameObject) : GameObject.Instantiate(gameObject, parent);
+        if(position != null) returnObject.transform.position = position.Value;
+        if(rotation != null) returnObject.transform.rotation = rotation.Value;
+        if(scale != null) returnObject.transform.localScale = Vector3.Scale(returnObject.transform.localScale, scale.Value);
+        if(returnObject.TryGetComponent<Renderer>(out var renderer)) renderer.sortingOrder = renderingOrder;
+        returnObject.name = objectName;
+
+        return returnObject;
+    }
+
+    public static GameObject CreateObject(
+        string prefabPath,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ){
+        GameObject prefabObject = Resources.Load<GameObject>(prefabPath);
+        if(prefabObject == null) Debug.LogError("Prefab not found: " + prefabPath);
+        return CreateObject(prefabObject, parent, position, scale, rotation, renderingOrder, objectName);
+    }
+
+    public static GameObject CreateAttackObject(
+        string prefabPath,
+        float damage,
+        float knockbackPower,
+        AttackObjectType type,
+        Transform parent = null,
+        Vector3? position = null,
+        Vector3? scale = null,
+        Quaternion? rotation = null,
+        int renderingOrder = 0,
+        string objectName = "Unnamed Object"
+    ){
+        GameObject prefabObject = Resources.Load<GameObject>(prefabPath);
+        if(prefabObject == null) Debug.LogError("Prefab not found: " + prefabPath);
+        if(!prefabObject.TryGetComponent<IAttack>(out var attackObject)) Debug.LogError("Loaded prefab is not an IAttack: " + prefabPath);
+
+        attackObject.Damage = damage;
+        attackObject.KnockbackPower = knockbackPower;
+
+        switch (type){
+            case AttackObjectType.PLAYER:
+                prefabObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_PLAYER_HITBOX);
+                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].PlayerDamageMultiplier;
+                break;
+            case AttackObjectType.ENEMY:
+                prefabObject.layer = LayerMask.NameToLayer(GameEnvironmentConfig.LAYER_ENEMY_HITBOX);
+                attackObject.Damage *= GameConfig.DIFFICULTY_MODIFIERS[GameSaveData.instance.difficulty].EnemyDamageMultiplier;
+                break;
+            default:
+                Debug.LogError("Invalid AttackObjectType set, please refer to enum AttackObjectType for valid types");
+                break;
+        }
+
+        return CreateObject(prefabObject, parent, position, scale, rotation, renderingOrder, objectName);
+    }
+
+    public static void Destroy(GameObject gameObject, float delay = 0){
+        if(gameObject == null){
+            Debug.LogError("Tried to destroy a null gameObject");
+            return;
+        }
+        GameController.instance.StartCoroutine(DestroyWithDelay(gameObject, delay));
+    }
+
+    private static IEnumerator DestroyWithDelay(GameObject gameObject, float delay){
+        yield return new WaitForSeconds(delay);
+        GameObject.Destroy(gameObject);
+    }
 }