diff --git a/library/phx/resources/resource_utils.cpp b/library/phx/resources/resource_utils.cpp
index e8e82fcb5356defa3988ae2696281f75a7054cc9..3804fae89b37f689c34763a38e47933942da29df 100644
--- a/library/phx/resources/resource_utils.cpp
+++ b/library/phx/resources/resource_utils.cpp
@@ -22,13 +22,41 @@
 #include "phx/resources/resource_utils.hpp"
 
 #include <algorithm>
+#include <cassert>
+#include <fstream>
 #include <locale>
 #include <string>
+#include <vector>
+
+#include "boost/filesystem.hpp"
 
 #include "phx/resources/resource_manager.hpp"
 #include "phx/resources_path.hpp"
 
 namespace phx {
+namespace {
+std::vector<std::string> default_resource_search_paths = {
+    {std::string("./"), resources_root}};
+}
+
+std::vector<std::string> ResourceUtils::resource_search_paths_{
+    default_resource_search_paths};
+
+void ResourceUtils::AddResourceSearchPath(const std::string& path_to_add) {
+  assert(!path_to_add.empty());
+  auto p = (path_to_add.back() == '/' ? path_to_add
+                                      : path_to_add + std::string("/"));
+  resource_search_paths_.push_back(p);
+}
+
+void ResourceUtils::ResetResourceSearchPath() {
+  resource_search_paths_ = default_resource_search_paths;
+}
+
+std::vector<std::string> ResourceUtils::GetResourceSearchPath() {
+  return resource_search_paths_;
+}
+
 ResourceDeclaration ResourceUtils::DeclarationFromFile(
     const std::string& file_name, nlohmann::json additional_info /*= {}*/,
     bool absolute_path /*= false*/) {
@@ -36,7 +64,7 @@ ResourceDeclaration ResourceUtils::DeclarationFromFile(
   if (absolute_path) {
     declaration["file_name"] = file_name;
   } else {
-    declaration["file_name"] = resources_root + file_name;
+    declaration["file_name"] = FindFileInSearchPath(file_name);
   }
   for (nlohmann::json::iterator it = additional_info.begin();
        it != additional_info.end(); ++it) {
@@ -52,4 +80,12 @@ std::string ResourceUtils::ExtractFileExtension(const std::string& file_name) {
   return extension;
 }
 
+std::string ResourceUtils::FindFileInSearchPath(const std::string& file_name) {
+  for (auto& entry : resource_search_paths_) {
+    auto full_name = entry + file_name;
+    if (boost::filesystem::exists(full_name.c_str())) return full_name;
+  }
+  return "";
+}
+
 }  // namespace phx
diff --git a/library/phx/resources/resource_utils.hpp b/library/phx/resources/resource_utils.hpp
index 8f18bc1fa3c17ae0db1dc93a83ed4aebab8d8236..95cba49f82f2601230288d4e65a948b376d436f0 100644
--- a/library/phx/resources/resource_utils.hpp
+++ b/library/phx/resources/resource_utils.hpp
@@ -26,25 +26,35 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "json.hpp"
 
 #include "phx/core/logger.hpp"
+#include "phx/export.hpp"
 #include "phx/resources/resource_declaration.hpp"
 #include "phx/resources/resource_load_strategy.hpp"
 #include "phx/resources/resource_manager.hpp"
 #include "phx/resources/resource_pointer.hpp"
 #include "phx/utility/aspects/singleton.hpp"
-#include "phx/export.hpp"
 
 namespace phx {
 /**
  * The ResourceUtils class contains static convenience methods to simplify
- * interactions with the resource system. It should never hold any state.
+ * interactions with the resource system. It also holds a user configurable
+ * resource search path. When operating on a relative file name, it will
+ * search all entries in the search path and return/load the first file that
+ * matches the given file name. Per default, the resource search path
+ * contains the local directory and phx::resources_root.
  */
 class PHOENIX_EXPORT ResourceUtils final {
  public:
+  static void AddResourceSearchPath(const std::string& path_to_add);
+  static void ResetResourceSearchPath();
+  static std::vector<std::string> GetResourceSearchPath();
+
   static std::string ExtractFileExtension(const std::string& file_name);
+
   static ResourceDeclaration DeclarationFromFile(
       const std::string& file_name, nlohmann::json additional_info = {},
       bool absolute_path = false);
@@ -59,6 +69,11 @@ class PHOENIX_EXPORT ResourceUtils final {
     res_ptr.Load();
     return res_ptr;
   }
+
+ private:
+  static std::string FindFileInSearchPath(const std::string& file_name);
+
+  static std::vector<std::string> resource_search_paths_;
 };
 
 }  // namespace phx
diff --git a/tests/src/test_resource_utils.cpp b/tests/src/test_resource_utils.cpp
index d2b0a9bb82b807735219581322600fec1e1c6e26..1da8fcab9e8789cba8a6a11d1a0261b45dc8aa36 100644
--- a/tests/src/test_resource_utils.cpp
+++ b/tests/src/test_resource_utils.cpp
@@ -20,15 +20,27 @@
 // limitations under the License.
 //------------------------------------------------------------------------------
 
+#include <fstream>
 #include <string>
 
 #include "catch/catch.hpp"
 
-#include "phx/resources/types/image.hpp"
 #include "phx/resources/resource_declaration.hpp"
 #include "phx/resources/resource_utils.hpp"
+#include "phx/resources/types/image.hpp"
 #include "phx/resources_path.hpp"
 
+namespace {
+void CreateDummyFile(const std::string &file_name) {
+  std::fstream out_file(file_name.c_str(), std::ios::out);
+  // force fail test if file could not be created
+  REQUIRE(out_file.is_open());
+}
+void DeleteDummyFile(const std::string &file_name) {
+  std::remove(file_name.c_str());
+}
+}  // namespace
+
 SCENARIO("Resource utils can extract file extensions.",
          "[phx][phx::ResourceUtils]") {
   GIVEN("A file name") {
@@ -56,17 +68,19 @@ SCENARIO("Resource utils can declarare a file resource.",
   GIVEN("A file name with absolute path") {
     std::string file_name{"C:/some_path/to/file.34.ext"};
 
-    THEN("It can declare it") {
+    THEN("we get a declaration with a valid (unmodified) file name") {
       phx::ResourceDeclaration declaration =
           phx::ResourceUtils::DeclarationFromFile(file_name, {}, true);
       REQUIRE(declaration["TYPE"] == ".ext");
       REQUIRE(declaration["file_name"] == file_name);
     }
   }
-  GIVEN("A file name with relative path") {
-    std::string file_name{"file.png"};
+  GIVEN("A file name and a search path") {
+    std::string file_name{"textures/splash_progress.png"};
 
-    THEN("It can declare it") {
+    THEN(
+        "we get a declaration with a valid file name that has been pre-pended "
+        "by the first hit in the search path") {
       phx::ResourceDeclaration declaration =
           phx::ResourceUtils::DeclarationFromFile(file_name);
       REQUIRE(declaration["TYPE"] == ".png");
@@ -74,11 +88,11 @@ SCENARIO("Resource utils can declarare a file resource.",
     }
   }
   GIVEN("Additional key, value pairs are provided") {
-    std::string file_name{"file.png"};
+    std::string file_name{"textures/splash_progress.png"};
     std::string key = "some_key";
     int value = 42;
 
-    THEN("these are in the resulting declaration") {
+    THEN("the resulting declaration contains them") {
       phx::ResourceDeclaration declaration =
           phx::ResourceUtils::DeclarationFromFile(file_name, {{key, value}},
                                                   false);
@@ -87,9 +101,26 @@ SCENARIO("Resource utils can declarare a file resource.",
   }
 }
 
+SCENARIO("Resource utils find file resource outside the original search path",
+         "[phx][phx::ResourceUtils]") {
+  GIVEN("A file outside the original resource tree") {
+    std::string dummy_file = "dummy.txt";
+    std::string offset_search_path = "../";
+    ::CreateDummyFile(offset_search_path + dummy_file);
+
+    phx::ResourceUtils::AddResourceSearchPath(offset_search_path);
+    THEN("the file is found and a valid declaration is returned") {
+      phx::ResourceDeclaration declaration =
+          phx::ResourceUtils::DeclarationFromFile(dummy_file, {}, false);
+      CHECK(declaration["file_name"] == offset_search_path + dummy_file);
+      ::DeleteDummyFile(offset_search_path + dummy_file);
+    }
+  }
+}
+
 SCENARIO("Resource utils can load a file resource.",
          "[phx][phx::ResourceUtils]") {
-  GIVEN("A file name") {
+  GIVEN("A file name within the original resource tree") {
     std::string file_name{"textures/splash_progress.png"};
 
     THEN("It can load it") {