diff --git a/Engine.Core/Primitives/AABB3D.cs b/Engine.Core/Primitives/AABB3D.cs
new file mode 100644
index 0000000..70f331a
--- /dev/null
+++ b/Engine.Core/Primitives/AABB3D.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Collections.Generic;
+
+namespace Engine.Core;
+
+///
+/// Represents an Axis-Aligned Bounding Box (AABB) in 3D space.
+///
+/// The lower boundary of the .
+/// The upper boundary of the .
+///
+/// Initializes a new instance of the struct with the specified lower and upper boundaries.
+///
+[System.Diagnostics.DebuggerDisplay("LowerBoundary: {LowerBoundary.ToString(), nq}, UpperBoundary: {UpperBoundary.ToString(), nq}")]
+public readonly struct AABB3D(Vector3D lowerBoundary, Vector3D upperBoundary) : IEquatable
+{
+ ///
+ /// The lower boundary of the .
+ ///
+ public readonly Vector3D LowerBoundary = lowerBoundary;
+
+ ///
+ /// The upper boundary of the .
+ ///
+ public readonly Vector3D UpperBoundary = upperBoundary;
+
+ ///
+ /// Gets the center point of the .
+ ///
+ public readonly Vector3D Center => (LowerBoundary + UpperBoundary) * .5f;
+
+ ///
+ /// Gets the size of the .
+ ///
+ public readonly Vector3D Size => LowerBoundary.FromTo(UpperBoundary).Abs();
+
+ ///
+ /// Gets half the size of the .
+ ///
+ public readonly Vector3D SizeHalf => Size * .5f;
+
+ public static bool operator ==(AABB3D left, AABB3D right) => left.UpperBoundary == right.UpperBoundary && left.LowerBoundary == right.LowerBoundary;
+ public static bool operator !=(AABB3D left, AABB3D right) => left.UpperBoundary != right.UpperBoundary || left.LowerBoundary != right.LowerBoundary;
+
+ ///
+ /// Creates an from a collection of s.
+ ///
+ /// The collection of s.
+ /// An that bounds all the s.
+ public static AABB3D FromVectors(IEnumerable vectors)
+ {
+ int counter = 0;
+
+ Vector3D lowerBoundary = new(float.MaxValue, float.MaxValue, float.MaxValue);
+ Vector3D upperBoundary = new(float.MinValue, float.MinValue, float.MinValue);
+
+ foreach (Vector3D vector in vectors)
+ {
+ lowerBoundary = Vector3D.Min(lowerBoundary, vector);
+ upperBoundary = Vector3D.Max(upperBoundary, vector);
+ counter++;
+ }
+
+ if (counter < 2)
+ throw new ArgumentException($"Parameter {nameof(vectors)} must have at least 2 items.");
+
+ return new(lowerBoundary, upperBoundary);
+ }
+
+ ///
+ /// Checks if two s are approximately equal.
+ ///
+ /// The first .
+ /// The second .
+ /// The epsilon range.
+ /// if the s are approximately equal; otherwise, .
+ public static bool ApproximatelyEquals(AABB3D left, AABB3D right, float epsilon = float.Epsilon)
+ => left.LowerBoundary.ApproximatelyEquals(right.LowerBoundary, epsilon) && left.UpperBoundary.ApproximatelyEquals(right.UpperBoundary, epsilon);
+
+ ///
+ /// Determines whether the specified object is equal to the current .
+ ///
+ /// The object to compare with the current .
+ /// if the specified object is equal to the current ; otherwise, .
+ public override bool Equals(object? obj) => obj is AABB3D aabb && this == aabb;
+ public bool Equals(AABB3D other) => this == other;
+
+ ///
+ /// Generates a hash code for the .
+ ///
+ /// A hash code for the .
+ public override int GetHashCode() => System.HashCode.Combine(LowerBoundary, UpperBoundary);
+
+ ///
+ /// Converts the to its string representation.
+ ///
+ /// A string representation of the .
+ public override string ToString() => $"{nameof(AABB3D)}({LowerBoundary}, {UpperBoundary})";
+}
+
+///
+/// Provides extension methods for the struct.
+///
+public static class AABB3DExtensions
+{
+ ///
+ public static AABB3D ToAABB3D(this IEnumerable vectors) => AABB3D.FromVectors(vectors);
+
+ ///
+ public static bool ApproximatelyEquals(this AABB3D left, AABB3D right, float epsilon = float.Epsilon) => AABB3D.ApproximatelyEquals(left, right, epsilon);
+}
diff --git a/Engine.Integration/Engine.Integration.LiteNetLib/Packers/AABB3DNetPacker.cs b/Engine.Integration/Engine.Integration.LiteNetLib/Packers/AABB3DNetPacker.cs
new file mode 100644
index 0000000..3bd4545
--- /dev/null
+++ b/Engine.Integration/Engine.Integration.LiteNetLib/Packers/AABB3DNetPacker.cs
@@ -0,0 +1,22 @@
+using LiteNetLib.Utils;
+
+using Engine.Core;
+
+namespace Engine.Systems.Network;
+
+internal static class AABB3DNetPacker
+{
+ internal static void Write(NetDataWriter writer, AABB3D data)
+ {
+ Vector3DNetPacker.Write(writer, data.LowerBoundary);
+ Vector3DNetPacker.Write(writer, data.UpperBoundary);
+ }
+
+ internal static AABB3D Read(NetDataReader reader)
+ {
+ Vector3D lowerBoundary = Vector3DNetPacker.Read(reader);
+ Vector3D upperBoundary = Vector3DNetPacker.Read(reader);
+
+ return new AABB3D(lowerBoundary, upperBoundary);
+ }
+}
diff --git a/Engine.Integration/Engine.Integration.Yaml/Converters/Primitives/AABB3DConverter.cs b/Engine.Integration/Engine.Integration.Yaml/Converters/Primitives/AABB3DConverter.cs
new file mode 100644
index 0000000..83558e8
--- /dev/null
+++ b/Engine.Integration/Engine.Integration.Yaml/Converters/Primitives/AABB3DConverter.cs
@@ -0,0 +1,41 @@
+using System;
+
+using Engine.Core;
+
+using YamlDotNet.Core;
+using YamlDotNet.Core.Events;
+using YamlDotNet.Serialization;
+
+namespace Engine.Serializers.Yaml;
+
+public class AABB3DConverter : EngineTypeYamlSerializerBase
+{
+ public override AABB3D Read(IParser parser, Type type, ObjectDeserializer rootDeserializer)
+ {
+ parser.Consume();
+
+ if (parser.Consume().Value.CompareTo(nameof(AABB3D.LowerBoundary)) != 0)
+ throw new ArgumentException($"{nameof(AABB3D)} mapping must start with {nameof(AABB3D.LowerBoundary)}");
+ Vector3D lowerBoundary = (Vector3D)rootDeserializer(typeof(Vector3D))!;
+
+ if (parser.Consume().Value.CompareTo(nameof(AABB3D.UpperBoundary)) != 0)
+ throw new ArgumentException($"{nameof(AABB3D)} mapping must end with {nameof(AABB3D.UpperBoundary)}");
+ Vector3D upperBoundary = (Vector3D)rootDeserializer(typeof(Vector3D))!;
+
+ parser.Consume();
+
+ return new AABB3D(lowerBoundary, upperBoundary);
+ }
+
+ public override void WriteYaml(IEmitter emitter, object? value, Type type, ObjectSerializer serializer)
+ {
+ AABB3D aabb = (AABB3D)value!;
+
+ emitter.Emit(new MappingStart());
+ emitter.Emit(new Scalar(nameof(AABB3D.LowerBoundary)));
+ serializer(aabb.LowerBoundary, typeof(Vector3D));
+ emitter.Emit(new Scalar(nameof(AABB3D.UpperBoundary)));
+ serializer(aabb.UpperBoundary, typeof(Vector3D));
+ emitter.Emit(new MappingEnd());
+ }
+}
diff --git a/Engine.Systems/Tween/EngineExtensions/TweenAABB3DExtensions.cs b/Engine.Systems/Tween/EngineExtensions/TweenAABB3DExtensions.cs
new file mode 100644
index 0000000..f65daf0
--- /dev/null
+++ b/Engine.Systems/Tween/EngineExtensions/TweenAABB3DExtensions.cs
@@ -0,0 +1,24 @@
+using Engine.Core;
+
+namespace Engine.Systems.Tween;
+
+public static class TweenAABB3DExtensions
+{
+ private static readonly BoxedPool boxedAABBPool = new(2);
+
+ public static ITween TweenAABB(this AABB3D initialAABB, ITweenManager tweenManager, float duration, AABB3D targetAABB, System.Action setMethod)
+ {
+ Boxed boxedInitial = boxedAABBPool.Get(initialAABB);
+ Boxed boxedTarget = boxedAABBPool.Get(targetAABB);
+
+ ITween tween = tweenManager.StartTween(duration, t => setMethod?.Invoke(new AABB3D(boxedInitial.Value.LowerBoundary.Lerp(boxedTarget.Value.LowerBoundary, t), boxedInitial.Value.UpperBoundary.Lerp(boxedTarget.Value.UpperBoundary, t))));
+
+ tween.OnComplete(() =>
+ {
+ boxedAABBPool.Return(boxedInitial);
+ boxedAABBPool.Return(boxedTarget);
+ });
+
+ return tween;
+ }
+}