diff --git a/lib/SDL b/lib/SDL
index 4a53dc5b..d4519aaf 160000
--- a/lib/SDL
+++ b/lib/SDL
@@ -1 +1 @@
-Subproject commit 4a53dc5b8ddb77b09f069d171f5277cee877a0f3
+Subproject commit d4519aafd3d1f3f54cef62ba09c016e6f913a772
diff --git a/lib/freetype b/lib/freetype
index dec2743e..5769f13a 160000
--- a/lib/freetype
+++ b/lib/freetype
@@ -1 +1 @@
-Subproject commit dec2743e6a2a40cddfc8a9892895cb4f861e1eeb
+Subproject commit 5769f13a6b9fafa3840726f06dde07e755501a16
diff --git a/lib/glfw b/lib/glfw
index 3fa23607..3eaf1255 160000
--- a/lib/glfw
+++ b/lib/glfw
@@ -1 +1 @@
-Subproject commit 3fa2360720eeba1964df3c0ecf4b5df8648a8e52
+Subproject commit 3eaf1255b29fdf5c2895856c7be7d7185ef2b241
diff --git a/lib/openal-soft b/lib/openal-soft
index 05f9ce8b..b9de83c3 160000
--- a/lib/openal-soft
+++ b/lib/openal-soft
@@ -1 +1 @@
-Subproject commit 05f9ce8b978239cebecef1a60f0d451a118fa3df
+Subproject commit b9de83c3e191858ac6b572d145bec5f9f2515543
diff --git a/src/dawn/asset/Asset.cpp b/src/dawn/asset/Asset.cpp
index db894629..9c782888 100644
--- a/src/dawn/asset/Asset.cpp
+++ b/src/dawn/asset/Asset.cpp
@@ -8,8 +8,8 @@
 using namespace Dawn;
 
 Asset::Asset(AssetManager *assetManager, std::string name) {
-  assertTrue(name.size() > 0);
-  assertNotNull(assetManager);
+  assertTrue(name.size() > 0, "Asset::Asset: Name cannot be empty");
+  assertNotNull(assetManager, "Asset::Asset: AssetManager cannot be null");
   
   this->assetManager = assetManager;
   this->name = name;
diff --git a/src/dawn/asset/AssetLoader.cpp b/src/dawn/asset/AssetLoader.cpp
index 42cfb5d8..41cce6c7 100644
--- a/src/dawn/asset/AssetLoader.cpp
+++ b/src/dawn/asset/AssetLoader.cpp
@@ -8,58 +8,58 @@
 using namespace Dawn;
 
 AssetLoader::AssetLoader(std::string fileName) {
-  assertTrue(fileName.size() > 0);
+  assertTrue(fileName.size() > 0, "AssetLoader::AssetLoader: fileName must be greater than 0");
 
   this->fileName = fileName;
   this->handle = nullptr;
 }
 
 void AssetLoader::open() {
-  assertNull(this->handle);
+  assertNull(this->handle, "AssetLoader::open: File is already open");
   std::string pathFull = DAWN_ASSET_BUILD_PREFIX + this->fileName;
   this->handle = fopen(pathFull.c_str(), "rb");
-  assertNotNull(this->handle);
+  assertNotNull(this->handle, "AssetLoader::open: Failed to open file");
 }
 
 int32_t AssetLoader::close() {
-  assertNotNull(this->handle);
+  assertNotNull(this->handle, "AssetLoader::close: File is not open");
   int32_t ret = fclose(this->handle);
   this->handle = nullptr;
   return ret;
 }
 
 size_t AssetLoader::read(uint8_t *buffer, size_t size) {
-  assertNotNull(buffer);
-  assertTrue(size > 0);
-  assertNotNull(this->handle);
+  assertNotNull(buffer, "AssetLoader::read: buffer must not be null");
+  assertTrue(size > 0, "AssetLoader::read: size must be greater than 0");
+  assertNotNull(this->handle, "AssetLoader::read: File is not open");
   return fread(buffer, 1, size, this->handle);
 }
 
 int32_t AssetLoader::end() {
-  assertNotNull(this->handle);
+  assertNotNull(this->handle, "AssetLoader::end: File is not open");
   return fseek(this->handle, 0, SEEK_END);
 }
 
 size_t AssetLoader::skip(size_t n) {
-  assertTrue(n > 0);
-  assertNotNull(this->handle);
+  assertTrue(n > 0, "AssetLoader::skip: n must be greater than 0");
+  assertNotNull(this->handle, "AssetLoader::skip: File is not open");
   return fseek(this->handle, n, SEEK_CUR);
 }
 
 int32_t AssetLoader::rewind() {
-  assertNotNull(this->handle);
+  assertNotNull(this->handle, "AssetLoader::rewind: File is not open");
   return fseek(this->handle, 0, SEEK_SET);
 }
 
 size_t AssetLoader::getPosition() {
-  assertNotNull(this->handle);
+  assertNotNull(this->handle, "AssetLoader::getPosition: File is not open");
   return ftell(this->handle);
 }
 
 size_t AssetLoader::loadRaw(uint8_t **buffer) {
   size_t length, read;
 
-  assertNotNull(buffer);
+  assertNotNull(buffer, "AssetLoader::loadRaw: buffer must not be null");
 
   // Open a buffer.
   this->open();
@@ -92,7 +92,7 @@ size_t AssetLoader::loadRaw(uint8_t **buffer) {
 }
 
 size_t AssetLoader::setPosition(size_t position) {
-  assertTrue(position >= 0);
+  assertTrue(position >= 0, "AssetLoader::setPosition: position must be greater than or equal to 0");
   this->rewind();
   return this->skip(position);
 }
diff --git a/src/dawn/asset/AssetManager.hpp b/src/dawn/asset/AssetManager.hpp
index d4eccc36..e4bd401f 100644
--- a/src/dawn/asset/AssetManager.hpp
+++ b/src/dawn/asset/AssetManager.hpp
@@ -79,7 +79,7 @@ namespace Dawn {
        */
       template<class T>
       T * get(std::string name) {
-        assertTrue(name.size() > 0);
+        assertTrue(name.size() > 0, "AssetManager::get: name must be greater than 0");
         
         auto existing = this->assets.find(name);
         if(existing != this->assets.end()) {
@@ -105,11 +105,11 @@ namespace Dawn {
 
       template<class T>
       void unload(T *asset) {
-        assertUnreachable();
+        assertUnreachable("AssetManager::unload: NOT IMPLEMENTED");
       }
 
       void unload(std::string name) {
-        assertUnreachable();
+        assertUnreachable("AssetManager::unload: NOT IMPLEMENTED");
       }
 
       /**
diff --git a/src/dawn/asset/assets/AudioAsset.cpp b/src/dawn/asset/assets/AudioAsset.cpp
index 350e485e..ec783a8c 100644
--- a/src/dawn/asset/assets/AudioAsset.cpp
+++ b/src/dawn/asset/assets/AudioAsset.cpp
@@ -41,7 +41,7 @@ void AudioAsset::updateAsync() {
   end = strchr(start, '|');
   *end = '\0';
   this->channelCount = atoi(start);
-  assertTrue(this->channelCount > 0);
+  assertTrue(this->channelCount > 0, "AudioAsset::updateAsync: Channel count must be greater than 0");
 
   // Sample Rate
   this->state = 0x04;
@@ -49,7 +49,7 @@ void AudioAsset::updateAsync() {
   end = strchr(start, '|');
   *end = '\0';
   this->sampleRate = (uint32_t)strtoul(start, NULL, 10);
-  assertTrue(this->sampleRate > 0);
+  assertTrue(this->sampleRate > 0, "AudioAsset::updateAsync: Sample rate must be greater than 0");
 
   // Number of samples per channel
   this->state = 0x05;
@@ -57,7 +57,7 @@ void AudioAsset::updateAsync() {
   end = strchr(start, '|');
   *end = '\0';
   this->samplesPerChannel = atoi(start);
-  assertTrue(this->samplesPerChannel > 0);
+  assertTrue(this->samplesPerChannel > 0, "AudioAsset::updateAsync: Samples per channel must be greater than 0");
 
   // Total Data Length
   this->state = 0x06;
@@ -65,7 +65,7 @@ void AudioAsset::updateAsync() {
   end = strchr(start, '|');
   *end = '\0';
   this->bufferSize = (size_t)atoll(start);
-  assertTrue(this->bufferSize > 0);
+  assertTrue(this->bufferSize > 0, "AudioAsset::updateAsync: Buffer size must be greater than 0");
 
   // Determine frame size
   this->frameSize = sizeof(int16_t) * this->channelCount;
diff --git a/src/dawn/asset/assets/LanguageAsset.cpp b/src/dawn/asset/assets/LanguageAsset.cpp
index 5cb30fb8..e277fb51 100644
--- a/src/dawn/asset/assets/LanguageAsset.cpp
+++ b/src/dawn/asset/assets/LanguageAsset.cpp
@@ -19,7 +19,7 @@ void LanguageAsset::updateSync() {
 }
 
 void LanguageAsset::updateAsync() {
-  assertTrue(this->state == 0x00);
+  assertTrue(this->state == 0x00, "LanguageAsset::updateAsync: State must be 0x00");
 
   // Open Asset
   this->state = 0x01;
@@ -71,9 +71,9 @@ void LanguageAsset::updateAsync() {
 }
 
 std::string LanguageAsset::getValue(std::string key) {
-  assertTrue(this->state == 0x07);
-  assertMapHasKey(this->values, key);
-  assertTrue(this->values[key].begin >= 0 && this->values[key].length > 0);
+  assertTrue(this->state == 0x07, "LanguageAsset::getValue: State must be 0x07");
+  assertMapHasKey(this->values, key, "LanguageAsset::getValue: Key does not exist");
+  assertTrue(this->values[key].begin >= 0 && this->values[key].length > 0, "LanguageAsset::getValue: Value is invalid");
 
   // Get the positions
   struct AssetLanguageValue value = this->values[key];
diff --git a/src/dawn/asset/assets/TextureAsset.cpp b/src/dawn/asset/assets/TextureAsset.cpp
index 64cf8a4f..79180e7f 100644
--- a/src/dawn/asset/assets/TextureAsset.cpp
+++ b/src/dawn/asset/assets/TextureAsset.cpp
@@ -58,7 +58,7 @@ void TextureAsset::updateAsync() {
     switch(parseState) {
       case TEXTURE_ASSET_HEADER_PARSE_STATE_VERSION: {
         auto compared = strcmp(integer, "DT_2.00");
-        assertTrue(compared == 0);
+        assertTrue(compared == 0, "TextureAsset::updateAsync: Invalid version");
         j = 0;
         parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_WIDTH;
         break;
@@ -66,7 +66,7 @@ void TextureAsset::updateAsync() {
 
       case TEXTURE_ASSET_HEADER_PARSE_STATE_WIDTH: {
         this->width = atoi(integer);
-        assertTrue(this->width > 0);
+        assertTrue(this->width > 0, "TextureAsset::updateAsync: Invalid width");
         j = 0;
         parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_HEIGHT;
         break;
@@ -74,7 +74,7 @@ void TextureAsset::updateAsync() {
 
       case TEXTURE_ASSET_HEADER_PARSE_STATE_HEIGHT: {
         this->height = atoi(integer);
-        assertTrue(this->height > 0);
+        assertTrue(this->height > 0, "TextureAsset::updateAsync: Invalid height");
         j = 0;
         parseState = TEXTURE_ASSET_HEADER_PARSE_STATE_FORMAT;
         break;
@@ -116,7 +116,7 @@ void TextureAsset::updateAsync() {
       }
 
       default:
-        assertUnreachable();
+        assertUnreachable("TextureAsset::updateAsync: Invalid parse state");
     }
   }
 
diff --git a/src/dawn/asset/assets/TilesetAsset.cpp b/src/dawn/asset/assets/TilesetAsset.cpp
index 29f5a8ff..ad96c160 100644
--- a/src/dawn/asset/assets/TilesetAsset.cpp
+++ b/src/dawn/asset/assets/TilesetAsset.cpp
@@ -20,7 +20,7 @@ void TilesetAsset::updateSync() {
 
 void TilesetAsset::updateAsync() {
   uint8_t *buffer;
-  assertTrue(this->state == 0x00);
+  assertTrue(this->state == 0x00, "TilesetAsset::updateAsync: Initial state should be 0x00");
 
   this->state = 0x01;
   this->loader.loadRaw(&buffer);
@@ -34,28 +34,28 @@ void TilesetAsset::updateAsync() {
   *strNext = '\0';
   this->tileset.columns = atoi(strCurrent);
   this->state = 0x03;
-  assertTrue(this->tileset.columns > 0);
+  assertTrue(this->tileset.columns > 0, "TilesetAsset::updateAsync: Count of columns needs to be greater than 0");
 
   strCurrent = strNext+1;
   strNext = strchr(strCurrent, '|');
   *strNext = '\0';
   this->tileset.rows = atoi(strCurrent);
   this->state = 0x04;
-  assertTrue(this->tileset.rows > 0);
+  assertTrue(this->tileset.rows > 0, "TilesetAsset::updateAsync: Count of rows needs to be greater than 0");
 
   strCurrent = strNext+1;
   strNext = strchr(strCurrent, '|');
   *strNext = '\0';
   this->tileset.divX = atoi(strCurrent);
   this->state = 0x05;
-  assertTrue(this->tileset.rows > 0);
+  assertTrue(this->tileset.divX > 0, "TilesetAsset::updateAsync: divX needs to be greater than 0");
 
   strCurrent = strNext+1;
   strNext = strchr(strCurrent, '|');
   *strNext = '\0';
   this->tileset.divY = atoi(strCurrent);
   this->state = 0x06;
-  assertTrue(this->tileset.rows > 0);
+  assertTrue(this->tileset.divY > 0, "TilesetAsset::updateAsync: divY needs to be greater than 0");
 
   // Begin reading tiles.
   int32_t done = 0;
diff --git a/src/dawn/asset/assets/TrueTypeAsset.cpp b/src/dawn/asset/assets/TrueTypeAsset.cpp
index baaae3a4..32194c09 100644
--- a/src/dawn/asset/assets/TrueTypeAsset.cpp
+++ b/src/dawn/asset/assets/TrueTypeAsset.cpp
@@ -15,20 +15,20 @@ TrueTypeAsset::TrueTypeAsset(AssetManager *assMan, std::string name) :
   this->locks.onLockRemoved = [&](usagelockid_t id){
     auto texture = this->textureByLock[id];
 
-    assertNotNull(texture);
+    assertNotNull(texture, "TrueTypeAsset::TrueTypeAsset: Texture cannot be null");
 
     std::vector<usagelockid_t> &lbt = this->locksByTexture[texture];
     auto it0 = std::find(lbt.begin(), lbt.end(), id);
-    assertTrue(it0 != lbt.end());
+    assertTrue(it0 != lbt.end(), "TrueTypeAsset::TrueTypeAsset: Could not remove locksByTexture[texture]");
     lbt.erase(it0);
 
     auto it1 = this->textureByLock.find(id);
-    assertTrue(it1 != this->textureByLock.end());
+    assertTrue(it1 != this->textureByLock.end(), "TrueTypeAsset::TrueTypeAsset: Could not remove textureByLock");
     this->textureByLock.erase(it1);
 
-    if(lbt.empty()) {      
+    if(lbt.empty()) {
       auto it2 = locksByTexture.find(texture);
-      assertTrue(it2 != locksByTexture.end());
+      assertTrue(it2 != locksByTexture.end(), "TrueTypeAsset::TrueTypeAsset: Could not remove locksByTexture");
       locksByTexture.erase(it2);
       
       auto it3 = textureByStyle.begin();
@@ -38,7 +38,7 @@ TrueTypeAsset::TrueTypeAsset(AssetManager *assMan, std::string name) :
       }
 
       auto it4 = std::find(textures.begin(), textures.end(), texture);
-      assertTrue(it4 != textures.end());
+      assertTrue(it4 != textures.end(), "TrueTypeAsset::TrueTypeAsset: Could not remove textureByStyle");
       textures.erase(it4);
 
       delete texture;
@@ -61,40 +61,40 @@ void TrueTypeAsset::updateAsync() {
   uint8_t buffer[64];
   this->loader.rewind();
   size_t read = this->loader.read(buffer, sizeof(char) * 6);
-  assertTrue(read == (6 * sizeof(char)));
+  assertTrue(read == (6 * sizeof(char)), "TrueTypeAsset::updateAsync: Could not read header");
   buffer[6] = '\0';
 
   // Confirm "DE_TTF"
-  assertTrue(std::string((char *)buffer) == "DE_TTF");
+  assertTrue(std::string((char *)buffer) == "DE_TTF", "TrueTypeAsset::updateAsync: Header is invalid (Missing DE_TTF)");
 
   // Vertical bar
   this->loader.read(buffer, 1);
-  assertTrue(buffer[0] == '|');
+  assertTrue(buffer[0] == '|', "TrueTypeAsset::updateAsync: Header is invalid (Missing first vertical bar)");
 
   // Read version
   this->state = TRUE_TYPE_ASSET_STATE_VALIDATE_VERSION;
   read = this->loader.read(buffer, sizeof(char) * 5);
-  assertTrue(buffer[0] == '3');
-  assertTrue(buffer[1] == '.');
-  assertTrue(buffer[2] == '0');
-  assertTrue(buffer[3] == '0');
-  assertTrue(buffer[4] == '|');
+  assertTrue(buffer[0] == '3', "TrueTypeAsset::updateAsync: Version is invalid 3");
+  assertTrue(buffer[1] == '.', "TrueTypeAsset::updateAsync: Version is invalid .");
+  assertTrue(buffer[2] == '0', "TrueTypeAsset::updateAsync: Version is invalid 0(1)");
+  assertTrue(buffer[3] == '0', "TrueTypeAsset::updateAsync: Version is invalid 0(2)");
+  assertTrue(buffer[4] == '|', "TrueTypeAsset::updateAsync: Version is invalid (Missing second vertical bar)");
 
   // Read the count of font styles / variants.
   size_t styleListBegin = this->loader.getPosition();
   this->state = TRUE_TYPE_ASSET_STATE_READ_VARIANT_COUNT;
   read = this->loader.read(buffer, 64);
-  assertTrue(read > 0);
+  assertTrue(read > 0, "TrueTypeAsset::updateAsync: Could not read variant count");
 
   // Get position of vertical bar.
   size_t i = 0;
   while(buffer[i] != '|' && i < 64) i++;
-  assertTrue(buffer[i] == '|');
+  assertTrue(buffer[i] == '|', "TrueTypeAsset::updateAsync: Could not find vertical bar");
   styleListBegin += i + 1;
   buffer[i] = '\0';
 
   int32_t count = atoi((char *)buffer);
-  assertTrue(count > 0);
+  assertTrue(count > 0, "TrueTypeAsset::updateAsync: Invalid variant count");
 
   // Now begin parsing each font style.
   this->state = TRUE_TYPE_ASSET_STATE_READ_VARIANT;
@@ -106,7 +106,7 @@ void TrueTypeAsset::updateAsync() {
     this->loader.rewind();
     this->loader.setPosition(styleListBegin);
     read = this->loader.read(buffer, 32);
-    assertTrue(read == 32);
+    assertTrue(read == 32, "TrueTypeAsset::updateAsync: Could not read variant");
 
     // Read style
     i = 0;
@@ -119,7 +119,7 @@ void TrueTypeAsset::updateAsync() {
     this->loader.rewind();
     this->loader.setPosition(styleListBegin);
     read = this->loader.read(buffer, 32);
-    assertTrue(read == 32);
+    assertTrue(read == 32, "TrueTypeAsset::updateAsync: Could not read variant style");
 
     // Read length
     i = 0;
@@ -145,7 +145,7 @@ void TrueTypeAsset::updateAsync() {
   // Init FreeType
   this->state = TRUE_TYPE_ASSET_STATE_INIT_FREETYPE;
   int32_t ret = FT_Init_FreeType(&fontLibrary);
-  assertTrue(ret == 0);
+  assertTrue(ret == 0, "TrueTypeAsset::updateAsync: Could not init FreeType");
 
   // Done parsing!
   this->state = TRUE_TYPE_ASSET_STATE_READY;
@@ -153,7 +153,7 @@ void TrueTypeAsset::updateAsync() {
 }
 
 usagelockid_t TrueTypeAsset::lock(struct TrueTypeFaceTextureStyle style) {
-  assertTrue(this->state == TRUE_TYPE_ASSET_STATE_READY);
+  assertTrue(this->state == TRUE_TYPE_ASSET_STATE_READY, "TrueTypeAsset::lock: Asset is not ready");
 
   // Try and find an existing texture that matches this style
   auto it = this->textureByStyle.find(style);
@@ -169,19 +169,19 @@ usagelockid_t TrueTypeAsset::lock(struct TrueTypeFaceTextureStyle style) {
       }
       ++itAssetStyle;
     }
-    assertTrue(itAssetStyle != this->assetStyles.end());
+    assertTrue(itAssetStyle != this->assetStyles.end(), "TrueTypeAsset::lock: Could not find asset style");
 
     // Create and read buffer.
     uint8_t *dataBuffer = (uint8_t*)memoryAllocate(sizeof(uint8_t) * itAssetStyle->dataSize);
     this->loader.rewind();
     this->loader.setPosition(itAssetStyle->dataOffset);
     auto read = this->loader.read(dataBuffer, itAssetStyle->dataSize);
-    assertTrue(read == itAssetStyle->dataSize);
+    assertTrue(read == itAssetStyle->dataSize, "TrueTypeAsset::lock: Could not read data");
 
     // Create the face
     FT_Face face;
     auto ret = FT_New_Memory_Face(this->fontLibrary, (FT_Byte*)dataBuffer, itAssetStyle->dataSize, 0, &face);
-    assertTrue(ret == 0);
+    assertTrue(ret == 0, "TrueTypeAsset::lock: Could not create face");
     texture = new TrueTypeFaceTexture(face, style);
     memoryFree(dataBuffer);
 
@@ -200,7 +200,7 @@ usagelockid_t TrueTypeAsset::lock(struct TrueTypeFaceTextureStyle style) {
 
 TrueTypeFaceTexture * TrueTypeAsset::getTexture(usagelockid_t id) {
   auto it = this->textureByLock.find(id);
-  assertTrue(it != this->textureByLock.end());
+  assertTrue(it != this->textureByLock.end(), "TrueTypeAsset::getTexture: Could not find texture");
   return it->second;
 }
 
diff --git a/src/dawn/display/RenderPipeline.cpp b/src/dawn/display/RenderPipeline.cpp
index 10c0d6ad..8e156588 100644
--- a/src/dawn/display/RenderPipeline.cpp
+++ b/src/dawn/display/RenderPipeline.cpp
@@ -14,7 +14,7 @@
 using namespace Dawn;
 
 RenderPipeline::RenderPipeline(RenderManager *renderManager) {
-  assertNotNull(renderManager);
+  assertNotNull(renderManager, "RenderPipeline::RenderPipeline: RenderManager cannot be null");
   this->renderManager = renderManager;
 }
 
@@ -29,7 +29,7 @@ void RenderPipeline::render() {
 }
 
 void RenderPipeline::renderScene(Scene *scene) {
-  assertNotNull(scene);
+  assertNotNull(scene, "RenderPipeline::renderScene: Scene cannot be null");
 
   // Render subscenes first.
   auto subSceneControllers = scene->findComponents<SubSceneController>();
@@ -82,8 +82,8 @@ void RenderPipeline::renderScene(Scene *scene) {
 void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
   std::vector<struct ShaderPassItem>::iterator itPassItem;
 
-  assertNotNull(scene);
-  assertNotNull(camera);
+  assertNotNull(scene, "RenderPipeline::renderSceneCamera: Scene cannot be null");
+  assertNotNull(camera, "RenderPipeline::renderSceneCamera: Camera cannot be null");
 
   // Create a new render ID. Long story short this is a really dirty way of 
   // not sending parameters to shaders more than we need.
@@ -91,7 +91,7 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
 
   // Get the render target.
   auto renderTarget = camera->getRenderTarget();
-  assertNotNull(renderTarget);
+  assertNotNull(renderTarget, "RenderPipeline::renderSceneCamera: Camera must have a render target");
 
   // Update shader parameter buffers with current knowledge
   struct RenderPipelineShaderBufferData shaderBufferData;
@@ -183,7 +183,7 @@ void RenderPipeline::renderSceneCamera(Scene *scene, Camera *camera) {
     auto itTextureSlot = item.textureSlots.begin();
     while(itTextureSlot != item.textureSlots.end()) {
       // Assert texture isn't null, just don't include it.
-      assertNotNull(itTextureSlot->second);
+      assertNotNull(itTextureSlot->second, "RenderPipeline::renderSceneCamera: Texture cannot be null (omit texture instead)");
 
       if(boundTextures[itTextureSlot->first] != itTextureSlot->second) {
         itTextureSlot->second->bind(itTextureSlot->first);
diff --git a/src/dawn/display/Tileset.cpp b/src/dawn/display/Tileset.cpp
index a9cc605f..15a25e07 100644
--- a/src/dawn/display/Tileset.cpp
+++ b/src/dawn/display/Tileset.cpp
@@ -8,8 +8,8 @@
 using namespace Dawn;
 
 struct Tile Tileset::getTile(int32_t tile) {
-  assertTrue(tile >= 0);
-  assertTrue(tile < this->tiles.size());
+  assertTrue(tile >= 0, "Tileset::getTile: Tile must be greater than or equal to 0");
+  assertTrue(tile < this->tiles.size(), "Tileset::getTile: Tile is out of bounds");
   return this->tiles[tile];
 }
 
@@ -55,16 +55,16 @@ TilesetGrid::TilesetGrid(
   int32_t borderX,
   int32_t borderY
 ) {
-  assertTrue(columns >= 1);
-  assertTrue(rows >= 1);
-  assertTrue(w >= 1);
-  assertTrue(h >= 1);
-  assertTrue(gapX >= 0);
-  assertTrue(gapY >= 0);
-  assertTrue(borderX >= 0);
-  assertTrue(borderY >= 0);
-  assertTrue(w >= (columns + (gapX * columns) + borderX + borderX));
-  assertTrue(h >= (rows + (gapY * rows) + borderY + borderY));
+  assertTrue(columns >= 1, "TilesetGrid::TilesetGrid: Columns must be greater than or equal to 1");
+  assertTrue(rows >= 1, "TilesetGrid::TilesetGrid: Rows must be greater than or equal to 1");
+  assertTrue(w >= 1, "TilesetGrid::TilesetGrid: Width must be greater than or equal to 1");
+  assertTrue(h >= 1, "TilesetGrid::TilesetGrid: Height must be greater than or equal to 1");
+  assertTrue(gapX >= 0, "TilesetGrid::TilesetGrid: GapX must be greater than or equal to 0");
+  assertTrue(gapY >= 0, "TilesetGrid::TilesetGrid: GapY must be greater than or equal to 0");
+  assertTrue(borderX >= 0, "TilesetGrid::TilesetGrid: BorderX must be greater than or equal to 0");
+  assertTrue(borderY >= 0, "TilesetGrid::TilesetGrid: BorderY must be greater than or equal to 0");
+  assertTrue(w >= (columns + (gapX * columns) + borderX + borderX), "TilesetGrid::TilesetGrid: Width is too small");
+  assertTrue(h >= (rows + (gapY * rows) + borderY + borderY), "TilesetGrid::TilesetGrid: Height is too small");
 
   this->rows = rows;
   this->columns = columns;
@@ -99,7 +99,7 @@ float_t TilesetGrid::getTileHeight(int32_t tile) {
 }
 
 struct Tile TilesetGrid::getTileFromGrid(int32_t column, int32_t row) {
-  assertTrue(row > 0 && row < this->rows);
-  assertTrue(column > 0 && column < this->columns);
+  assertTrue(row > 0 && row < this->rows, "TilesetGrid::getTileFromGrid: Row is out of bounds");
+  assertTrue(column > 0 && column < this->columns, "TilesetGrid::getTileFromGrid: Column is out of bounds");
   return this->getTile(row + (column * this->rows));
 }
\ No newline at end of file
diff --git a/src/dawn/display/Transform.cpp b/src/dawn/display/Transform.cpp
index a1a0058d..783945a5 100644
--- a/src/dawn/display/Transform.cpp
+++ b/src/dawn/display/Transform.cpp
@@ -13,7 +13,7 @@ Transform::Transform(SceneItem *item) :
   transformLocal(1.0f),
   transformWorld(1.0f)
 {
-  assertNotNull(item);
+  assertNotNull(item, "Transform::Transform: Item cannot be null");
   
   this->item = item;
   this->updateLocalValuesFromLocalTransform();
@@ -147,7 +147,7 @@ void Transform::setWorldTransform(glm::mat4 transform) {
 
 
 void Transform::setParent(Transform *parent) {
-  assertTrue(parent == nullptr || parent != this);
+  assertTrue(parent == nullptr || parent != this, "Transform::setParent: Cannot set parent to self");
   
   auto currentParent = this->getParent();
   if(currentParent == parent) return;
diff --git a/src/dawn/display/_RenderManager.hpp b/src/dawn/display/_RenderManager.hpp
index e3a40b05..3371eeb7 100644
--- a/src/dawn/display/_RenderManager.hpp
+++ b/src/dawn/display/_RenderManager.hpp
@@ -29,7 +29,7 @@ namespace Dawn {
        * @param game Game that this render manager belongs to.
        */
       IRenderManager(DawnGame *game) {
-        assertNotNull(game);
+        assertNotNull(game, "IRenderManager::IRenderManager: Game cannot be null");
         this->game = game;
       }
 
diff --git a/src/dawn/display/animation/SimpleAnimation.hpp b/src/dawn/display/animation/SimpleAnimation.hpp
index a3a52e73..13b18c86 100644
--- a/src/dawn/display/animation/SimpleAnimation.hpp
+++ b/src/dawn/display/animation/SimpleAnimation.hpp
@@ -48,7 +48,7 @@ namespace Dawn {
        * @param modifies Pointer to the value that will be modified.
        */
       SimpleAnimation(T *modifies) {
-        assertNotNull(modifies);
+        assertNotNull(modifies, "SimpleAnimation::SimpleAnimation: Modifies cannot be null");
         this->modifies = modifies;
       }
 
@@ -59,7 +59,7 @@ namespace Dawn {
        * @param value Value at this given time.
        */
       void addKeyframe(float_t time, T value) {
-        assertTrue(time >= 0);
+        assertTrue(time >= 0, "SimpleAnimation::addKeyframe: Time must be >= 0");
         
         struct SimpleKeyframe<T> keyframe;
         keyframe.time = time;
diff --git a/src/dawn/display/font/truetype/TrueTypeFaceTexture.cpp b/src/dawn/display/font/truetype/TrueTypeFaceTexture.cpp
index 284ca0b8..e1762052 100644
--- a/src/dawn/display/font/truetype/TrueTypeFaceTexture.cpp
+++ b/src/dawn/display/font/truetype/TrueTypeFaceTexture.cpp
@@ -11,14 +11,14 @@ TrueTypeFaceTexture::TrueTypeFaceTexture(
   FT_Face face,
   struct TrueTypeFaceTextureStyle style
 ) {
-  assertTrue(style.fontSize < 256);
+  assertTrue(style.fontSize < 256, "TrueTypeFaceTexture::TrueTypeFaceTexture: Font size cannot be greater than 256");
 
   this->face = face;
   this->style = style;
 
   // Set freetype font size prior to baking.
   if(FT_Set_Pixel_Sizes(face, 0, style.fontSize)) {
-    assertUnreachable();
+    assertUnreachable("TrueTypeFaceTexture::TrueTypeFaceTexture: Failed to set font size");
   }
 
   size_t w = 0, h = 0;
@@ -29,7 +29,7 @@ TrueTypeFaceTexture::TrueTypeFaceTexture(
     // Load the character
     auto ret = FT_Load_Char(face, c, FT_LOAD_BITMAP_METRICS_ONLY);
     if(ret) {
-      assertUnreachable();
+      assertUnreachable("TrueTypeFaceTexture::TrueTypeFaceTexture: Failed to load character (0)");
     }
 
     if(face->glyph->bitmap.width == 0 || face->glyph->bitmap.rows == 0) continue;
@@ -39,8 +39,8 @@ TrueTypeFaceTexture::TrueTypeFaceTexture(
     h += face->glyph->bitmap.rows;
   }
 
-  assertTrue(w > 0);
-  assertTrue(h > 0);
+  assertTrue(w > 0, "TrueTypeFaceTexture::TrueTypeFaceTexture: Width cannot be less than or equal to 0");
+  assertTrue(h > 0, "TrueTypeFaceTexture::TrueTypeFaceTexture: Height cannot be less than or equal to 0");
 
   // Now buffer pixels to the texture
   float_t y = 0;
@@ -54,7 +54,7 @@ TrueTypeFaceTexture::TrueTypeFaceTexture(
   for(c = TRUE_TYPE_CHAR_BEGIN; c < TRUE_TYPE_CHAR_END; c++) {
     // Load the character
     if(FT_Load_Char(face, c, FT_LOAD_RENDER)) {
-      assertUnreachable();
+      assertUnreachable("TrueTypeFaceTexture::TrueTypeFaceTexture: Failed to load character (1)");
     }
 
     // Store the character information
@@ -74,7 +74,7 @@ TrueTypeFaceTexture::TrueTypeFaceTexture(
         face->glyph->bitmap.width * sizeof(uint8_t)
       );
       offset += w * sizeof(uint8_t);
-      assertTrue(offset <= (w * h * sizeof(uint8_t)));
+      assertTrue(offset <= (w * h * sizeof(uint8_t)), "TrueTypeFaceTexture::TrueTypeFaceTexture: Buffer overflow");
     }
     y += face->glyph->bitmap.rows;
   }
diff --git a/src/dawn/display/mesh/CapsuleMesh.cpp b/src/dawn/display/mesh/CapsuleMesh.cpp
index 590989c2..c7c9b5bc 100644
--- a/src/dawn/display/mesh/CapsuleMesh.cpp
+++ b/src/dawn/display/mesh/CapsuleMesh.cpp
@@ -16,7 +16,7 @@ void CapsuleMesh::calculateRing(
   float_t dy,
   std::vector<glm::vec3> *positions
 ) {
-  assertNotNull(positions);
+  assertNotNull(positions, "CapsuleMesh::calculateRing: positions cannot be null");
   float_t segIncr = 1.0f / (float_t)(segments - 1);
   for(int32_t s = 0; s < segments; s++ ) {
     float_t x = cosf(MATH_PI * 2 * s * segIncr) * dr;
@@ -30,7 +30,7 @@ void CapsuleMesh::create(
   float_t radius,
   float_t height
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "CapsuleMesh::create: Mesh cannot be null");
 
   std::vector<glm::vec3> positions;
   std::vector<meshindice_t> indices;
diff --git a/src/dawn/display/mesh/CubeMesh.cpp b/src/dawn/display/mesh/CubeMesh.cpp
index 5c2496d2..233d8a30 100644
--- a/src/dawn/display/mesh/CubeMesh.cpp
+++ b/src/dawn/display/mesh/CubeMesh.cpp
@@ -12,7 +12,7 @@ void CubeMesh::buffer(
   glm::vec3 pos, glm::vec3 size,
   int32_t verticeStart, int32_t indiceStart
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "CubeMesh::buffer: Mesh cannot be null");
 
   glm::vec3 positions[CUBE_VERTICE_COUNT] = {
     pos, 
diff --git a/src/dawn/display/mesh/QuadMesh.cpp b/src/dawn/display/mesh/QuadMesh.cpp
index 39c7fcc8..51060ff9 100644
--- a/src/dawn/display/mesh/QuadMesh.cpp
+++ b/src/dawn/display/mesh/QuadMesh.cpp
@@ -13,7 +13,7 @@ void QuadMesh::bufferQuadMeshWithZ(
   glm::vec2 xy1, glm::vec2 uv1,
   float_t z, int32_t verticeStart, int32_t indiceStart
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "QuadMesh::bufferQuadMeshWithZ: Mesh cannot be null");
 
   glm::vec3 positions[QUAD_VERTICE_COUNT] = {
     glm::vec3(xy0, z),
@@ -51,7 +51,7 @@ void QuadMesh::bufferCoordinates(
   glm::vec2 uv0, glm::vec2 uv1,
   int32_t verticeStart
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "QuadMesh::bufferCoordinates: Mesh cannot be null");
   glm::vec2 coordinates[QUAD_VERTICE_COUNT] = {
     uv0, glm::vec2(uv1.x, uv0.y),
     glm::vec2(uv0.x, uv1.y), uv1
@@ -64,7 +64,7 @@ void QuadMesh::bufferPositions(
   glm::vec2 xy0, glm::vec2 xy1,
   int32_t verticeStart
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "QuadMesh::bufferPositions: Mesh cannot be null");
   glm::vec3 positions[QUAD_VERTICE_COUNT] = {
     glm::vec3(xy0, 0),
     glm::vec3(xy1.x, xy0.y, 0),
@@ -80,7 +80,7 @@ void QuadMesh::initQuadMesh(
   glm::vec2 xy1, glm::vec2 uv1,
   float_t z
 ) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "QuadMesh::initQuadMesh: Mesh cannot be null");
   mesh->createBuffers(QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT);
   QuadMesh::bufferQuadMeshWithZ(mesh, xy0, uv0, xy1, uv1, z, 0, 0);
 }
\ No newline at end of file
diff --git a/src/dawn/display/mesh/TriangleMesh.cpp b/src/dawn/display/mesh/TriangleMesh.cpp
index e2d5ea7c..4b24130d 100644
--- a/src/dawn/display/mesh/TriangleMesh.cpp
+++ b/src/dawn/display/mesh/TriangleMesh.cpp
@@ -8,7 +8,7 @@
 using namespace Dawn;
 
 void TriangleMesh::createTriangleMesh(Mesh *mesh) {
-  assertNotNull(mesh);
+  assertNotNull(mesh, "TriangleMesh::createTriangleMesh: Mesh cannot be null");
 
   glm::vec3 positions[3] = {
     glm::vec3(-0.5f, -0.5f, 0),
diff --git a/src/dawn/event/Event.hpp b/src/dawn/event/Event.hpp
index 9b621d70..0c86466d 100644
--- a/src/dawn/event/Event.hpp
+++ b/src/dawn/event/Event.hpp
@@ -32,7 +32,7 @@ namespace Dawn {
      * @param callback Callback method that invokes back.
      */
     EventListener(T *instance, void (T::*callback)(A... args)) {
-      assertNotNull(instance);
+      assertNotNull(instance, "EventListener::EventListener: Instance cannot be null");
 
       this->instance = instance;
       this->callback = callback;
@@ -64,10 +64,10 @@ namespace Dawn {
         T *instance,
         void (T::*callback)(A... args)
       ) {
-        assertNotNull(instance);
+        assertNotNull(instance, "Event::addListener: Instance cannot be null");
 
         auto listener = new EventListener<T,A...>(instance, callback);
-        assertNotNull(listener);
+        assertNotNull(listener, "Event::addListener: Listener could not be created (Memory filled?)");
         this->listeners.push_back(listener);
         return listener;
       }
diff --git a/src/dawn/games/tictactoe/TicTacToeLogic.cpp b/src/dawn/games/tictactoe/TicTacToeLogic.cpp
index 79897d14..6b1b0951 100644
--- a/src/dawn/games/tictactoe/TicTacToeLogic.cpp
+++ b/src/dawn/games/tictactoe/TicTacToeLogic.cpp
@@ -12,7 +12,7 @@ enum TicTacToeTileState Dawn::ticTacToeDetermineWinner(
   std::vector<uint8_t> *winningCombo
 ) {
   uint8_t i;
-  assertNotNull(winningCombo);
+  assertNotNull(winningCombo, "ticTacToeDetermineWinner: winningCombo cannot be null");
 
   // Check rows
   for(i = 0; i < 9; i += 3) {
diff --git a/src/dawn/games/vn/components/VNTextboxScroller.cpp b/src/dawn/games/vn/components/VNTextboxScroller.cpp
index 5569f531..5b402524 100644
--- a/src/dawn/games/vn/components/VNTextboxScroller.cpp
+++ b/src/dawn/games/vn/components/VNTextboxScroller.cpp
@@ -16,7 +16,7 @@ VNTextboxScroller::VNTextboxScroller(SceneItem *item) :
 }
 
 void VNTextboxScroller::onStart() {
-  assertNotNull(label);
+  assertNotNull(label, "VNTextboxScroller::onStart: Label cannot be null");
 
   std::function<void()> x = [&]{
     this->lineCurrent = 0;
@@ -101,5 +101,4 @@ bool_t VNTextboxScroller::hasRevealedAllCharacters() {
     this->lineCurrent + this->visibleLines >=
     this->label->lines.size()
   );
-  assertUnreachable();
 }
\ No newline at end of file
diff --git a/src/dawn/games/vn/events/VNEvent.cpp b/src/dawn/games/vn/events/VNEvent.cpp
index e578f8bf..e287baf2 100644
--- a/src/dawn/games/vn/events/VNEvent.cpp
+++ b/src/dawn/games/vn/events/VNEvent.cpp
@@ -29,8 +29,8 @@ VNEvent * VNEvent::getNextEvent() {
 }
 
 void VNEvent::next() {
-  assertNotNull(this->manager);
-  assertNotNull(this->parent);
+  assertNotNull(this->manager, "VNEvent::next: Manager cannot be null");
+  assertNotNull(this->parent, "VNEvent::next: Parent cannot be null");
 
   this->end();
   auto next = this->getNextEvent();
diff --git a/src/dawn/games/vn/events/VNIfEvent.hpp b/src/dawn/games/vn/events/VNIfEvent.hpp
index b847d790..94966c87 100644
--- a/src/dawn/games/vn/events/VNIfEvent.hpp
+++ b/src/dawn/games/vn/events/VNIfEvent.hpp
@@ -19,8 +19,8 @@ namespace Dawn {
 
     protected:
       void onStart() override {
-        assertNotNull(ifTrue);
-        assertNotNull(ifEnd);
+        assertNotNull(ifTrue, "VNIfEvent::onStart: ifTrue cannot be null");
+        assertNotNull(ifEnd, "VNIfEvent::onStart: ifEnd cannot be null");
 
         if(this->manager->getFlag(key) == value) {
           useEvent([&]{
diff --git a/src/dawn/games/vn/events/VNTextEvent.hpp b/src/dawn/games/vn/events/VNTextEvent.hpp
index 29d57048..7416c3b6 100644
--- a/src/dawn/games/vn/events/VNTextEvent.hpp
+++ b/src/dawn/games/vn/events/VNTextEvent.hpp
@@ -18,7 +18,7 @@ namespace Dawn {
 
       void onStart() override {
         scroller = this->getScene()->findComponent<VNTextboxScroller>();
-        assertNotNull(scroller);
+        assertNotNull(scroller, "VNTextEvent::onStart: VNTextboxScroller cannot be null");
 
         auto richText = stringReplaceAll(this->manager->defaultFont, "{{ text }}", this->text);
         scroller->label->richText = richText;
diff --git a/src/dawn/input/_InputManager.hpp b/src/dawn/input/_InputManager.hpp
index b93416f7..dc22dfa4 100644
--- a/src/dawn/input/_InputManager.hpp
+++ b/src/dawn/input/_InputManager.hpp
@@ -37,7 +37,7 @@ namespace Dawn {
       StateEvent<inputbind_t> eventBindReleased;
 
       IInputManager(DawnGame *game) {
-        assertNotNull(game);
+        assertNotNull(game, "IInputManager::IInputManager: Game cannot be null");
         this->game = game;
       }
 
diff --git a/src/dawn/locale/LocaleManager.cpp b/src/dawn/locale/LocaleManager.cpp
index 880486ce..64b1984f 100644
--- a/src/dawn/locale/LocaleManager.cpp
+++ b/src/dawn/locale/LocaleManager.cpp
@@ -57,7 +57,7 @@ struct Locale LocaleManager::getLocale() {
 }
 
 std::string LocaleManager::getString(std::string key) {
-  assertNotNull(this->currentlyLoadedAsset);
+  assertNotNull(this->currentlyLoadedAsset, "LocaleManager::getString: Currently loaded asset cannot be null");
   return this->currentlyLoadedAsset->getValue(key);
 }
 
diff --git a/src/dawn/physics/3d/Ray3D.cpp b/src/dawn/physics/3d/Ray3D.cpp
index b0eadad1..fd968708 100644
--- a/src/dawn/physics/3d/Ray3D.cpp
+++ b/src/dawn/physics/3d/Ray3D.cpp
@@ -39,9 +39,9 @@ bool_t Dawn::raytestTriangle(
   glm::vec3 *hitNormal,
   float_t *hitDistance
 ) {
-  assertNotNull(hitPoint);
-  assertNotNull(hitNormal);
-  assertNotNull(hitDistance);
+  assertNotNull(hitPoint, "Ray3D::raytestTriangle: hitPoint cannot be null");
+  assertNotNull(hitNormal, "Ray3D::raytestTriangle: hitNormal cannot be null");
+  assertNotNull(hitDistance, "Ray3D::raytestTriangle: hitDistance cannot be null");
 
   // Calculate the normal of the triangle
   glm::vec3 e0 = triangle.v1 - triangle.v0;
@@ -92,9 +92,9 @@ bool_t Dawn::raytestAABB(
   glm::vec3 *normal,
   float_t *distance
 ) {
-  assertNotNull(point);
-  assertNotNull(normal);
-  assertNotNull(distance);
+  assertNotNull(point, "Ray3D::raytestAABB: point cannot be null");
+  assertNotNull(normal, "Ray3D::raytestAABB: normal cannot be null");
+  assertNotNull(distance, "Ray3D::raytestAABB: distance cannot be null");
 
   // Compute the inverse direction of the ray, for numerical stability
   glm::vec3 invDir(1.0f / ray.direction.x, 1.0f / ray.direction.y, 1.0f / ray.direction.z);
@@ -176,9 +176,9 @@ bool_t Dawn::raytestQuad(
   glm::vec3 *normal,
   float_t *distance
 ) {
-  assertNotNull(point);
-  assertNotNull(normal);
-  assertNotNull(distance);
+  assertNotNull(point, "Ray3D::raytestQuad: point cannot be null");
+  assertNotNull(normal, "Ray3D::raytestQuad: normal cannot be null");
+  assertNotNull(distance, "Ray3D::raytestQuad: distance cannot be null");
   
   // transform ray into local space of the quad
   glm::mat4 inverseTransform = glm::inverse(transform);
diff --git a/src/dawn/prefab/Prefab.hpp b/src/dawn/prefab/Prefab.hpp
index a2e48377..6c7d8c9a 100644
--- a/src/dawn/prefab/Prefab.hpp
+++ b/src/dawn/prefab/Prefab.hpp
@@ -29,7 +29,7 @@ namespace Dawn {
        * @return The instance of the created prefab.
        */
       static O * create(J *context) {
-        assertNotNull(context);
+        assertNotNull(context, "Prefab::create: Context cannot be null");
         return P::prefabCreate(context);
       }
   };
diff --git a/src/dawn/save/SaveFile.cpp b/src/dawn/save/SaveFile.cpp
index db457acf..c1ce8c91 100644
--- a/src/dawn/save/SaveFile.cpp
+++ b/src/dawn/save/SaveFile.cpp
@@ -14,7 +14,7 @@ bool_t SaveFile::has(std::string key) {
 
 savedata_t SaveFile::get(std::string key) {
   auto exist = this->values.find(key);
-  assertTrue(exist != this->values.end());
+  assertTrue(exist != this->values.end(), "SaveFile::get: Key does not exist");
   return exist->second;
 }
 
diff --git a/src/dawn/save/SaveManager.cpp b/src/dawn/save/SaveManager.cpp
index c5dbaaa4..42bbf576 100644
--- a/src/dawn/save/SaveManager.cpp
+++ b/src/dawn/save/SaveManager.cpp
@@ -15,7 +15,7 @@ SaveManager::SaveManager(DawnGame *game) {
 void SaveManager::saveFile() {
   savedata_t value;
 
-  assertTrue(this->currentSaveSlot >= 0);
+  assertTrue(this->currentSaveSlot >= 0, "SaveManager::saveFile: Current save slot must be greater than or equal to 0");
   
   // Update metadata
   auto timestamp = this->game->timeManager.getTimestamp();
@@ -30,7 +30,7 @@ void SaveManager::saveFile() {
   FILE *fptr = fopen(filename, "wb");
   if(fptr == NULL) {
     printf("Error opening %s\n", filename);
-    assertUnreachable();
+    assertUnreachable("SaveManager::saveFile: Error opening file");
     return;
   }
 
@@ -60,7 +60,7 @@ void SaveManager::saveFile() {
 enum SaveLoadResult SaveManager::loadFile() {
   this->currentSave.reset();
 
-  assertTrue(this->currentSaveSlot >= 0);
+  assertTrue(this->currentSaveSlot >= 0, "SaveManager::loadFile: Current save slot must be greater than or equal to 0");
 
   // Load file
   struct SaveFile temporaryFile;
@@ -201,11 +201,11 @@ enum SaveLoadResult SaveManager::loadFile() {
 }
 
 void SaveManager::deleteFile(int16_t slot) {
-  assertTrue(slot >= 0);
+  assertTrue(slot >= 0, "SaveManager::deleteFile: Slot must be greater than or equal to 0");
 }
 
 void SaveManager::useSlot(int16_t slot) {
-  assertTrue(slot >= 0);
+  assertTrue(slot >= 0, "SaveManager::useSlot: Slot must be greater than or equal to 0");
   this->currentSaveSlot = slot;
   this->currentSave.reset();
 }
diff --git a/src/dawn/scene/Scene.cpp b/src/dawn/scene/Scene.cpp
index 86908e22..0757d626 100644
--- a/src/dawn/scene/Scene.cpp
+++ b/src/dawn/scene/Scene.cpp
@@ -11,7 +11,7 @@
 using namespace Dawn;
 
 Scene::Scene(DawnGame *game) {
-  assertNotNull(game);
+  assertNotNull(game, "Scene::Scene: Game cannot be null");
   this->game = game;
   this->nextId = 0;
   this->physics = new ScenePhysicsManager(this);
diff --git a/src/dawn/scene/Scene.hpp b/src/dawn/scene/Scene.hpp
index aac42c95..af764072 100644
--- a/src/dawn/scene/Scene.hpp
+++ b/src/dawn/scene/Scene.hpp
@@ -60,7 +60,7 @@ namespace Dawn {
       T * createSceneItemOfType() {
         sceneitemid_t id = this->nextId++;
         auto item = new T(this, id);
-        assertNotNull(item);
+        assertNotNull(item, "Scene::createSceneItemOfType: Failed to create SceneItem (Memory Filled?)");
         this->itemsNotInitialized[id] = item;
         return item;
       }
diff --git a/src/dawn/scene/SceneItem.cpp b/src/dawn/scene/SceneItem.cpp
index 005c7d12..2f1c1463 100644
--- a/src/dawn/scene/SceneItem.cpp
+++ b/src/dawn/scene/SceneItem.cpp
@@ -9,7 +9,7 @@
 using namespace Dawn;
 
 SceneItem::SceneItem(Scene *scene, sceneitemid_t id)  : transform(this) {
-  assertNotNull(scene);
+  assertNotNull(scene, "SceneItem::SceneItem: Scene cannot be null");
   
   this->id = id;
   this->scene = scene;
diff --git a/src/dawn/scene/SceneItem.hpp b/src/dawn/scene/SceneItem.hpp
index 8b544765..71288154 100644
--- a/src/dawn/scene/SceneItem.hpp
+++ b/src/dawn/scene/SceneItem.hpp
@@ -55,7 +55,7 @@ namespace Dawn {
       template<class T>
       T * addComponent() {
         auto component = new T(this);
-        assertNotNull(component);
+        assertNotNull(component, "SceneItem::addComponent: Component could not be created (Memory filled?)");
         this->components.push_back(component);
         return component;
       }
diff --git a/src/dawn/scene/SceneItemComponent.cpp b/src/dawn/scene/SceneItemComponent.cpp
index 66ec0927..1ad45ff7 100644
--- a/src/dawn/scene/SceneItemComponent.cpp
+++ b/src/dawn/scene/SceneItemComponent.cpp
@@ -11,7 +11,7 @@
 using namespace Dawn;
 
 SceneItemComponent::SceneItemComponent(SceneItem *item) {
-  assertNotNull(item);
+  assertNotNull(item, "SceneItemComponent::SceneItemComponent: Item cannot be null");
   this->item = item;
   this->transform = &item->transform;
 }
diff --git a/src/dawn/scene/components/debug/FPSLabelComponent.cpp b/src/dawn/scene/components/debug/FPSLabelComponent.cpp
index d1dfe4db..6eee6f03 100644
--- a/src/dawn/scene/components/debug/FPSLabelComponent.cpp
+++ b/src/dawn/scene/components/debug/FPSLabelComponent.cpp
@@ -18,7 +18,7 @@ void FPSLabelComponent::onStart() {
     if(this->label == nullptr) return;
     std::string strFps = std::to_string((int32_t)(1.0f / delta));
     std::string strTick = std::to_string((int32_t)(delta * 1000.0f));
-    assertUnreachable();// Needs updating to new UI Label
+    assertUnreachable("FPSLabelComponent::onStart: Not yet implemented");// Needs updating to new UI Label
     // label->text = strFps + "FPS (" + strTick + "ms)";
   }, this->item->scene->eventSceneUnpausedUpdate);
 }
\ No newline at end of file
diff --git a/src/dawn/scene/components/display/AnimationController.cpp b/src/dawn/scene/components/display/AnimationController.cpp
index 3bf2a860..5942b67a 100644
--- a/src/dawn/scene/components/display/AnimationController.cpp
+++ b/src/dawn/scene/components/display/AnimationController.cpp
@@ -15,7 +15,7 @@ AnimationController::AnimationController(SceneItem *item) :
 }
 
 void AnimationController::addAnimation(Animation *animation) {
-  assertNotNull(animation);
+  assertNotNull(animation, "AnimationController::addAnimation: Animation cannot be null");
   this->animations.push_back(animation);
 }
 
diff --git a/src/dawn/scene/components/display/PixelPerfectCamera.cpp b/src/dawn/scene/components/display/PixelPerfectCamera.cpp
index ab0ccfb2..b3fd31a3 100644
--- a/src/dawn/scene/components/display/PixelPerfectCamera.cpp
+++ b/src/dawn/scene/components/display/PixelPerfectCamera.cpp
@@ -43,7 +43,7 @@ void PixelPerfectCamera::updateDimensions() {
       break;
     
     default:
-      assertUnreachable();
+      assertUnreachable("PixelPerfectCamera::updateDimensions: Unknown camera type");
   }
 }
 
diff --git a/src/dawn/scene/components/display/SimpleRenderTargetQuad.cpp b/src/dawn/scene/components/display/SimpleRenderTargetQuad.cpp
index c62af65a..a37f2348 100644
--- a/src/dawn/scene/components/display/SimpleRenderTargetQuad.cpp
+++ b/src/dawn/scene/components/display/SimpleRenderTargetQuad.cpp
@@ -20,7 +20,7 @@ std::vector<SceneItemComponent*> SimpleRenderTargetQuad::getDependencies() {
 }
 
 void SimpleRenderTargetQuad::onStart() {
-  assertNotNull(this->meshHost);
+  assertNotNull(this->meshHost, "SimpleRenderTargetQuad::onStart: MeshHost cannot be null");
 
   // Create quad mesh
   this->meshHost->mesh.createBuffers(QUAD_VERTICE_COUNT, QUAD_INDICE_COUNT);
diff --git a/src/dawn/scene/components/display/TiledSprite.cpp b/src/dawn/scene/components/display/TiledSprite.cpp
index a6b73323..4dbf78ed 100644
--- a/src/dawn/scene/components/display/TiledSprite.cpp
+++ b/src/dawn/scene/components/display/TiledSprite.cpp
@@ -81,7 +81,7 @@ void TiledSprite::onStart() {
       }
 
       default:
-        assertUnreachable();
+        assertUnreachable("TiledSprite::onStart: Size type not implemented");
     }
 
     this->meshHost->xy0 = -quadSize;
diff --git a/src/dawn/scene/components/physics/2d/SolidController2D.cpp b/src/dawn/scene/components/physics/2d/SolidController2D.cpp
index 265f8690..81592590 100644
--- a/src/dawn/scene/components/physics/2d/SolidController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/SolidController2D.cpp
@@ -25,8 +25,8 @@ bool_t SolidController2D::getCollidingResult(
   glm::vec2 &entryPoint,
   glm::vec2 &exitPoint
 ) {
-  assertNotNull(this->collider);
-  assertNotNull(movingObject);
+  assertNotNull(this->collider, "SolidController2D::getCollidingResult: Collider cannot be null");
+  assertNotNull(movingObject, "SolidController2D::getCollidingResult: Moving object cannot be null");
   if(movement.x == 0 && movement.y == 0) return false;
 
   auto myPos = physics3Dto2D(movingObject->transform->getWorldPosition());
@@ -35,13 +35,13 @@ bool_t SolidController2D::getCollidingResult(
   switch(movingObject->getColliderType()) {
     case COLLIDER2D_TYPE_BOX: {
       auto box1 = dynamic_cast<BoxCollider*>(movingObject);
-      assertNotNull(box1);
+      assertNotNull(box1, "SolidController2D::getCollidingResult: Moving object is not a BoxCollider");
 
       // Box VS (this)?
       switch(this->collider->getColliderType()) {
         case COLLIDER2D_TYPE_BOX: {
           auto box2 = dynamic_cast<BoxCollider*>(this->collider);
-          assertNotNull(box2);
+          assertNotNull(box2, "SolidController2D::getCollidingResult: Collider is not a BoxCollider");
           auto otherPos = physics3Dto2D(box2->transform->getWorldPosition());
 
           return boxCheckCollision(
@@ -53,17 +53,17 @@ bool_t SolidController2D::getCollidingResult(
         }
         
         default: {
-          assertUnreachable();
+          assertUnreachable("SolidController2D::getCollidingResult: Collider type not implemented");
         }
       }
       break;
     }
 
     default: {
-      assertUnreachable();
+      assertUnreachable("SolidController2D::getCollidingResult: Moving object type not implemented");
     }
   }
   
-  assertUnreachable();
+  assertUnreachable("SolidController2D::getCollidingResult: Should never reach this point");
   return false;
 }
\ No newline at end of file
diff --git a/src/dawn/scene/components/physics/2d/TriggerController2D.cpp b/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
index a0e1a6bb..46da426e 100644
--- a/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
+++ b/src/dawn/scene/components/physics/2d/TriggerController2D.cpp
@@ -18,19 +18,19 @@ std::vector<SceneItemComponent*> TriggerController2D::getDependencies() {
 }
 
 bool_t TriggerController2D::getCollidingResult(Collider2D* movingObject) {
-  assertNotNull(this->collider);
-  assertNotNull(movingObject);
+  assertNotNull(this->collider, "TriggerController2D::getCollidingResult: Collider cannot be null");
+  assertNotNull(movingObject, "TriggerController2D::getCollidingResult: Moving object cannot be null");
 
   switch(movingObject->getColliderType()) {
     case COLLIDER2D_TYPE_BOX: {
       auto box1 = dynamic_cast<BoxCollider*>(movingObject);
-      assertNotNull(box1);
+      assertNotNull(box1, "TriggerController2D::getCollidingResult: Moving object is not a BoxCollider");
 
       // Box VS ?
       switch(collider->getColliderType()) {
         case COLLIDER2D_TYPE_BOX: {
           auto box2 = dynamic_cast<BoxCollider*>(collider);
-          assertNotNull(box2);
+          assertNotNull(box2, "TriggerController2D::getCollidingResult: Collider is not a BoxCollider");
           return boxIsBoxColliding(
             physics3Dto2D(box1->transform->getWorldPosition()), box1->min, box1->max,
             physics3Dto2D(box2->transform->getWorldPosition()), box2->min, box2->max
@@ -38,13 +38,13 @@ bool_t TriggerController2D::getCollidingResult(Collider2D* movingObject) {
         }
         
         default: {
-          assertUnreachable();
+          assertUnreachable("TriggerController2D::getCollidingResult: Collider type not implemented");
         }
       }
     }
     
     default: {
-      assertUnreachable();
+      assertUnreachable("TriggerController2D::getCollidingResult: Moving object type not implemented");
     }
   }
 }
\ No newline at end of file
diff --git a/src/dawn/scene/components/physics/3d/CapsuleCollider.cpp b/src/dawn/scene/components/physics/3d/CapsuleCollider.cpp
index 0e224e02..99be5625 100644
--- a/src/dawn/scene/components/physics/3d/CapsuleCollider.cpp
+++ b/src/dawn/scene/components/physics/3d/CapsuleCollider.cpp
@@ -15,7 +15,7 @@ bool_t CapsuleCollider::performRaycast(
   struct Collider3DRayResult *result,
   struct Ray3D ray
 ) {
-  assertNotNull(result);
+  assertNotNull(result, "CapsuleCollider::performRaycast: Result cannot be null");
 
   return raytestCapsule(
     ray,
diff --git a/src/dawn/scene/components/physics/3d/Collider3D.cpp b/src/dawn/scene/components/physics/3d/Collider3D.cpp
index ee5ce5b0..d36518d1 100644
--- a/src/dawn/scene/components/physics/3d/Collider3D.cpp
+++ b/src/dawn/scene/components/physics/3d/Collider3D.cpp
@@ -15,7 +15,7 @@ bool_t Collider3D::raycast(
   struct Collider3DRayResult *result,
   struct Ray3D ray
 ) {
-  assertNotNull(result);
+  assertNotNull(result, "Collider3D::raycast: Result cannot be null");
   if(!this->performRaycast(result, ray)) return false;
   result->collider = this;
   return true;
diff --git a/src/dawn/scene/components/physics/3d/CubeCollider.cpp b/src/dawn/scene/components/physics/3d/CubeCollider.cpp
index 444277f2..2f2eba87 100644
--- a/src/dawn/scene/components/physics/3d/CubeCollider.cpp
+++ b/src/dawn/scene/components/physics/3d/CubeCollider.cpp
@@ -15,7 +15,7 @@ bool_t CubeCollider::performRaycast(
   struct Collider3DRayResult *result,
   struct Ray3D ray
 ) {
-  assertNotNull(result);
+  assertNotNull(result, "CubeCollider::performRaycast: Result cannot be null");
 
   return Dawn::raytestCube(
     ray,
diff --git a/src/dawn/scene/components/physics/3d/SphereCollider.cpp b/src/dawn/scene/components/physics/3d/SphereCollider.cpp
index 271108dd..4988a034 100644
--- a/src/dawn/scene/components/physics/3d/SphereCollider.cpp
+++ b/src/dawn/scene/components/physics/3d/SphereCollider.cpp
@@ -19,7 +19,7 @@ bool_t SphereCollider::performRaycast(
   struct Collider3DRayResult *result,
   struct Ray3D ray
 ) {
-  assertNotNull(result);
+  assertNotNull(result, "SphereCollider::performRaycast: Result cannot be null");
 
   return raytestSphere(
     ray,
diff --git a/src/dawn/scene/components/ui/UICanvas.cpp b/src/dawn/scene/components/ui/UICanvas.cpp
index c867fbc7..e27c1447 100644
--- a/src/dawn/scene/components/ui/UICanvas.cpp
+++ b/src/dawn/scene/components/ui/UICanvas.cpp
@@ -40,7 +40,7 @@ void UICanvas::rebufferShaderParameters() {
       break;
 
     default:
-      assertUnreachable();
+      assertUnreachable("UICanvas::rebufferShaderParameters: Unknown draw type");
   }
 
   this->shaderBuffer.buffer(&data);
diff --git a/src/dawn/scene/components/ui/UIComponent.cpp b/src/dawn/scene/components/ui/UIComponent.cpp
index d6892a08..2bbe0451 100644
--- a/src/dawn/scene/components/ui/UIComponent.cpp
+++ b/src/dawn/scene/components/ui/UIComponent.cpp
@@ -25,7 +25,7 @@ UIComponentDimensional * UIComponent::getParentDimensional() {
   auto parent = this->transform->getParent();
   if(parent == nullptr) return nullptr;
   auto dimensional = parent->item->getComponent<UIComponentDimensional>();
-  assertNotNull(dimensional);
+  assertNotNull(dimensional, "UIComponent::getParentDimensional: Parent must have a UIComponentDimensional");
   return dimensional;
 }
 
@@ -36,7 +36,7 @@ void UIComponent::updateAlignment() {
   auto dimensional = this->getParentDimensional();
   auto translate = this->transform->getLocalPosition();
 
-  assertNotNull(dimensional);
+  assertNotNull(dimensional, "UIComponent::updateAlignment: Parent must have a UIComponentDimensional");
 
   parentInnerWidth = dimensional->getContentWidth();
   parentInnerHeight = dimensional->getContentHeight();
@@ -89,8 +89,8 @@ void UIComponent::calculateDimensions(
   float_t innerSize,
   glm::vec2 alignment
 ) {
-  assertNotNull(position);
-  assertNotNull(size);
+  assertNotNull(position, "UIComponent::calculateDimensions: Position cannot be null");
+  assertNotNull(size, "UIComponent::calculateDimensions: Size cannot be null");
 
   switch(align) {
     case UI_COMPONENT_ALIGN_STRETCH: {
@@ -157,7 +157,7 @@ void UIComponent::calculateDimensions(
     }
     
     default:
-      assertUnreachable();
+      assertUnreachable("UIComponent::calculateDimensions: Unknown alignment");
       break;
   }
 }
@@ -170,7 +170,7 @@ UICanvas * UIComponent::getCanvas() {
     if(canvas != nullptr) return canvas;
     parent = parent->getParent();
   }
-  assertUnreachable();
+  assertUnreachable("UIComponent::getCanvas: No canvas found");
   return nullptr;
 }
 
diff --git a/src/dawn/scene/components/ui/menu/UISimpleMenu.cpp b/src/dawn/scene/components/ui/menu/UISimpleMenu.cpp
index 71bebe97..0b19890d 100644
--- a/src/dawn/scene/components/ui/menu/UISimpleMenu.cpp
+++ b/src/dawn/scene/components/ui/menu/UISimpleMenu.cpp
@@ -24,8 +24,8 @@ std::vector<SceneItemComponent*> UISimpleMenu::getDependencies() {
 void UISimpleMenu::onStart() {
   if(canvas == nullptr) canvas = getScene()->findComponent<UICanvas>();
 
-  assertNotNull(this->menu);
-  assertNotNull(this->canvas);
+  assertNotNull(this->menu, "UISimpleMenu::onStart: Menu cannot be null");
+  assertNotNull(this->canvas, "UISimpleMenu::onStart: Canvas cannot be null");
   menuItems = this->item->findChildren<UISimpleMenuItem>();
 
   auto updateSimpleMenuPos = [&](int32_t x, int32_t y) {
@@ -59,7 +59,7 @@ void UISimpleMenu::onStart() {
   }, menu->eventItemSelected);
 
   useEvent([&](float_t d){
-    assertNotNull(canvas->camera);
+    assertNotNull(canvas->camera, "UISimpleMenu::onStart: Camera cannot be null");
     if(!this->menu->active) return;
 
     // Mouse in screen space.
@@ -121,7 +121,7 @@ void UISimpleMenu::onStart() {
       }
       
       default: {
-        assertUnreachable();
+        assertUnreachable("UISimpleMenu::onStart: Draw type not implemented");
       }
     }
   }, getScene()->eventSceneUnpausedUpdate);
diff --git a/src/dawn/scene/components/ui/text/UILabel.cpp b/src/dawn/scene/components/ui/text/UILabel.cpp
index d32827e8..4e7261ad 100644
--- a/src/dawn/scene/components/ui/text/UILabel.cpp
+++ b/src/dawn/scene/components/ui/text/UILabel.cpp
@@ -72,7 +72,7 @@ std::vector<struct ShaderPassItem> UILabel::getUIRenderPasses() {
         break;
 
       default:
-        assertUnreachable();
+        assertUnreachable("UILabel::getUIRenderPasses: Texture slot not implemented");
     }
 
     item.textureSlots[it->second] = &it->first->texture;
@@ -119,7 +119,7 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
     return;
   }
 
-  assertTrue(newTexts.size() <= FONT_SHADER_PARTS_MAX);
+  assertTrue(newTexts.size() <= FONT_SHADER_PARTS_MAX, "UILabel::rebufferQuads: Too many parts (not supported)");
 
   int32_t nextTexture = 0;
   glm::vec2 position(0, 0);
@@ -161,17 +161,17 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
     realText.style = text.style;
 
     // Lock the font
-    assertNotNull(text.style.font);
+    assertNotNull(text.style.font, "UILabel::rebufferQuads: Font cannot be null");
     realText.lockId = text.style.font->lock(TrueTypeFaceTextureStyle{
       text.style.size,
       text.style.style
     });
-    assertTrue(realText.lockId != -1);
+    assertTrue(realText.lockId != -1, "UILabel::rebufferQuads: Failed to lock font");
     realText.texture = text.style.font->getTexture(realText.lockId);
 
     // Map texture
     if(textureMap.find(realText.texture) == textureMap.end()) {
-      assertTrue(nextTexture < FONT_SHADER_TEXTURE_MAX);
+      assertTrue(nextTexture < FONT_SHADER_TEXTURE_MAX, "UILabel::rebufferQuads: Too many textures (not supported)");
       textureMap[realText.texture] = nextTexture++;
     }
 
@@ -252,10 +252,10 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
       }
 
       // Validate characters
-      assertTrue(ch >= TRUE_TYPE_CHAR_BEGIN && ch < TRUE_TYPE_CHAR_END);
-      assertTrue(ch != '\r');
-      assertTrue(ch != '\t');
-      assertTrue(ch != '\n');
+      assertTrue(ch >= TRUE_TYPE_CHAR_BEGIN && ch < TRUE_TYPE_CHAR_END, "UILabel::rebufferQuads: Character out of range");
+      assertTrue(ch != '\r', "UILabel::rebufferQuads: Character cannot be a carriage return");
+      assertTrue(ch != '\t', "UILabel::rebufferQuads: Character cannot be a tab");
+      assertTrue(ch != '\n', "UILabel::rebufferQuads: Character cannot be a newline");
 
       // Get font data.
       auto charInfo = realText.texture->getCharacterData(ch);
@@ -357,7 +357,7 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
     );
 
     if(hasDecorations) {
-      assertTrue(vertices.size() == decorations.size());
+      assertTrue(vertices.size() == decorations.size(), "UILabel::rebufferQuads: Decoration count mismatch");
       this->meshDecorations.createBuffers(
         QUAD_VERTICE_COUNT * decorations.size(),
         QUAD_INDICE_COUNT * decorations.size()
@@ -408,8 +408,8 @@ void UILabel::rebufferQuads(const std::vector<struct UILabelText> newTexts) {
   // Finally, release the old locks
   itText = textsBuffered.begin();
   while(itText != textsBuffered.end()) {
-    assertTrue(itText->lockId != -1);
-    assertNotNull(itText->style.font);
+    assertTrue(itText->lockId != -1, "UILabel::rebufferQuads: Lock ID cannot be -1");
+    assertNotNull(itText->style.font, "UILabel::rebufferQuads: Font cannot be null");
     itText->style.font->unlock(itText->lockId);
     ++itText;
   }
diff --git a/src/dawn/scene/components/ui/text/UIRichTextLabel.cpp b/src/dawn/scene/components/ui/text/UIRichTextLabel.cpp
index 275d9819..02de8155 100644
--- a/src/dawn/scene/components/ui/text/UIRichTextLabel.cpp
+++ b/src/dawn/scene/components/ui/text/UIRichTextLabel.cpp
@@ -39,7 +39,7 @@ void UIRichTextLabel::onStart() {
           bufferTexts.push_back(text);
         } else if(child.nodeType == XML_NODE_TYPE_ELEMENT) {
           auto node = child.child;
-          assertTrue(node->node == "font");
+          assertTrue(node->node == "font", "UIRichTextLabel::onStart: Unknown node type '" + node->node + "'");
 
           struct UILabelStyle style;
           if(node->attributes.contains("font")) {
diff --git a/src/dawn/state/StateOwner.hpp b/src/dawn/state/StateOwner.hpp
index 281873c2..f661ccf5 100644
--- a/src/dawn/state/StateOwner.hpp
+++ b/src/dawn/state/StateOwner.hpp
@@ -132,7 +132,7 @@ namespace Dawn {
           // all the listeners on StateProperty<> that belong to this StateOwner
           // I need to keep track of what events I've subbed to, consuming more
           // memory, and I don't know if I actually need to do this or not.
-          assertTrue(property.owner == this);
+          assertTrue(property.owner == this, "StateOwner::useEffect: Property owner must be this StateOwner");
         }
         property._effectListners.push_back(fn);
         return fn;
@@ -156,7 +156,7 @@ namespace Dawn {
           if(property->owner == nullptr) {
             property->owner = this;
           } else {
-            assertTrue(property->owner == this);
+            assertTrue(property->owner == this, "StateOwner::useEffect: Property owner must be this StateOwner");
           }
           property->_effectListners.push_back(fn);
           ++itProp;
@@ -177,7 +177,11 @@ namespace Dawn {
         const std::function<std::function<void()>()> &fn,
         IStateProperty &property
       ) {
-        if(property.owner == nullptr) { property.owner = this; } else { assertTrue(property.owner == this); }
+        if(property.owner == nullptr) {
+          property.owner = this;
+        } else {
+          assertTrue(property.owner == this, "StateOwner::useEffectWithTeardown: Property owner must be this StateOwner");
+        }
         property._effectListnersWithTeardown.push_back(fn);
 
         return std::bind([&](
diff --git a/src/dawn/state/StateProvider.hpp b/src/dawn/state/StateProvider.hpp
index 6da08092..bbc7e6ff 100644
--- a/src/dawn/state/StateProvider.hpp
+++ b/src/dawn/state/StateProvider.hpp
@@ -40,7 +40,7 @@ namespace Dawn {
 
         auto unsub = std::bind([&](struct StateListener<D, A...> listener) {
           // Not yet implemented
-          assertUnreachable();
+          assertUnreachable("StateProviderSet::addEffect: Not yet implemented");
         }, l);
 
         context->_stateProviderListeners.push_back(unsub);
diff --git a/src/dawnglfw/host/DawnGLFWHost.cpp b/src/dawnglfw/host/DawnGLFWHost.cpp
index 6be1660b..cc4e0774 100644
--- a/src/dawnglfw/host/DawnGLFWHost.cpp
+++ b/src/dawnglfw/host/DawnGLFWHost.cpp
@@ -207,7 +207,7 @@ void glfwOnCursor(GLFWwindow* window, double xpos, double ypos) {
 
 void glfwOnMouseButton(GLFWwindow* window, int button, int action, int mods) {
   if(DAWN_HOST == nullptr) return;
-  assertTrue(window == DAWN_HOST->data->window);
+  assertTrue(window == DAWN_HOST->data->window, "glfwOnMouseButton: Window mismatch");
 
   float_t value = action == GLFW_PRESS ? 1 : 0;
   DAWN_HOST->game->inputManager.rawInputValues[INPUT_MANAGER_AXIS_MOUSE_0 + button] = value;
diff --git a/src/dawnopengl/display/Texture.cpp b/src/dawnopengl/display/Texture.cpp
index 40a7fc2a..d4f1124e 100644
--- a/src/dawnopengl/display/Texture.cpp
+++ b/src/dawnopengl/display/Texture.cpp
@@ -18,7 +18,7 @@ Texture::Texture() : ITexture() {
 }
 
 void Texture::bind(textureslot_t slot) {
-  assertTrue(this->id != -1);
+  assertTrue(this->id != -1, "Texture::bind: Texture is not ready!");
   glActiveTexture(GL_TEXTURE0 + slot);
   glBindTexture(GL_TEXTURE_2D, this->id);
 
@@ -108,7 +108,7 @@ void Texture::updateTextureProperties() {
         break;
 
       default:
-        assertUnreachable();
+        assertUnreachable("Texture::updateTextureProperties: Unknown wrap mode!");
     }
   };
 
@@ -156,7 +156,7 @@ void Texture::updateTextureProperties() {
       }
 
       default: {
-        assertUnreachable();
+        assertUnreachable("Texture::updateTextureProperties: Unknown filter mode!");
       }
     }
   };
@@ -166,7 +166,7 @@ void Texture::updateTextureProperties() {
 }
 
 void Texture::bufferRaw(void *data) {
-  assertTrue(this->isReady());
+  assertTrue(this->isReady(), "Texture::bufferRaw: Texture is not ready!");
 
   GLenum format;
   switch(this->format) {
@@ -187,7 +187,7 @@ void Texture::bufferRaw(void *data) {
       break;
     
     default:
-      assertUnreachable();
+      assertUnreachable("Texture::bufferRaw: Unknown texture format!");
   }
 
   GLenum dataFormat;
@@ -201,7 +201,7 @@ void Texture::bufferRaw(void *data) {
       break;
 
     default:
-      assertUnreachable();
+      assertUnreachable("Texture::bufferRaw: Unknown texture data format!");
   }
 
   glBindTexture(GL_TEXTURE_2D, this->id);
@@ -215,18 +215,18 @@ void Texture::bufferRaw(void *data) {
 }
 
 void Texture::buffer(struct ColorU8 pixels[]) {
-  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE);
+  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE, "Texture::buffer: Texture data format must be unsigned byte!");
   this->bufferRaw((void*)pixels);
 }
 
 void Texture::buffer(struct Color pixels[]) {
-  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_FLOAT);
-  assertTrue(this->format == TEXTURE_FORMAT_RGBA);
+  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_FLOAT, "Texture::buffer: Texture data format must be float!");
+  assertTrue(this->format == TEXTURE_FORMAT_RGBA, "Texture::buffer: Texture format must be RGBA!");
   this->bufferRaw((void*)pixels);
 }
 
 void Texture::buffer(uint8_t pixels[]) {
-  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE);
+  assertTrue(this->dataFormat == TEXTURE_DATA_FORMAT_UNSIGNED_BYTE, "Texture::buffer: Texture data format must be unsigned byte!");
   this->bufferRaw((void*)pixels);
 }
 
diff --git a/src/dawnopengl/display/TextureRenderTarget.cpp b/src/dawnopengl/display/TextureRenderTarget.cpp
index a535011a..563130a3 100644
--- a/src/dawnopengl/display/TextureRenderTarget.cpp
+++ b/src/dawnopengl/display/TextureRenderTarget.cpp
@@ -16,8 +16,8 @@ Texture * TextureRenderTarget::getTexture() {
 }
 
 void TextureRenderTarget::setSize(float_t width, float_t height) {
-  assertTrue(width > 0);
-  assertTrue(height > 0);
+  assertTrue(width > 0, "TextureRenderTarget::setSize: Width must be greater than 0!");
+  assertTrue(height > 0, "TextureRenderTarget::setSize: Height must be greater than 0!");
 
   if(width == this->getWidth() && height == this->getHeight()) return;
 
@@ -50,7 +50,7 @@ void TextureRenderTarget::setSize(float_t width, float_t height) {
 
   // Validate things went correct.
   if(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
-    assertUnreachable();
+    assertUnreachable("TextureRenderTarget::setSize: Framebuffer is not complete!");
   }
 }
 
diff --git a/src/dawnopengl/display/mesh/Mesh.cpp b/src/dawnopengl/display/mesh/Mesh.cpp
index e2fd41d9..6f1566b4 100644
--- a/src/dawnopengl/display/mesh/Mesh.cpp
+++ b/src/dawnopengl/display/mesh/Mesh.cpp
@@ -73,7 +73,11 @@ void Mesh::disposeBuffers() {
 }
 
 void Mesh::bufferPositions(int32_t pos, glm::vec3 *positions, int32_t len) {
-  assertNotNull(positions);
+  assertNotNull(positions, "Mesh::bufferPositions: Positions cannot be null");
+  assertTrue(pos >= 0 && pos < this->verticeCount, "Mesh::bufferPositions: Position must be within range");
+  assertTrue(pos+len <= this->verticeCount, "Mesh::bufferPositions: Position + Length must be within range");
+  assertTrue(len > 0, "Mesh::bufferPositions: Length must be greater than zero");
+
   glBindBuffer(GL_ARRAY_BUFFER, this->vertexBuffer);
   glBufferSubData(
     GL_ARRAY_BUFFER,
@@ -84,7 +88,10 @@ void Mesh::bufferPositions(int32_t pos, glm::vec3 *positions, int32_t len) {
 }
 
 void Mesh::bufferCoordinates(int32_t pos, glm::vec2 *coordinates, int32_t len) {
-  assertNotNull(coordinates);
+  assertNotNull(coordinates, "Mesh::bufferCoordinates: Coordinates cannot be null");
+  assertTrue(pos >= 0 && pos < this->verticeCount, "Mesh::bufferCoordinates: Position must be within range");
+  assertTrue(pos+len <= this->verticeCount, "Mesh::bufferCoordinates: Position + Length must be within range");
+  assertTrue(len > 0, "Mesh::bufferCoordinates: Length must be greater than zero");
 
   auto offsetCoordinates = (
     (sizeof(glm::vec3) * this->verticeCount) +
@@ -101,7 +108,11 @@ void Mesh::bufferCoordinates(int32_t pos, glm::vec2 *coordinates, int32_t len) {
 }
 
 void Mesh::bufferIndices(int32_t pos, meshindice_t *indices, int32_t len) {
-  assertNotNull(indices);
+  assertNotNull(indices, "Mesh::bufferIndices: Indices cannot be null");
+  assertTrue(pos >= 0 && pos < this->indiceCount, "Mesh::bufferIndices: Position must be within range");
+  assertTrue(pos+len <= this->indiceCount, "Mesh::bufferIndices: Position + Length must be within range");
+  assertTrue(len > 0, "Mesh::bufferIndices: Length must be greater than zero");
+
   glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, this->indexBuffer);
   glBufferSubData(
     GL_ELEMENT_ARRAY_BUFFER,
diff --git a/src/dawnopengl/display/shader/ShaderParameterBuffer.hpp b/src/dawnopengl/display/shader/ShaderParameterBuffer.hpp
index 1e35066b..05a1aca2 100644
--- a/src/dawnopengl/display/shader/ShaderParameterBuffer.hpp
+++ b/src/dawnopengl/display/shader/ShaderParameterBuffer.hpp
@@ -27,7 +27,7 @@ namespace Dawn {
 
     public:
       void init() {
-        assertTrue(this->id == -1);
+        assertTrue(this->id == -1, "ShaderParameterBuffer::init: ShaderParameterBuffer is already initialized!");
         this->size = sizeof(T);
         glGenBuffers(1, &this->id);
 
@@ -50,7 +50,7 @@ namespace Dawn {
       }
 
       void bind(shaderbufferslot_t location) override {
-        assertTrue(this->isReady());
+        assertTrue(this->isReady(), "ShaderParameterBuffer::bind: ShaderParameterBuffer is not ready!");
         glBindBuffer(GL_UNIFORM_BUFFER, this->id);
         glBindBufferBase(GL_UNIFORM_BUFFER, location, this->id); 
       }
@@ -73,7 +73,7 @@ namespace Dawn {
        * @param length Length of the data to buffer.
        */
       void bufferRaw(void *data, size_t start, size_t length) {
-        assertTrue(this->isReady());
+        assertTrue(this->isReady(), "ShaderParameterBuffer::bufferRaw: ShaderParameterBuffer is not ready!");
         glBindBuffer(GL_UNIFORM_BUFFER, this->id);
         glBufferSubData(GL_UNIFORM_BUFFER, start, length, (void*)((size_t)data + start));
       }
diff --git a/src/dawnopengl/scene/components/display/material/SimpleBillboardedMaterial.cpp b/src/dawnopengl/scene/components/display/material/SimpleBillboardedMaterial.cpp
index 58d6a31f..3e58da29 100644
--- a/src/dawnopengl/scene/components/display/material/SimpleBillboardedMaterial.cpp
+++ b/src/dawnopengl/scene/components/display/material/SimpleBillboardedMaterial.cpp
@@ -26,9 +26,9 @@ std::vector<struct ShaderPassItem> SimpleBillboardedMaterial::getRenderPasses(IR
   auto mesh = this->item->getComponent<MeshRenderer>();
   auto shader = this->getGame()->renderManager.getShaderManager()->getShader<SimpleBillboardedShader>(this->shaderLock);
 
-  assertNotNull(mesh);
-  assertNotNull(mesh->mesh);
-  assertNotNull(shader);
+  assertNotNull(mesh, "SimpleBillboardedMaterial::getRenderPasses: Mesh cannot be null");
+  assertNotNull(mesh->mesh, "SimpleBillboardedMaterial::getRenderPasses: Mesh cannot be null");
+  assertNotNull(shader, "SimpleBillboardedMaterial::getRenderPasses: Shader cannot be null");
 
   struct ShaderPassItem onlyPass;
   onlyPass.mesh = mesh->mesh;
diff --git a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.cpp b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.cpp
index de3eb4d9..c2a3279b 100644
--- a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.cpp
+++ b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.cpp
@@ -25,9 +25,9 @@ std::vector<struct ShaderPassItem> SimpleTexturedMaterial::getRenderPasses(IRend
   auto mesh = this->item->getComponent<MeshRenderer>();
   auto shader = this->getGame()->renderManager.getShaderManager()->getShader<SimpleTexturedShader>(this->shaderLock);
 
-  assertNotNull(mesh);
-  assertNotNull(mesh->mesh);
-  assertNotNull(shader);
+  assertNotNull(mesh, "SimpleTexturedMaterial::getRenderPasses: Mesh cannot be null");
+  assertNotNull(mesh->mesh, "SimpleTexturedMaterial::getRenderPasses: Mesh cannot be null");
+  assertNotNull(shader, "SimpleTexturedMaterial::getRenderPasses: Shader cannot be null");
 
   struct ShaderPassItem onlyPass;
   onlyPass.mesh = mesh->mesh;
diff --git a/src/dawnshared/assert/assert.cpp b/src/dawnshared/assert/assert.cpp
index cd060444..36bce1e4 100644
--- a/src/dawnshared/assert/assert.cpp
+++ b/src/dawnshared/assert/assert.cpp
@@ -10,31 +10,61 @@
 #if ASSERTS_ENABLED == 0
 
 #elif ASSERTS_ENABLED == 1
-  void assertTrue(bool_t x) {
+  void assertTrue(bool_t x, const char message[]) {
     if(x != true) {
-      throw "Assertion Failed";
+      std::cout << message << std::endl;
+      throw message;
       free(0);
     }
     assert(x == true);
   }
+
+  void assertTrue(bool_t x, std::string message) {
+    assertTrue(x, message.c_str());
+  }
   
-  void assertFalse(bool_t x) {
-    assertTrue(!x);
+
+  void assertFalse(bool_t x, const char message[]) {
+    assertTrue(!x, message);
   }
 
-  void assertUnreachable() {
-    assertTrue(false);
+  void assertFalse(bool_t x, std::string message) {
+    assertFalse(x, message.c_str());
   }
 
-  void assertNotNull(void *pointer) {
-    assertTrue(pointer != nullptr && pointer != NULL);
+
+  void assertUnreachable(const char message[]) {
+    assertTrue(false, message);
   }
 
-  void assertNull(void *pointer) {
-    assertTrue(pointer == NULL || pointer == nullptr);
+  void assertUnreachable(std::string message) {
+    assertUnreachable(message.c_str());
   }
 
-  void assertDeprecated() {
-    assertUnreachable();
+
+  void assertNotNull(void *pointer, const char message[]) {
+    assertTrue(pointer != nullptr && pointer != NULL, message);
+  }
+
+  void assertNotNull(void *pointer, std::string message) {
+    assertNotNull(pointer, message.c_str());
+  }
+
+
+  void assertNull(void *pointer, const char message[]) {
+    assertTrue(pointer == NULL || pointer == nullptr, message);
+  }
+
+  void assertNull(void *pointer, std::string message) {
+    assertNull(pointer, message.c_str());
+  }
+
+
+  void assertDeprecated(const char message[]) {
+    assertUnreachable(message);
+  }
+
+  void assertDeprecated(std::string message) {
+    assertDeprecated(message.c_str());
   }
 #endif
\ No newline at end of file
diff --git a/src/dawnshared/assert/assert.hpp b/src/dawnshared/assert/assert.hpp
index d8592812..3ad381d0 100644
--- a/src/dawnshared/assert/assert.hpp
+++ b/src/dawnshared/assert/assert.hpp
@@ -19,47 +19,72 @@ static inline void assertTrue(bool_t x) {}
   /**
    * Assert a given value to be true.
    * @param x Value to assert as true.
+   * @param message Message to throw against assertion failure.
    */
-  void assertTrue(bool_t x);
+  void assertTrue(bool_t x, const char message[]);
+  void assertTrue(bool_t x, std::string message);
 
   /**
    * Asserts a given statement to be false.
    * @param x Value to assert as false.
+   * @param message Message to throw against assertion failure.
    */
-  void assertFalse(bool_t x);
+  void assertFalse(bool_t x, const char message[]);
+  void assertFalse(bool_t x, std::string message);
 
   /**
    * Asserts that a given line of code is unreachable. Essentially a forced
    * assertion failure, good for "edge cases"
+   * @param message Message to throw against assertion failure.
    */
-  void assertUnreachable();
+  void assertUnreachable(const char message[]);
+  void assertUnreachable(std::string message);
 
   /**
    * Assert a given pointer to not point to a null pointer.
    * @param pointer Pointer to assert is not a null pointer.
+   * @param message Message to throw against assertion failure.
    */
-  void assertNotNull(void *pointer);
+  void assertNotNull(void *pointer, const char message[]);
+  void assertNotNull(void *pointer, std::string message);
 
   /**
    * Asserts a given pointer to be a nullptr.
    * @param pointer Pointer to assert is nullptr.
+   * @param message Message to throw against assertion failure.
    */
-  void assertNull(void *pointer);
+  void assertNull(void *pointer, const char message[]);
+  void assertNull(void *pointer, std::string message);
 
   /**
    * Asserts a function as being deprecated.
+   * @param message Message to throw against assertion failure.
    */
-  void assertDeprecated();
+  void assertDeprecated(const char message[]);
+  void assertDeprecated(std::string message);
 
   /**
    * Asserts that a given map has a key.
    * 
    * @param map Map to check.
    * @param key Key to try and assert exists.
+   * @param message Message to throw against assertion failure.
    */
   template<typename K, typename V>
-  void assertMapHasKey(std::map<K,V> map, K key) {
-    assertTrue(map.find(key) != map.end());
+  void assertMapHasKey(std::map<K,V> map, K key, const char message[]) {
+    assertTrue(map.find(key) != map.end(), message);
+  }
+
+  /**
+   * Asserts that a given map has a key.
+   * 
+   * @param map Map to check.
+   * @param key Key to try and assert exists.
+   * @param message Message to throw against assertion failure.
+   */
+  template<typename K, typename V>
+  void assertMapHasKey(std::map<K,V> map, K key, std::string message) {
+    assertMapHasKey(map, key, message.c_str());
   }
 #else
 
diff --git a/src/dawnshared/display/Color.cpp b/src/dawnshared/display/Color.cpp
index 75947ef7..747e0c3e 100644
--- a/src/dawnshared/display/Color.cpp
+++ b/src/dawnshared/display/Color.cpp
@@ -35,6 +35,6 @@ struct Color Color::fromString(std::string str) {
   }
 
   // TODO: Parse other kinds of colors
-  assertUnreachable();
+  assertUnreachable("Failed to find a color match for " + str);
   return {};
 }
\ No newline at end of file
diff --git a/src/dawnshared/util/UsageLock.cpp b/src/dawnshared/util/UsageLock.cpp
index 088f80d5..81181a7e 100644
--- a/src/dawnshared/util/UsageLock.cpp
+++ b/src/dawnshared/util/UsageLock.cpp
@@ -11,7 +11,7 @@ UsageLock::UsageLock() : UsageLock(&this->internalPool) {
 }
 
 UsageLock::UsageLock(usagelockid_t *lockPool) {
-  assertNotNull(lockPool);
+  assertNotNull(lockPool, "Lock pool cannot be null");
   this->pool = lockPool;
   this->onEmpty = []() {};
   this->onFirstLock = []() {};
diff --git a/src/dawnshared/util/Xml.cpp b/src/dawnshared/util/Xml.cpp
index ba89006d..0aac2116 100644
--- a/src/dawnshared/util/Xml.cpp
+++ b/src/dawnshared/util/Xml.cpp
@@ -199,7 +199,7 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
           while(c = data[i++]) {
             xml->innerXml += c;
             if(c == ';') break;
-            if(c == '<') assertUnreachable();//Invalid XML
+            if(c == '<') assertUnreachable("Error decrypting XML/HTML Special Char, encountered end of Node?");//Invalid XML
             sc += c;
           }
 
@@ -221,8 +221,7 @@ void Xml::load(Xml *xml, std::string data, size_t *j) {
               int code = std::stoi(sc.substr(1));
               buffer += (char)code;
             } else {
-              std::cout << "Unknown Special character: " << sc << std::endl;
-              assertUnreachable();
+              assertUnreachable("Unknown Special character: " + sc);
             }
           }
         } else {
diff --git a/src/dawnshared/util/array.hpp b/src/dawnshared/util/array.hpp
index 8b53ec7d..fd700cc2 100644
--- a/src/dawnshared/util/array.hpp
+++ b/src/dawnshared/util/array.hpp
@@ -16,8 +16,8 @@ namespace Dawn {
    */
   template<typename T>
   void vectorAppend(std::vector<T> *list, std::vector<T> *append) {
-    assertNotNull(list);
-    assertNotNull(append);
+    assertNotNull(list, "vectorAppend: list cannot be null");
+    assertNotNull(append, "vectorAppend: append cannot be null");
 
     auto it = append->begin();
     while(it != append->end()) {
@@ -34,7 +34,7 @@ namespace Dawn {
    */
   template<typename T>
   void vectorAppend(std::vector<T> *list, std::vector<T> append) {
-    assertNotNull(list);
+    assertNotNull(list, "vectorAppend: list cannot be null");
 
     auto it = append.begin();
     while(it != append.end()) {
diff --git a/src/dawnshared/util/memory.hpp b/src/dawnshared/util/memory.hpp
index 041ccd12..8cf4af42 100644
--- a/src/dawnshared/util/memory.hpp
+++ b/src/dawnshared/util/memory.hpp
@@ -21,12 +21,12 @@
  * @return Pointer to the space in memory to use.
  */
 static inline void * memoryAllocate(const size_t size) {
-  assertTrue(size > 0);
+  assertTrue(size > 0, "memoryAllocate: size must be greater than 0");
   #if DAWN_DEBUG_BUILD
     dawnAllocatedItemCount++;
   #endif
   auto x = (void *)malloc(size);
-  assertNotNull(x);
+  assertNotNull(x, "memoryAllocate: Failed to allocate memory");
   return x;
 }
 
@@ -37,12 +37,12 @@ static inline void * memoryAllocate(const size_t size) {
  * @return Pointer to the space in memory to use.
  */
 static inline void * memoryFillWithZero(const size_t size) {
-  assertTrue(size > 0);
+  assertTrue(size > 0, "memoryFillWithZero: size must be greater than 0");
   #if DAWN_DEBUG_BUILD
     dawnAllocatedItemCount++;
   #endif
-  auto x =(void *)calloc(1, size);
-  assertNotNull(x);
+  auto x = (void*)calloc(1, size);
+  assertNotNull(x, "memoryFillWithZero: Failed to allocate memory");
   return x;
 }
 
@@ -52,7 +52,7 @@ static inline void * memoryFillWithZero(const size_t size) {
  * @param pointer Pointer in memory to free.
  */
 static inline void memoryFree(void *pointer) {
-  assertNotNull(pointer);
+  assertNotNull(pointer, "memoryFree: pointer must not be null");
   #if DAWN_DEBUG_BUILD
     dawnAllocatedItemCount--;
   #endif
@@ -71,10 +71,10 @@ static inline void memoryCopy(
   void *destination,
   size_t size
 ) {
-  assertNotNull(source);
-  assertNotNull(destination);
-  assertTrue(destination != source);
-  assertTrue(size > 0);
+  assertNotNull(source, "memoryCopy: source must not be null");
+  assertNotNull(destination, "memoryCopy: destination must not be null");
+  assertTrue(destination != source, "memoryCopy: destination must not be source");
+  assertTrue(size > 0, "memoryCopy: size must be greater than 0");
   memcpy(destination, source, size);
 }
 
@@ -91,8 +91,8 @@ static inline int32_t memoryCompare(
   const void *right,
   const size_t size
 ) {
-  assertTrue(left != right);
-  assertTrue(size > 0);
+  assertTrue(left != right, "memoryCompare: left must not be right");
+  assertTrue(size > 0, "memoryCompare: size must be greater than 0");
   return memcmp(left, right, size);
 }
 
@@ -108,8 +108,8 @@ static inline void memorySet(
   uint8_t data,
   size_t length
 ) {
-  assertNotNull(dest);
-  assertTrue(length > 0);
+  assertNotNull(dest, "memorySet: dest must not be null");
+  assertTrue(length > 0, "memorySet: length must be greater than 0");
   memset(dest, data, length);
 }
 
diff --git a/src/dawnshared/util/string.hpp b/src/dawnshared/util/string.hpp
index 32b76023..51b0cc47 100644
--- a/src/dawnshared/util/string.hpp
+++ b/src/dawnshared/util/string.hpp
@@ -23,12 +23,12 @@ static inline char * stringFindNext(
 ) {
   char *p;
 
-  assertNotNull(haystack);
-  assertTrue(limit > 0);
+  assertNotNull(haystack, "String find haystack cannot be null");
+  assertTrue(limit > 0, "String find limit must be greater than 0");
 
   for(p = haystack; (size_t)(p - haystack) < limit; p++) {
     if(*p == needle) return p;
-    assertFalse(*p == '\0');// We don't allow you to have a limit > strlen
+    assertFalse(*p == '\0', "String find limit reached");
   }
 
   return NULL;
diff --git a/src/dawntools/util/File.cpp b/src/dawntools/util/File.cpp
index f35938cc..3bd4f70b 100644
--- a/src/dawntools/util/File.cpp
+++ b/src/dawntools/util/File.cpp
@@ -54,7 +54,7 @@ File::File(std::string filename) {
 }
 
 bool_t File::open(enum FileMode mode) {
-  assertNull(this->file);
+  assertNull(this->file, "File is already open");
 
   this->mode = mode;
   this->file = fopen(
@@ -93,7 +93,7 @@ bool_t File::exists() {
 }
 
 void File::close() {
-  assertNotNull(this->file);
+  assertNotNull(this->file, "File::close: File is not open");
   fclose(this->file);
   this->file = nullptr;
 }
@@ -104,12 +104,12 @@ bool_t File::mkdirp() {
 }
 
 bool_t File::readString(std::string *out) {
-  assertNotNull(out);
+  assertNotNull(out, "File::readString: Out cannot be null");
 
   if(!this->isOpen()) {
     if(!this->open(FILE_MODE_READ)) return false;
   }
-  assertTrue(this->mode == FILE_MODE_READ);
+  assertTrue(this->mode == FILE_MODE_READ, "File::readString: File must be open in read mode");
   out->clear();
 
   size_t i = 0;
@@ -127,13 +127,13 @@ bool_t File::readString(std::string *out) {
 }
 
 size_t File::readAhead(char *buffer, size_t max, char needle) {
-  assertNotNull(buffer);
-  assertTrue(max > 0);
+  assertNotNull(buffer, "File::readAhead: Buffer cannot be null");
+  assertTrue(max > 0, "File::readAhead: Max must be greater than 0");
 
   if(!this->isOpen()) {
     if(!this->open(FILE_MODE_READ)) return 0;
   }
-  assertTrue(this->mode == FILE_MODE_READ);
+  assertTrue(this->mode == FILE_MODE_READ, "File::readAhead: File must be open in read mode");
 
   // Buffer
   size_t pos = ftell(this->file);
@@ -170,7 +170,7 @@ size_t File::readToBuffer(char **buffer) {
   if(!this->isOpen()) {
     if(!this->open(FILE_MODE_READ)) return 0;
   }
-  assertTrue(this->mode == FILE_MODE_READ);
+  assertTrue(this->mode == FILE_MODE_READ, "File::readToBuffer: File must be open in read mode");
 
   if((*buffer) == nullptr) *buffer = (char*)malloc(this->length);
   fseek(this->file, 0, SEEK_SET);
@@ -179,32 +179,32 @@ size_t File::readToBuffer(char **buffer) {
 }
 
 size_t File::readRaw(char *buffer, size_t max) {
-  assertNotNull(buffer);
-  assertTrue(max > 0);
+  assertNotNull(buffer, "File::readRaw: Buffer cannot be null");
+  assertTrue(max > 0, "File::readRaw: Max must be greater than 0");
   if(!this->isOpen()) {
     if(!this->open(FILE_MODE_READ)) return 0;
   }
-  assertTrue(this->mode == FILE_MODE_READ);
+  assertTrue(this->mode == FILE_MODE_READ, "File::readRaw: File must be open in read mode");
   return fread(buffer, sizeof(char), max, this->file);
 }
 
 bool_t File::writeString(std::string in) {
   if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false;
-  assertTrue(this->mode == FILE_MODE_WRITE);
+  assertTrue(this->mode == FILE_MODE_WRITE, "File::writeString: File must be open in write mode");
   return this->writeRaw((char *)in.c_str(), in.size()) && this->length == in.size();
 }
 
 bool_t File::writeRaw(char *data, size_t len) {
   if(!this->isOpen() && !this->open(FILE_MODE_WRITE)) return false;
-  assertTrue(this->mode == FILE_MODE_WRITE);
-  assertTrue(len > 0);
+  assertTrue(this->mode == FILE_MODE_WRITE, "File::writeRaw: File must be open in write mode");
+  assertTrue(len > 0, "File::writeRaw: Length must be greater than 0");
   this->length = fwrite(data, sizeof(char_t), len, this->file);
   return true;
 }
 
 bool_t File::copyRaw(File *otherFile, size_t length) {
-  assertTrue(length > 0);
-  assertTrue(otherFile->isOpen());
+  assertTrue(length > 0, "File::copyRaw: Length must be greater than 0");
+  assertTrue(otherFile->isOpen(), "File::copyRaw: Other file must be open");
 
   char buffer[FILE_BUFFER_SIZE];
   size_t amountLeftToRead = length;
@@ -217,7 +217,7 @@ bool_t File::copyRaw(File *otherFile, size_t length) {
     read += iRead;
   }
 
-  assertTrue(read == length);
+  assertTrue(read == length, "File::copyRaw: Read length does not match expected length");
   return true;
 }
 
diff --git a/src/dawntools/util/generator/SceneAssetGenerator.cpp b/src/dawntools/util/generator/SceneAssetGenerator.cpp
index 35d40d5b..4923338d 100644
--- a/src/dawntools/util/generator/SceneAssetGenerator.cpp
+++ b/src/dawntools/util/generator/SceneAssetGenerator.cpp
@@ -39,7 +39,7 @@ void SceneAssetGenerator::generate(
       break;
 
     default:
-      assertUnreachable();
+      assertUnreachable("SceneAssetGenerator::generate: Unknown asset type");
   }
 
   if(!asset->ref.empty()) {
diff --git a/src/dawntools/util/generator/SceneGenerator.cpp b/src/dawntools/util/generator/SceneGenerator.cpp
index 2bbcf3d9..2c72fd0d 100644
--- a/src/dawntools/util/generator/SceneGenerator.cpp
+++ b/src/dawntools/util/generator/SceneGenerator.cpp
@@ -13,7 +13,7 @@ void SceneGenerator::generate(
   struct MethodGenInfo &methodAssets,
   struct MethodGenInfo &methodInit
 ) {
-  assertNotNull(scene);
+  assertNotNull(scene, "SceneGenerator::generate: Scene cannot be null");
 
   std::map<std::string, std::string> assetMap;
   int32_t assetNumber = 0;
diff --git a/src/dawntools/util/generator/SceneItemGenerator.cpp b/src/dawntools/util/generator/SceneItemGenerator.cpp
index a8d6fddd..489388f5 100644
--- a/src/dawntools/util/generator/SceneItemGenerator.cpp
+++ b/src/dawntools/util/generator/SceneItemGenerator.cpp
@@ -73,7 +73,7 @@ void SceneItemGenerator::generateDependency(
     }
 
     default:
-      assertUnreachable();
+      assertUnreachable("SceneItemGenerator::generateDependency: Unknown dependency type");
   }
 }
 
@@ -91,10 +91,10 @@ void SceneItemGenerator::generate(
   struct SceneItem *item,
   std::string tabs
 ) {
-  assertNotNull(publicProperties);
-  assertNotNull(initBody);
-  assertNotNull(assetBody);
-  assertNotNull(item);
+  assertNotNull(publicProperties, "SceneItemGenerator::generate: publicProperties cannot be null");
+  assertNotNull(initBody, "SceneItemGenerator::generate: initBody cannot be null");
+  assertNotNull(assetBody, "SceneItemGenerator::generate: assetBody cannot be null");
+  assertNotNull(item, "SceneItemGenerator::generate: item cannot be null");
 
   // Determine interface
   std::string name = "itm" + std::to_string(childNumber++);
diff --git a/src/dawntools/util/parser/SceneItemComponentRegistry.cpp b/src/dawntools/util/parser/SceneItemComponentRegistry.cpp
index 8265ad30..2070a283 100644
--- a/src/dawntools/util/parser/SceneItemComponentRegistry.cpp
+++ b/src/dawntools/util/parser/SceneItemComponentRegistry.cpp
@@ -11,7 +11,7 @@ struct SceneItemComponentRuleset SceneItemComponentRegistry::parseFile(
   File *file,
   std::string clazz
 ) {
-  assertNotNull(file);
+  assertNotNull(file, "SceneItemCOmponentRegistry::parseFile: File is null");
 
   std::string data;
   if(!file->readString(&data)) {
@@ -130,7 +130,7 @@ struct SceneItemComponentRuleset SceneItemComponentRegistry::parseFile(
     } else if(paramType == "innerXml") {
       ruleset.innerXml[name] = type;
     } else {
-      assertUnreachable();
+      assertUnreachable("SceneItemComponentRegistry::parseFile: Unknown parameter type");
     }
     ++it;
   }
diff --git a/src/dawntools/vnscenetool/VNSceneGen.cpp b/src/dawntools/vnscenetool/VNSceneGen.cpp
index b0a1fb96..9abe34e2 100644
--- a/src/dawntools/vnscenetool/VNSceneGen.cpp
+++ b/src/dawntools/vnscenetool/VNSceneGen.cpp
@@ -132,7 +132,7 @@ void VNSceneGen::test(
 
       if(ifFirst == "" || ifPrevious == "") {
         std::cout << "If event must have at least one event" << std::endl;
-        assertUnreachable();
+        assertUnreachable("VNSCeneGen::test: If event must have at least one event");
       }
 
       line(eventChain, eventName + "->ifTrue = " + ifFirst + ";", "");
@@ -163,7 +163,7 @@ void VNSceneGen::test(
 
     default:
       std::cout << "Unknown event type: " << event->type << std::endl;
-      assertUnreachable();
+      assertUnreachable("VNSceneGen::test: Unknown event type");
   }
 
   if(!toInclude.empty()) includes->push_back(toInclude);
@@ -192,7 +192,7 @@ void VNSceneGen::generate(
 
   // Events
   classInfo.includes.push_back("games/vn/events/VNDummyEvent.hpp");
-  line(&methodInit.body, "assertNotNull(vnManager);", "");
+  line(&methodInit.body, "assertNotNull(vnManager, \"VNSceneGenInit - VN Manager is null?\");", "");
   line(&methodInit.body, "VNEvent *previous = vnManager->createEvent<VNDummyEvent>();", "");
   line(&methodInit.body, "auto eventStart = previous;", "");