diff --git a/assets/games/rose/prefabs/Player.xml b/assets/games/rose/prefabs/Player.xml
index c37a6d63..40218b32 100644
--- a/assets/games/rose/prefabs/Player.xml
+++ b/assets/games/rose/prefabs/Player.xml
@@ -6,7 +6,7 @@
   <BoxCollider min="-1, -1" max="1, 1" />
   <PlayerController ref="player" />
 
-  <child ref="nose">
+  <child position="0, 0, 2" scale="0.1, 0.1, 0.1">
     <MeshRenderer />
     <MeshHost ref="noseMeshHost" />
     <SimpleTexturedMaterial color="COLOR_RED" />
diff --git a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp
index cc6f2264..ec29eb36 100644
--- a/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp
+++ b/src/dawnopengl/scene/components/display/material/SimpleTexturedMaterial.hpp
@@ -9,7 +9,9 @@
 namespace Dawn {
   class SimpleTexturedMaterial : public Material {
     public:
+      // @optional
       Texture *texture = nullptr;
+      // @optional
       struct Color color = COLOR_WHITE;
 
       /**
diff --git a/src/dawntools/prefabtool/CMakeLists.txt b/src/dawntools/prefabtool/CMakeLists.txt
index b51ece00..cfa6ebc6 100644
--- a/src/dawntools/prefabtool/CMakeLists.txt
+++ b/src/dawntools/prefabtool/CMakeLists.txt
@@ -13,6 +13,8 @@ target_sources(prefabtool
     ${DAWN_SHARED_SOURCES}
     ${DAWN_TOOL_SOURCES}
     PrefabTool.cpp
+    PrefabGen.cpp
+    PrefabChildParser.cpp
     PrefabParser.cpp
     PrefabRegistry.cpp
     PrefabComponentParser.cpp
diff --git a/src/dawntools/prefabtool/Parsers.hpp b/src/dawntools/prefabtool/Parsers.hpp
new file mode 100644
index 00000000..3fcf7f56
--- /dev/null
+++ b/src/dawntools/prefabtool/Parsers.hpp
@@ -0,0 +1,71 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "util/string.hpp"
+
+namespace Dawn {
+  static inline std::string rawParser(std::string v, std::string *error) {
+    return v;
+  };
+
+  static inline std::string stringParser(std::string v, std::string *error) {
+    return "\"" + v + "\"";
+  };
+
+  static inline std::string floatParser(std::string v, std::string *error) {
+    v = stringTrim(v);
+
+    // Make sure number contains decimal
+    if(v.find(".") == std::string::npos) {
+      v += ".0";
+    }
+    // Make sure number contains a number before the decimal
+    if(v.find(".") == 0) {
+      v = "0" + v;
+    }
+    // Make sure ends with f
+    if(v.find("f") == std::string::npos) {
+      v += "f";
+    }
+    return v;
+  };
+
+  static inline std::string vec2Parser(std::string v, std::string *error) {
+    // Split string by comma into two strings that we pass into float
+    auto split = stringSplit(v, ",");
+    if(split.size() != 2) {
+      *error = "Invalid vec2 value: " + v;
+      return std::string("");
+    }
+    return std::string(
+      "glm::vec2(" +
+        floatParser(split[0], error) + ", " +
+        floatParser(split[1], error) +
+      ")"
+    );
+  };
+
+
+  static inline std::string vec3Parser(std::string v, std::string *error) {
+    // Split string by comma into two strings that we pass into float
+    auto split = stringSplit(v, ",");
+    if(split.size() != 3) {
+      *error = "Invalid vec3 value: " + v;
+      return std::string("");
+    }
+    return std::string(
+      "glm::vec3(" +
+        floatParser(split[0], error) + ", " +
+        floatParser(split[1], error) + ", " +
+        floatParser(split[2], error) +
+      ")"
+    );
+  };
+
+  static inline std::string colorParser(std::string v, std::string *error) {
+    return rawParser(v, error);
+  }
+}
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/PrefabChildParser.cpp b/src/dawntools/prefabtool/PrefabChildParser.cpp
new file mode 100644
index 00000000..0dc5ecb6
--- /dev/null
+++ b/src/dawntools/prefabtool/PrefabChildParser.cpp
@@ -0,0 +1,61 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "PrefabChildParser.hpp"
+
+using namespace Dawn;
+
+std::vector<std::string> PrefabChildParser::getRequiredAttributes() {
+  return std::vector<std::string>();
+}
+
+std::map<std::string, std::string> PrefabChildParser::getOptionalAttributes() {
+  return {
+    { "ref", "" },
+    { "position", "" },
+    { "scale", "" }
+  };
+}
+
+int32_t PrefabChildParser::onParse(
+  Xml *node,
+  std::map<std::string, std::string> values,
+  struct PrefabChild *out,
+  std::string *error
+) {
+  out->ref = values["ref"];
+
+  if(values["position"].size() > 0) {
+    out->position = vec3Parser(values["position"], error);
+    if(error->size() > 0) return 1;
+  }
+
+  if(values["scale"].size() > 0) {
+    out->scale = vec3Parser(values["scale"], error);
+    if(error->size() > 0) return 1;
+  }
+
+  auto itChildren = node->children.begin();
+  while(itChildren != node->children.end()) {
+    // Parse child nodes, they may be components or not
+    auto c = *itChildren;
+    if(c->node == "child") {
+      struct PrefabChild child;
+      child.registry = out->registry;
+      auto ret = (PrefabChildParser()).parse(c, &child, error);
+      if(ret != 0) return ret;
+      out->children.push_back(child);
+    } else {
+      struct PrefabComponent component;
+      component.registry = out->registry;
+      auto ret = (PrefabComponentParser()).parse(c, &component, error);
+      if(ret != 0) return ret;
+      out->components.push_back(component);
+    }
+    ++itChildren;
+  }
+
+  return 0;
+}
diff --git a/src/dawntools/prefabtool/PrefabChildParser.hpp b/src/dawntools/prefabtool/PrefabChildParser.hpp
index c346c8ba..e9309f78 100644
--- a/src/dawntools/prefabtool/PrefabChildParser.hpp
+++ b/src/dawntools/prefabtool/PrefabChildParser.hpp
@@ -4,7 +4,27 @@
 // https://opensource.org/licenses/MIT
 
 #pragma once
-#include "PrefabParser.hpp"
+#include "PrefabComponentParser.hpp"
 
 namespace Dawn {
-}
\ No newline at end of file
+  struct PrefabChild {
+    struct PrefabRegistry *registry;
+    std::string ref;
+    std::string position;
+    std::string scale;
+    std::vector<struct PrefabComponent> components;
+    std::vector<struct PrefabChild> children;
+  };
+
+  class PrefabChildParser : public XmlParser<struct PrefabChild> {
+    protected:
+      std::vector<std::string> getRequiredAttributes() override;
+      std::map<std::string, std::string> getOptionalAttributes() override;
+      int32_t onParse(
+        Xml *node,
+        std::map<std::string, std::string> values,
+        struct PrefabChild *out,
+        std::string *error
+      ) override;
+  };
+}
diff --git a/src/dawntools/prefabtool/PrefabComponentParser.cpp b/src/dawntools/prefabtool/PrefabComponentParser.cpp
index 657b5108..e84e316e 100644
--- a/src/dawntools/prefabtool/PrefabComponentParser.cpp
+++ b/src/dawntools/prefabtool/PrefabComponentParser.cpp
@@ -38,58 +38,6 @@ int32_t PrefabComponentParser::onParse(
   out->type = node->node;
 
   // Define parser types here.
-  auto rawParser = [&](std::string v){
-    return v;
-  };
-
-  auto stringParser = [&](std::string v){
-    return "\"" + v + "\"";
-  };
-
-  auto floatParser = [&](std::string v){
-    v = stringTrim(v);
-
-    // Make sure number contains decimal
-    if(v.find(".") == std::string::npos) {
-      v += ".0";
-    }
-    // Make sure number contains a number before the decimal
-    if(v.find(".") == 0) {
-      v = "0" + v;
-    }
-    // Make sure ends with f
-    if(v.find("f") == std::string::npos) {
-      v += "f";
-    }
-    return v;
-  };
-
-  auto vec2Parser = [&](std::string v) {
-    // Split string by comma into two strings that we pass into float
-    auto split = stringSplit(v, ",");
-    if(split.size() != 2) {
-      *error = "Invalid vec2 value: " + v;
-      return std::string("");
-    }
-    return std::string(
-      "glm::vec2(" + floatParser(split[0]) + ", " + floatParser(split[1]) + ")"
-    );
-  };
-
-
-  auto vec3Parser = [&](std::string v) {
-    // Split string by comma into two strings that we pass into float
-    auto split = stringSplit(v, ",");
-    if(split.size() != 3) {
-      *error = "Invalid vec3 value: " + v;
-      return std::string("");
-    }
-    return std::string(
-      "glm::vec3(" + floatParser(split[0]) + ", " + floatParser(split[1]) + ", " + floatParser(split[2]) + ")"
-    );
-  };
-
-  auto colorParser = rawParser;
 
   // Iterate all the optional attributes and store within the out if present
   auto itOptional = ruleset.optional.begin();
@@ -98,7 +46,7 @@ int32_t PrefabComponentParser::onParse(
     auto name = itOptional->first;
     auto type = itOptional->second;
 
-    std::function<std::string(std::string)> parser = rawParser;
+    std::function<std::string(std::string, std::string*)> parser = rawParser;
     if(type.find("string") != std::string::npos) {
       parser = stringParser;
     } else if(type.find("float") != std::string::npos) {
@@ -122,7 +70,7 @@ int32_t PrefabComponentParser::onParse(
 
     if(node->attributes.find(name) != node->attributes.end()) {
       auto raw = node->attributes[name];
-      out->values[name] = parser(raw);
+      out->values[name] = parser(raw, error);
       if(error->size() != 0) return 1;
     }
     ++itOptional;
diff --git a/src/dawntools/prefabtool/PrefabComponentParser.hpp b/src/dawntools/prefabtool/PrefabComponentParser.hpp
index e4f06020..7c209ba4 100644
--- a/src/dawntools/prefabtool/PrefabComponentParser.hpp
+++ b/src/dawntools/prefabtool/PrefabComponentParser.hpp
@@ -5,11 +5,11 @@
 
 #pragma once
 #include "PrefabRegistry.hpp"
+#include "Parsers.hpp"
 
 namespace Dawn {
   struct PrefabComponent {
     struct PrefabRegistry *registry;
-
     std::string include;
     std::string type;
     std::map<std::string, std::string> values;
diff --git a/src/dawntools/prefabtool/PrefabGen.cpp b/src/dawntools/prefabtool/PrefabGen.cpp
new file mode 100644
index 00000000..5a79f7d3
--- /dev/null
+++ b/src/dawntools/prefabtool/PrefabGen.cpp
@@ -0,0 +1,125 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#include "PrefabGen.hpp"
+
+using namespace Dawn;
+
+void PrefabGen::generate(
+  std::vector<std::string> *out,
+  struct Prefab *info,
+  std::string tabs
+) {
+  struct ClassGenInfo classInfo;
+  classInfo.clazz = info->name;
+  classInfo.extend = "SceneItemPrefab<" + info->name + ">";
+  classInfo.constructorArgs = "Scene *scene, sceneitemid_t id";
+  classInfo.extendArgs = "scene, id";
+
+  struct MethodGenInfo methodAssets;
+  methodAssets.name = "prefabAssets";
+  methodAssets.isStatic = true;
+  methodAssets.type = "std::vector<Asset*>";
+  methodAssets.args = "AssetManager *man";
+  line(&methodAssets.body, "std::vector<Asset*> assets;", "");
+
+  struct MethodGenInfo methodInit;
+  methodInit.name = "prefabInit";
+  methodInit.isOverride = true;
+  methodInit.args = "AssetManager *man";
+
+  classInfo.includes.push_back("prefab/SceneItemPrefab.hpp");
+
+  // Process root and all of its children
+  int32_t childNumber = 0;
+  int32_t componentNumber = 0;
+
+  auto processComponent = [&](struct PrefabComponent c, std::string item) {
+    auto componentName = "cmp" + std::to_string(componentNumber++);
+    bool_t componentInit = true;
+    if(c.ref.size() > 0) {
+      componentInit = false;
+      componentName = c.ref;
+      line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", "");
+    }
+
+    // Initialize
+    line(&methodInit.body, (componentInit ? "auto " : "") + componentName + " = " + item + "->addComponent<" + c.type + ">();", "");
+
+    // Now set each property
+    auto itValues = c.values.begin();
+    while(itValues != c.values.end()) {
+      line(&methodInit.body, componentName + "->" + itValues->first + " = " + itValues->second + ";", "");
+      ++itValues;
+    }
+
+    classInfo.includes.push_back(c.include);
+  };
+
+  std::function<void(struct PrefabChild &, std::string)> processChild;
+  processChild = [&](struct PrefabChild &child, std::string parent) {
+    auto name = "itm" + std::to_string(childNumber++);
+    bool_t init = true;
+    if(child.ref.size() > 0) {
+      init = false;
+      name = child.ref;
+      line(&classInfo.publicProperties, "SceneItemComponent *" + name + " = nullptr;", "");
+    }
+    line(&methodInit.body, (init ? "auto " : "") + name + " = scene->createSceneItem();", "");
+
+    // Process extra properties
+    if(child.position.size() > 0) {
+      line(&methodInit.body, name + "->transform.setLocalPosition(" + child.position + ");", "");
+    }
+
+    if(child.scale.size() > 0) {
+      line(&methodInit.body, name + "->transform.setLocalScale(" + child.scale + ");", "");
+    }
+
+    // Add components for children
+    auto itComponents = child.components.begin();
+    while(itComponents != child.components.end()) {
+      auto c = *itComponents;
+      processComponent(c, name);
+      ++itComponents;
+    }
+
+    // Process sub children
+    auto itChildren = child.children.begin();
+    while(itChildren != child.children.end()) {
+      processChild(*itChildren, name);
+      ++itChildren;
+    }
+
+    // Set parent
+    line(&methodInit.body, name + "->transform.setParent(&"+parent+"->transform);", "");
+  };
+  
+  // Process each child
+  auto itChildren = info->root.children.begin();
+  while(itChildren != info->root.children.end()) {
+    processChild(*itChildren, "this");
+    line(&methodInit.body, "", "");
+    ++itChildren;
+  }
+
+  // Process self components
+  auto itComponents = info->root.components.begin();
+  while(itComponents != info->root.components.end()) {
+    auto c = *itComponents;
+    processComponent(c, "this");
+    ++itComponents;
+  }
+  
+  // Seal methods
+  line(&methodAssets.body, "return assets;", "");
+
+  // Add in methods
+  CodeGen::methodGen(&classInfo.publicCode, methodAssets);
+  line(&classInfo.publicCode, "", "");
+  CodeGen::methodGen(&classInfo.publicCode, methodInit);
+
+  CodeGen::classGen(out, classInfo);
+}
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/PrefabGen.hpp b/src/dawntools/prefabtool/PrefabGen.hpp
new file mode 100644
index 00000000..43ecbed3
--- /dev/null
+++ b/src/dawntools/prefabtool/PrefabGen.hpp
@@ -0,0 +1,18 @@
+// Copyright (c) 2023 Dominic Masters
+// 
+// This software is released under the MIT License.
+// https://opensource.org/licenses/MIT
+
+#pragma once
+#include "PrefabParser.hpp"
+
+namespace Dawn {
+  class PrefabGen : public CodeGen {
+    public:
+      static void generate(
+        std::vector<std::string> *out,
+        struct Prefab *prefab,
+        std::string tabs
+      );
+  };
+}
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/PrefabParser.cpp b/src/dawntools/prefabtool/PrefabParser.cpp
index c659edb1..159d7f1c 100644
--- a/src/dawntools/prefabtool/PrefabParser.cpp
+++ b/src/dawntools/prefabtool/PrefabParser.cpp
@@ -23,22 +23,6 @@ int32_t PrefabParser::onParse(
 ) {
   out->name = values["name"];
   out->type = values["type"];
-
-  auto itChildren = node->children.begin();
-  while(itChildren != node->children.end()) {
-    // Parse child nodes, they may be components or not
-    auto c = *itChildren;
-    if(c->node == "child") {
-      std::cout << "Child detected" << std::endl;
-    } else {
-      struct PrefabComponent component;
-      component.registry = out->registry;
-      auto ret = (PrefabComponentParser()).parse(*itChildren, &component, error);
-      if(ret != 0) return ret;
-      out->components.push_back(component);
-    }
-    ++itChildren;
-  }
-
-  return 0;
+  out->root.registry = out->registry;
+  return (PrefabChildParser()).parse(node, &out->root, error);
 }
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/PrefabParser.hpp b/src/dawntools/prefabtool/PrefabParser.hpp
index e39cecc5..89053e87 100644
--- a/src/dawntools/prefabtool/PrefabParser.hpp
+++ b/src/dawntools/prefabtool/PrefabParser.hpp
@@ -5,13 +5,14 @@
 
 #pragma once
 #include "PrefabComponentParser.hpp"
+#include "PrefabChildParser.hpp"
 
 namespace Dawn {
   struct Prefab {
     struct PrefabRegistry *registry;
+    struct PrefabChild root;
     std::string name;
     std::string type;
-    std::vector<struct PrefabComponent> components;
   };
   
   class PrefabParser : public XmlParser<struct Prefab> {
diff --git a/src/dawntools/prefabtool/PrefabRegistry.cpp b/src/dawntools/prefabtool/PrefabRegistry.cpp
index 950410f1..bfd189bf 100644
--- a/src/dawntools/prefabtool/PrefabRegistry.cpp
+++ b/src/dawntools/prefabtool/PrefabRegistry.cpp
@@ -32,6 +32,7 @@ struct PrefabComponentParserRuleset PrefabRegistry::getRuleset(std::string type)
         continue;
       }
 
+
       // Load ruleset
       std::string data;
       File file(str + "/" + itChildren->first);
diff --git a/src/dawntools/prefabtool/PrefabTool.cpp b/src/dawntools/prefabtool/PrefabTool.cpp
index c6ad8e8a..cd64f6b9 100644
--- a/src/dawntools/prefabtool/PrefabTool.cpp
+++ b/src/dawntools/prefabtool/PrefabTool.cpp
@@ -41,6 +41,7 @@ int32_t PrefabTool::start() {
     return result;
   }
 
+
   // Generate output
   std::vector<std::string> outputData;
   PrefabGen::generate(&outputData, &prefab, "");
@@ -66,70 +67,4 @@ int32_t PrefabTool::start() {
   }
 
   return 0;
-}
-
-//
-
-void PrefabGen::generate(
-  std::vector<std::string> *out,
-  struct Prefab *info,
-  std::string tabs
-) {
-  struct ClassGenInfo classInfo;
-  classInfo.clazz = info->name;
-  classInfo.extend = "SceneItemPrefab<" + info->name + ">";
-  classInfo.constructorArgs = "Scene *scene, sceneitemid_t id";
-  classInfo.extendArgs = "scene, id";
-
-  struct MethodGenInfo methodAssets;
-  methodAssets.name = "prefabAssets";
-  methodAssets.isStatic = true;
-  methodAssets.type = "std::vector<Asset*>";
-  methodAssets.args = "AssetManager *man";
-  line(&methodAssets.body, "std::vector<Asset*> assets;", "");
-
-  struct MethodGenInfo methodInit;
-  methodInit.name = "prefabInit";
-  methodInit.isOverride = true;
-  methodInit.args = "AssetManager *man";
-
-  classInfo.includes.push_back("prefab/SceneItemPrefab.hpp");
-
-  // Includes
-  int32_t componentNumber = 0;
-  auto itChildren = info->components.begin();
-  while(itChildren != info->components.end()) {
-    auto c = *itChildren;
-    std::string name = "c" + std::to_string(componentNumber++);
-    bool_t init = true;
-    if(c.ref.size() > 0) {
-      init = false;
-      name = c.ref;
-      line(&classInfo.publicProperties, c.type + " *" + c.ref + " = nullptr;", "");
-    }
-
-    // Initialize
-    line(&methodInit.body, (init ? "auto " : "") + name + " = this->addComponent<" + c.type + ">();", "");
-
-    // Now set each property
-    auto itValues = c.values.begin();
-    while(itValues != c.values.end()) {
-      line(&methodInit.body, name + "->" + itValues->first + " = " + itValues->second + ";", "");
-      ++itValues;
-    }
-    line(&methodInit.body, "", "");
-
-    classInfo.includes.push_back(c.include);
-    ++itChildren;
-  }
-  
-  // Seal methods
-  line(&methodAssets.body, "return assets;", "");
-
-  // Add in methods
-  CodeGen::methodGen(&classInfo.publicCode, methodAssets);
-  line(&classInfo.publicCode, "", "");
-  CodeGen::methodGen(&classInfo.publicCode, methodInit);
-
-  CodeGen::classGen(out, classInfo);
 }
\ No newline at end of file
diff --git a/src/dawntools/prefabtool/PrefabTool.hpp b/src/dawntools/prefabtool/PrefabTool.hpp
index 66975056..4ff53d31 100644
--- a/src/dawntools/prefabtool/PrefabTool.hpp
+++ b/src/dawntools/prefabtool/PrefabTool.hpp
@@ -4,7 +4,7 @@
 // https://opensource.org/licenses/MIT
 
 #pragma once
-#include "PrefabParser.hpp"
+#include "PrefabGen.hpp"
 
 namespace Dawn {
   class PrefabTool : public DawnTool {
@@ -15,13 +15,4 @@ namespace Dawn {
     public:
       int32_t start();
   };
-
-  class PrefabGen : public CodeGen {
-    public:
-      static void generate(
-        std::vector<std::string> *out,
-        struct Prefab *prefab,
-        std::string tabs
-      );
-  };
 }
\ No newline at end of file