diff --git a/.gitignore b/.gitignore
index 49aab4c22e69fe2631c99aa4daa400042dd54ddb..bbf307cd06a4ef697e37e0d160c9d7c77d426996 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,6 +63,3 @@ sysinfo.txt
 
 # Crashlytics generated file
 crashlytics-build.properties
-
-# Ignore UserSettings
-UserSettings/
diff --git a/Assets/ContentSizeFitterMaxWidth.cs b/Assets/ContentSizeFitterMaxWidth.cs
new file mode 100644
index 0000000000000000000000000000000000000000..525b3a5e47841873e558492012819e22b86da4ef
--- /dev/null
+++ b/Assets/ContentSizeFitterMaxWidth.cs
@@ -0,0 +1,37 @@
+using UnityEngine;
+using UnityEngine.UI;
+
+[ExecuteAlways]
+[RequireComponent(typeof(ContentSizeFitter))]
+public class ContentSizeFitterMaxWidth : MonoBehaviour
+{
+    public float maxWidth;
+
+    RectTransform _rtfm;
+    ContentSizeFitter _fitter;
+    ILayoutElement _layout;
+
+    void OnEnable()
+    {
+        _rtfm = (RectTransform)transform;
+        _fitter = GetComponent<ContentSizeFitter>();
+        _layout = GetComponent<ILayoutElement>();
+    }
+
+    void Update()
+    {
+        _fitter.horizontalFit = _layout.preferredWidth > maxWidth
+            ? ContentSizeFitter.FitMode.Unconstrained
+            : ContentSizeFitter.FitMode.PreferredSize;
+
+        if (_layout.preferredWidth > maxWidth)
+        {
+            _fitter.horizontalFit = ContentSizeFitter.FitMode.Unconstrained;
+            _rtfm.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, maxWidth);
+        }
+        else
+            _fitter.horizontalFit = ContentSizeFitter.FitMode.PreferredSize;
+    }
+
+    void OnValidate() => OnEnable();
+}
\ No newline at end of file
diff --git a/Assets/ContentSizeFitterMaxWidth.cs.meta b/Assets/ContentSizeFitterMaxWidth.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..10bae19192c7f5c044088700946e0481b6933a26
--- /dev/null
+++ b/Assets/ContentSizeFitterMaxWidth.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 7c2193a3ac4b5604eb3358d292b04fa7
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/ScriptableObjects/DataContainerGadgetCollection.cs b/Assets/ScriptableObjects/DataContainerGadgetCollection.cs
index 29c556c305f8b4dfb33a3749ff7629f870b9bb67..538ef9ed9bcea1ce7ac40cb3e1b5b8d2bd709b66 100644
--- a/Assets/ScriptableObjects/DataContainerGadgetCollection.cs
+++ b/Assets/ScriptableObjects/DataContainerGadgetCollection.cs
@@ -1,5 +1,5 @@
 using System;
-using System.Collections;
+using System.Linq;
 using System.Collections.Generic;
 using UnityEngine;
 
@@ -17,13 +17,16 @@ public class DataContainerGadgetCollection : ScriptableObject, ISerializationCal
 
     public void OnBeforeSerialize()
     {
-        GadgetType.Clear();
-        GadgetData.Clear();
+        var keys = DataContainerGadgetDict.Keys.ToArray();
+        var vals = DataContainerGadgetDict.Values.ToArray();
 
-        foreach (var kvp in DataContainerGadgetDict)
+        for (int i = 0; i < keys.Length; i++)
         {
-            GadgetType.Add(kvp.Key);
-            GadgetData.Add(kvp.Value);
+            if (GadgetType.Count <= i)  GadgetType.Add(keys[i]);
+            else                        GadgetType[i] = keys[i];
+
+            if (GadgetData.Count <= i)  GadgetData.Add(vals[i]);
+            else                        GadgetData[i] = vals[i];
         }
     }
 
diff --git a/Assets/Scripts/CircleSegmentGenerator.cs b/Assets/Scripts/CircleSegmentGenerator.cs
index db10a772d3152abd580baba9495343097771c1f6..2d4148134b9a1b2dc0fd16631b2d88ead6a530cc 100644
--- a/Assets/Scripts/CircleSegmentGenerator.cs
+++ b/Assets/Scripts/CircleSegmentGenerator.cs
@@ -29,7 +29,7 @@ private void CreateSegment(float angle, float radius)
         verticeList.Add(center0);
 
         //Center-Point of upper side
-        Vector3 center1 = new Vector3(0, height/2, 0);
+        Vector3 center1 = new Vector3(0, 0, 0);
         int center1Index = 1;
         verticeList.Add(center1);
 
@@ -37,7 +37,7 @@ private void CreateSegment(float angle, float radius)
         float negAngle = posAngle * -1;
 
         int i = 2;
-        for (float x = negAngle; x < posAngle; x += angleAccuracy)
+        for (float x = negAngle; x < posAngle; x += angleAccuracy, i += 2)
         {
             float nextAngle;
 
@@ -55,8 +55,8 @@ private void CreateSegment(float angle, float radius)
                 //Add first Points at the beginning of the angle
                 float firstPointX = radius * Mathf.Cos(negAngle * Mathf.Deg2Rad);
                 float firstPointZ = radius * Mathf.Sin(negAngle * Mathf.Deg2Rad);
-                verticeList.Add(new Vector3(firstPointX, 0, firstPointZ));
-                verticeList.Add(new Vector3(firstPointX, height, firstPointZ));
+                verticeList.Add(new Vector3(firstPointX, -height/2, firstPointZ));
+                verticeList.Add(new Vector3(firstPointX, +height/2, firstPointZ));
 
                 //Adding triangles for left side
                 if (absoluteAngle != 360)
@@ -72,8 +72,8 @@ private void CreateSegment(float angle, float radius)
                 i += 2;
             }
 
-            verticeList.Add(new Vector3(newPointX, 0, newPointZ));
-            verticeList.Add(new Vector3(newPointX, height, newPointZ));
+            verticeList.Add(new Vector3(newPointX, -height/2, newPointZ));
+            verticeList.Add(new Vector3(newPointX, +height/2, newPointZ));
 
             //Adding triangles for upper- and lower-side
             triangleList.Add(center0Index);
@@ -100,8 +100,6 @@ private void CreateSegment(float angle, float radius)
                 triangleList.Add(i);
                 triangleList.Add(i + 1);
             }
-
-            i += 2;
         }
 
         mesh = new Mesh
@@ -109,8 +107,9 @@ private void CreateSegment(float angle, float radius)
             vertices = verticeList.ToArray(),
             triangles = triangleList.ToArray()
         };
+        mesh.RecalculateNormals();
+
         GetComponent<MeshFilter>().mesh = mesh;
         GetComponent<MeshCollider>().sharedMesh = mesh;
-        mesh.RecalculateNormals();
     }
 }
diff --git a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs
index 0e3326a1017336ac3007af4bf09fb69371ad8f48..e08cbd9ac9d92b0b0b1b86415cd701cb7772b643 100644
--- a/Assets/Scripts/InteractionEngine/CommunicationEvents.cs
+++ b/Assets/Scripts/InteractionEngine/CommunicationEvents.cs
@@ -42,7 +42,6 @@ public static class CommunicationEvents
 
     public static Process process_mmt_frameIT_server;
 
-    public static bool takeNewToolID = false; //0=no, 1=instead, 2=both
     public static int ToolID_new;
     public static int ToolID_selected;//Script
     
diff --git a/Assets/Scripts/InteractionEngine/FactHandling/FactSpawner.cs b/Assets/Scripts/InteractionEngine/FactHandling/FactSpawner.cs
index 780cb4a902976c6898238ff88549dad026e7875f..370b755e169ea9ad7d6dc6ec8fb0e75a2327ea3e 100644
--- a/Assets/Scripts/InteractionEngine/FactHandling/FactSpawner.cs
+++ b/Assets/Scripts/InteractionEngine/FactHandling/FactSpawner.cs
@@ -150,12 +150,20 @@ public Fact SpawnAngle(Fact fact)
         float angleValue = Vector3.Angle(from, to); //We always get an angle between 0 and 180° here
 
         //Change scale and rotation, so that the angle is in between the two lines
-        var v3T = angle.transform.localScale;
-        v3T = new Vector3(length, v3T.y, length);
 
+        Vector3 forwoard = (from + to).normalized;
         Vector3 up = Vector3.Cross(to, from);
+
+        if (up.sqrMagnitude < Math3d.vectorPrecission) { //Angle is 180° (or 0°)
+            Vector3 arbitary = up == Vector3.forward ? Vector3.right : Vector3.forward;
+            up = Vector3.Cross(arbitary, to);
+
+            forwoard = to;
+        } else
+            forwoard = Vector3.Cross(forwoard, up);
+
         //Place the Angle at position of point2
-        angle.transform.SetPositionAndRotation(point2, Quaternion.LookRotation(Vector3.Cross((from+to).normalized,up), up));
+        angle.transform.SetPositionAndRotation(point2, Quaternion.LookRotation(forwoard, up));
 
         //Set text of angle
         TextMeshPro[] texts = angle.GetComponentsInChildren<TextMeshPro>();
diff --git a/Assets/Scripts/InteractionEngine/Gadgets/Gadget.cs b/Assets/Scripts/InteractionEngine/Gadgets/Gadget.cs
index ba704d48f91dd3ade60cd784238e46ec54f375fe..5674641c392c96bb0c2ab00f3d3e7c54209fbf9a 100644
--- a/Assets/Scripts/InteractionEngine/Gadgets/Gadget.cs
+++ b/Assets/Scripts/InteractionEngine/Gadgets/Gadget.cs
@@ -34,6 +34,7 @@ public abstract class Gadget
     /// <remarks>Do NOT rename elements! Do NOT change values! Deserialization relies on it!</remarks>
     public enum GadgetIDs
     {
+        Unused = -3,
         Undefined = -1,
         Pointer = 0,
         Tape = 1,
diff --git a/Assets/Scripts/InteractionEngine/ImageHintAnimation.cs b/Assets/Scripts/InteractionEngine/ImageHintAnimation.cs
index f56f135f43b46da1395120aba5f43b62ebe5d5dd..51e59deb9e6fc41b4331fe6651c6c338dda21653 100644
--- a/Assets/Scripts/InteractionEngine/ImageHintAnimation.cs
+++ b/Assets/Scripts/InteractionEngine/ImageHintAnimation.cs
@@ -21,8 +21,7 @@ void Awake()
 
     public void AnimationTrigger()
     {
-        routine = Animation();
-        StartCoroutine(routine);
+        StartCoroutine(routine = Animation());
 
         IEnumerator Animation()
         {
@@ -43,5 +42,7 @@ public void ResetAnimation()
     {
         if (routine != null)
             StopCoroutine(routine);
+
+        imageToChange.color = imageToChangeDefaultColor;
     }
 }
diff --git a/Assets/Scripts/InteractionEngine/ShinyThings.cs b/Assets/Scripts/InteractionEngine/ShinyThings.cs
index 87f0dd1b071fdb74fa1e806942b1f9c3fba0a9dd..d8e35ab79d69f9defe146289a61b162e043cea64 100644
--- a/Assets/Scripts/InteractionEngine/ShinyThings.cs
+++ b/Assets/Scripts/InteractionEngine/ShinyThings.cs
@@ -32,7 +32,7 @@ private void Awake()
         CommunicationEvents.PushoutFactFailEvent.AddListener(LetItRain);
         CommunicationEvents.AnimateExistingFactEvent.AddListener(HighlightWithFireworks);
 
-        rain = rain_wait = 0f.LerpInTime(0, 0, -1); // yield return break
+        rain = rain_wait = IEnumeratorExtensions.yield_break;
     }
 
     public void Start()
@@ -49,10 +49,10 @@ public void Start()
     // Update is called once per frame
     public void Update()
     {
-        Highlighting(Cursor.Hit);
+        HighlightCurserHit(Cursor.Hit);
     }
 
-    private void Highlighting(RaycastHit hit)
+    private void HighlightCurserHit(RaycastHit hit)
     {
         FactObject selected_fact_obj = hit.transform?.GetComponentInChildren<FactObject>();
 
@@ -97,7 +97,7 @@ public static void HighlightFact(Fact startFact, FactObject.FactMaterials tmp_ma
 
     public void HighlightWithFireworks(Fact fact)
     {
-        while (rain_wait.MoveNext()) ; //stop rain
+        rain_wait = IEnumeratorExtensions.yield_break; //stop rain
 
         StartCoroutine(BlossomAndDie());
         HighlightFact(fact, FactObject.FactMaterials.Solution);
@@ -127,20 +127,19 @@ IEnumerator BlossomAndDie()
 
     public void LetItRain(Fact startFact)
     {
-        bool restart = !rain_wait.MoveNext();
-
-        if (restart) {
+        // check if couroutine is waiting 
+        if (!rain_wait.MoveNext()) {
             StopCoroutine(rain);
             StartCoroutine(rain = BlossomAndDie());
         }
-        rain_wait = 0f.LerpInTime(0, 0, timerDuration);
+        rain_wait = 0f.LerpInTime(0, 0, timerDuration); //reset timer
 
         IEnumerator BlossomAndDie()
         {
             Destroy(active_rainwork);
             active_rainwork = GameObject.Instantiate(RainPrefab, new Vector3(0, 40, 0), Quaternion.identity);
 
-            Color start = directionalLight.color;
+            Color start = directionalLight.color; // may not be original one
             for (IEnumerator<float> lerper = MathfExtensions.LerpInTime(0, 1, lerpTime)
                 ; lerper.MoveNext();)
             {
diff --git a/Assets/Scripts/InventoryStuff/DisplayFacts.cs b/Assets/Scripts/InventoryStuff/DisplayFacts.cs
index d1bedf7667c2d8be6f0b66dd7fbf4608ce04c4a5..acc8973ef38837f5b966ed8722ba4c232c03c0c2 100644
--- a/Assets/Scripts/InventoryStuff/DisplayFacts.cs
+++ b/Assets/Scripts/InventoryStuff/DisplayFacts.cs
@@ -35,8 +35,8 @@ void Start()
         };
 
         var rect = GetComponent<RectTransform>();
-        x_Start = (int)(rect.rect.x + X_Pacece_Between_Items * .5f);
-        y_Start = (int)(-rect.rect.y - y_Pacece_Between_Items * .5f);//);
+        x_Start = (int)(+rect.rect.x + X_Pacece_Between_Items * .5f);
+        y_Start = (int)(-rect.rect.y - y_Pacece_Between_Items * .5f);
         number_of_Column = Mathf.Max(1, (int)(rect.rect.width / prefab_Point.GetComponent<RectTransform>().rect.width) - 1);
 
         AddFactEvent.AddListener(AddFact);
@@ -65,8 +65,7 @@ public void UpdatePositions()
     }
 
     public void AnimateFact(Fact fact) {
-        var factIcon = displayedFacts[fact.Id];
-        factIcon.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
+        displayedFacts[fact.Id].GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
     }
 
     private GameObject CreateDisplay(Transform transform, Fact fact)
diff --git a/Assets/Scripts/InventoryStuff/ScrollDetails.cs b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
index 8b99675fb6d120cdcee714dd48c7ada5eda6bdf4..d677431dd08ebf1350bd82ebd136c000fe60a28a 100644
--- a/Assets/Scripts/InventoryStuff/ScrollDetails.cs
+++ b/Assets/Scripts/InventoryStuff/ScrollDetails.cs
@@ -39,21 +39,17 @@ public void setScroll(Scroll s)
         originalScroll.GetChild(0).GetComponent<TextMeshProUGUI>().text = s.description;
 
         //Clear all current ScrollFacts
-        for (int i = 0; i < originalViewport.GetChild(0).childCount; i++) {
-            GameObject.Destroy(originalViewport.GetChild(0).transform.GetChild(i).gameObject);
-        }
+        originalViewport.GetChild(0).gameObject.DestroyAllChildren();
 
         ParameterDisplays = new List<GameObject>();
         for (int i = 0; i < s.requiredFacts.Count; i++)
         {
-            var originalObj = Instantiate(parameterDisplayPrefab, Vector3.zero, Quaternion.identity, transform);
+            var originalObj = Instantiate(parameterDisplayPrefab, parent: originalViewport.GetChild(0));
             var originalScrollFact = originalObj.transform.GetChild(0).GetComponent<RenderedScrollFact>();
             originalScrollFact.ID = i;
             originalScrollFact.Label = s.requiredFacts[i].label;
             originalScrollFact.factUri = s.requiredFacts[i].@ref.uri;
 
-            originalObj.transform.SetParent(originalViewport.GetChild(0));
-
             ParameterDisplays.Add(originalObj);
         }
     }
@@ -206,8 +202,7 @@ public List<string> processRenderedScroll(Scroll rendered, List<string> hintUris
             var obj = ParameterDisplays.Find(x => x.transform.GetChild(0).GetComponent<RenderedScrollFact>().factUri.Equals(rendered.requiredFacts[i].@ref.uri));
 
             if (this.dynamicScrollDescriptionsActive)
-            {
-                //Update ScrollParameter label
+            {   //Update ScrollParameter label
                 obj.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label = rendered.requiredFacts[i].label;
             }
 
@@ -252,30 +247,17 @@ public void animateHint(GameObject scrollParameter, string scrollParameterUri) {
             fact = LatestRenderedHints.Find(x => x.Id.Equals(scrollParameterUri));
             var factId = fact.Id;
 
+            //Animate ScrollParameter
+            scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
+
             //If there is an equal existing fact -> Animate that fact AND ScrollParameter
             if (StageStatic.stage.factState.ContainsKey(factId))
-            {
-                Fact existingFact = StageStatic.stage.factState[factId];
-
-                //Animate ScrollParameter
-                scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
-                //Animate Fact in FactPanel
-                AnimateExistingFactEvent.Invoke(existingFact);
+            {   //Animate Fact in FactPanel
+                AnimateExistingFactEvent.Invoke(StageStatic.stage.factState[factId]);
             }
-            //If not -> Generate a Fact-Representation with such dependent facts
-            else
-            {
-                //Animate ScrollParameter
-                scrollParameter.GetComponentInChildren<ImageHintAnimation>().AnimationTrigger();
-                //Generate new FactRepresentation and animate it
+            else { //Generate new FactRepresentation and animate it
                 AnimateNonExistingFactEvent.Invoke(fact);
             }
         }
     }
-
-    public void animateScrollParameter(string label)
-    {
-        var obj = ParameterDisplays.Find(x => x.transform.GetChild(0).GetComponent<RenderedScrollFact>().Label == label);
-        obj.GetComponentInChildren<Animator>().SetTrigger("animateHint");
-    }
 }
diff --git a/Assets/Scripts/Loading/Loader.cs b/Assets/Scripts/Loading/Loader.cs
index 5dba6d61f38870bc2c7aeb3b51dac35daab4ecfc..a780e754551cec8eedc08afb9c7e4e16770da876 100644
--- a/Assets/Scripts/Loading/Loader.cs
+++ b/Assets/Scripts/Loading/Loader.cs
@@ -12,8 +12,6 @@ public static class Loader
     /// <summary> Defines last <see cref="Scene"/> loaded by this and/ or to be loaded when calling <see cref="LoaderCallback"/>.</summary>
     private static string nextscene;
 
-    private class MonoDummy : MonoBehaviour { };
-
     /// <summary>
     /// <c>return <see cref="loadingscene"/> == <see langword="null"/> ? 1f : <see cref="loadingscene"/>.progress;</c>
     /// </summary>
diff --git a/Assets/Scripts/TestScripts.meta b/Assets/Scripts/TestScripts.meta
new file mode 100644
index 0000000000000000000000000000000000000000..628a874c6a54449c3743dc96a9d63ef621dbc4de
--- /dev/null
+++ b/Assets/Scripts/TestScripts.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: 52ae36f76caa802468ca9d4b2ff72441
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Utility.meta b/Assets/Scripts/Utility.meta
new file mode 100644
index 0000000000000000000000000000000000000000..9f0e279f94f07dbc5779b2015deffa030b5ff6aa
--- /dev/null
+++ b/Assets/Scripts/Utility.meta
@@ -0,0 +1,8 @@
+fileFormatVersion: 2
+guid: f1f40d918407d2f4bbfbc0c6d52f34e7
+folderAsset: yes
+DefaultImporter:
+  externalObjects: {}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Extensions.meta b/Assets/Scripts/Utility/Extensions.meta
similarity index 100%
rename from Assets/Scripts/Extensions.meta
rename to Assets/Scripts/Utility/Extensions.meta
diff --git a/Assets/Scripts/Extensions/GameObjectExtensions.cs b/Assets/Scripts/Utility/Extensions/GameObjectExtensions.cs
similarity index 100%
rename from Assets/Scripts/Extensions/GameObjectExtensions.cs
rename to Assets/Scripts/Utility/Extensions/GameObjectExtensions.cs
diff --git a/Assets/Scripts/Extensions/GameObjectExtensions.cs.meta b/Assets/Scripts/Utility/Extensions/GameObjectExtensions.cs.meta
similarity index 100%
rename from Assets/Scripts/Extensions/GameObjectExtensions.cs.meta
rename to Assets/Scripts/Utility/Extensions/GameObjectExtensions.cs.meta
diff --git a/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs b/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs
new file mode 100644
index 0000000000000000000000000000000000000000..476c9f3948a2697448c1f4f60778220221bb9eed
--- /dev/null
+++ b/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs
@@ -0,0 +1,18 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+public static class IEnumeratorExtensions
+{
+    public static void FastForward(this IEnumerator that)
+    {
+        while(that.MoveNext()) ;
+    }
+
+    public static IEnumerator yield_break => _YieldBreak;
+    private static IEnumerator _YieldBreak = YieldBreak();
+    public static IEnumerator YieldBreak()
+    {
+        yield break;
+    }
+}
diff --git a/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs.meta b/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..e3e1c3619c7c891605b5aef0fe99c433a9b9d042
--- /dev/null
+++ b/Assets/Scripts/Utility/Extensions/IEnumeratorExtensions.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 9852cb26f72b49f4887f729152b672f0
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/Extensions/LayerMaskExtensions.cs b/Assets/Scripts/Utility/Extensions/LayerMaskExtensions.cs
similarity index 100%
rename from Assets/Scripts/Extensions/LayerMaskExtensions.cs
rename to Assets/Scripts/Utility/Extensions/LayerMaskExtensions.cs
diff --git a/Assets/Scripts/Extensions/LayerMaskExtensions.cs.meta b/Assets/Scripts/Utility/Extensions/LayerMaskExtensions.cs.meta
similarity index 100%
rename from Assets/Scripts/Extensions/LayerMaskExtensions.cs.meta
rename to Assets/Scripts/Utility/Extensions/LayerMaskExtensions.cs.meta
diff --git a/Assets/Scripts/Extensions/MathfExtensions.cs b/Assets/Scripts/Utility/Extensions/MathfExtensions.cs
similarity index 100%
rename from Assets/Scripts/Extensions/MathfExtensions.cs
rename to Assets/Scripts/Utility/Extensions/MathfExtensions.cs
diff --git a/Assets/Scripts/Extensions/MathfExtensions.cs.meta b/Assets/Scripts/Utility/Extensions/MathfExtensions.cs.meta
similarity index 100%
rename from Assets/Scripts/Extensions/MathfExtensions.cs.meta
rename to Assets/Scripts/Utility/Extensions/MathfExtensions.cs.meta
diff --git a/Assets/Scripts/Extensions/RendererExtensions.cs b/Assets/Scripts/Utility/Extensions/RendererExtensions.cs
similarity index 100%
rename from Assets/Scripts/Extensions/RendererExtensions.cs
rename to Assets/Scripts/Utility/Extensions/RendererExtensions.cs
diff --git a/Assets/Scripts/Extensions/RendererExtensions.cs.meta b/Assets/Scripts/Utility/Extensions/RendererExtensions.cs.meta
similarity index 100%
rename from Assets/Scripts/Extensions/RendererExtensions.cs.meta
rename to Assets/Scripts/Utility/Extensions/RendererExtensions.cs.meta
diff --git a/Assets/Scripts/Utility/Graph.cs b/Assets/Scripts/Utility/Graph.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b488114e5cb97edcf888eafe36658e99357a96ad
--- /dev/null
+++ b/Assets/Scripts/Utility/Graph.cs
@@ -0,0 +1,106 @@
+
+/// <summary>
+/// Source: https://www.geeksforgeeks.org/topological-sorting/
+/// </summary>
+namespace geeksforgeeks
+{
+	// A C# program to print topological
+	// sorting of a DAG
+	using System;
+	using System.Collections.Generic;
+
+	// This class represents a directed graph
+	// using adjacency list representation
+	class Graph
+	{
+
+		// No. of vertices
+		private readonly int V;
+
+		// Adjacency List as ArrayList
+		// of ArrayList's
+		private List<List<int>> adj;
+
+		// Constructor
+		Graph(int v)
+		{
+			V = v;
+			adj = new List<List<int>>(v);
+			for (int i = 0; i < v; i++)
+				adj.Add(new List<int>());
+		}
+
+		// Function to add an edge into the graph
+		public void AddEdge(int v, int w) { adj[v].Add(w); }
+
+		// A recursive function used by topologicalSort
+		void TopologicalSortUtil(int v, bool[] visited,
+								Stack<int> stack)
+		{
+
+			// Mark the current node as visited.
+			visited[v] = true;
+
+			// Recur for all the vertices
+			// adjacent to this vertex
+			foreach (var vertex in adj[v])
+			{
+				if (!visited[vertex])
+					TopologicalSortUtil(vertex, visited, stack);
+			}
+
+			// Push current vertex to
+			// stack which stores result
+			stack.Push(v);
+		}
+
+		// The function to do Topological Sort.
+		// It uses recursive topologicalSortUtil()
+		void TopologicalSort()
+		{
+			Stack<int> stack = new Stack<int>();
+
+			// Mark all the vertices as not visited
+			var visited = new bool[V];
+
+			// Call the recursive helper function
+			// to store Topological Sort starting
+			// from all vertices one by one
+			for (int i = 0; i < V; i++)
+			{
+				if (visited[i] == false)
+					TopologicalSortUtil(i, visited, stack);
+			}
+
+			// Print contents of stack
+			foreach (var vertex in stack)
+			{
+				Console.Write(vertex + " ");
+			}
+		}
+
+		// Driver code
+		public static void Main(string[] args)
+		{
+
+			// Create a graph given
+			// in the above diagram
+			Graph g = new Graph(6);
+			g.AddEdge(5, 2);
+			g.AddEdge(5, 0);
+			g.AddEdge(4, 0);
+			g.AddEdge(4, 1);
+			g.AddEdge(2, 3);
+			g.AddEdge(3, 1);
+
+			Console.WriteLine("Following is a Topological "
+							+ "sort of the given graph");
+
+			// Function Call
+			g.TopologicalSort();
+		}
+	}
+
+	// This code is contributed by Abhinav Galodha
+
+}
diff --git a/Assets/Scripts/Utility/Graph.cs.meta b/Assets/Scripts/Utility/Graph.cs.meta
new file mode 100644
index 0000000000000000000000000000000000000000..a0550e9b2b0cea800b3ffd5c2c3a7e7f2252df22
--- /dev/null
+++ b/Assets/Scripts/Utility/Graph.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: d87236740cbbf894fbeb2129ea06eccc
+MonoImporter:
+  externalObjects: {}
+  serializedVersion: 2
+  defaultReferences: []
+  executionOrder: 0
+  icon: {instanceID: 0}
+  userData: 
+  assetBundleName: 
+  assetBundleVariant: 
diff --git a/Assets/Scripts/IJSONsavable.cs b/Assets/Scripts/Utility/IJSONsavable.cs
similarity index 100%
rename from Assets/Scripts/IJSONsavable.cs
rename to Assets/Scripts/Utility/IJSONsavable.cs
diff --git a/Assets/Scripts/IJSONsavable.cs.meta b/Assets/Scripts/Utility/IJSONsavable.cs.meta
similarity index 100%
rename from Assets/Scripts/IJSONsavable.cs.meta
rename to Assets/Scripts/Utility/IJSONsavable.cs.meta
diff --git a/Assets/Scripts/Math3d.cs b/Assets/Scripts/Utility/Math3d.cs
similarity index 99%
rename from Assets/Scripts/Math3d.cs
rename to Assets/Scripts/Utility/Math3d.cs
index b57c145ea2cdcc7c5bbd54de6195d19ebc19f60a..613a3c4eb4fa37fbb87f725f7a0252282f39675d 100644
--- a/Assets/Scripts/Math3d.cs
+++ b/Assets/Scripts/Utility/Math3d.cs
@@ -538,13 +538,12 @@ public static bool IsPointOnLine(Vector3 linePoint, Vector3 lineVec, Vector3 poi
     //The line is regarded as being infinite.
     public static bool IsPointApproximatelyOnLine(Vector3 linePoint, Vector3 lineVec, Vector3 point, double precission = Math3d.vectorPrecission)
     {
-
         //get vector from point on line to point in space
         Vector3 linePointToPoint = point - linePoint;
 
-        double t = Vector3.Dot(linePointToPoint.normalized, lineVec);
+        double t = Math.Abs(Vector3.Dot(linePointToPoint.normalized, lineVec)); // expected to be ~1
 
-        return Math.Abs(Math.Abs(t) - 1d) < precission || Math.Abs(t) < precission;
+        return Math.Cos(precission) < t;
     }
 
     //This function returns true if two Vector3s are approximately parallel
diff --git a/Assets/Scripts/Math3d.cs.meta b/Assets/Scripts/Utility/Math3d.cs.meta
similarity index 100%
rename from Assets/Scripts/Math3d.cs.meta
rename to Assets/Scripts/Utility/Math3d.cs.meta
diff --git a/ProjectSettings/BurstAotSettings_Android.json b/ProjectSettings/BurstAotSettings_Android.json
new file mode 100644
index 0000000000000000000000000000000000000000..771d37b73d4522914996afdb6b138e3338c5f368
--- /dev/null
+++ b/ProjectSettings/BurstAotSettings_Android.json
@@ -0,0 +1,14 @@
+{
+  "MonoBehaviour": {
+    "Version": 4,
+    "EnableBurstCompilation": true,
+    "EnableOptimisations": true,
+    "EnableSafetyChecks": false,
+    "EnableDebugInAllBuilds": false,
+    "CpuMinTargetX32": 0,
+    "CpuMaxTargetX32": 0,
+    "CpuMinTargetX64": 0,
+    "CpuMaxTargetX64": 0,
+    "OptimizeFor": 0
+  }
+}
diff --git a/Unity.gitignore b/Unity.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..72c27e4fe2f066bd5cbace2c924414175bd454ec
--- /dev/null
+++ b/Unity.gitignore
@@ -0,0 +1,71 @@
+# This .gitignore file should be placed at the root of your Unity project directory
+#
+# Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore
+#
+/[Ll]ibrary/
+/[Tt]emp/
+/[Oo]bj/
+/[Bb]uild/
+/[Bb]uilds/
+/[Ll]ogs/
+/[Uu]ser[Ss]ettings/
+
+# MemoryCaptures can get excessive in size.
+# They also could contain extremely sensitive data
+/[Mm]emoryCaptures/
+
+# Asset meta data should only be ignored when the corresponding asset is also ignored
+!/[Aa]ssets/**/*.meta
+
+# Uncomment this line if you wish to ignore the asset store tools plugin
+# /[Aa]ssets/AssetStoreTools*
+
+# Autogenerated Jetbrains Rider plugin
+/[Aa]ssets/Plugins/Editor/JetBrains*
+
+# Visual Studio cache directory
+.vs/
+
+# Gradle cache directory
+.gradle/
+
+# Autogenerated VS/MD/Consulo solution and project files
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+*.mdb
+*.opendb
+*.VC.db
+
+# Unity3D generated meta files
+*.pidb.meta
+*.pdb.meta
+*.mdb.meta
+
+# Unity3D generated file on crash reports
+sysinfo.txt
+
+# Builds
+*.apk
+*.aab
+*.unitypackage
+
+# Crashlytics generated file
+crashlytics-build.properties
+
+# Packed Addressables
+/[Aa]ssets/[Aa]ddressable[Aa]ssets[Dd]ata/*/*.bin*
+
+# Temporary auto-generated Android Assets
+/[Aa]ssets/[Ss]treamingAssets/aa.meta
+/[Aa]ssets/[Ss]treamingAssets/aa/*
diff --git a/Windows.gitignore b/Windows.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..84bffec74db3273565f4c9b3e9ffcc216cec1611
--- /dev/null
+++ b/Windows.gitignore
@@ -0,0 +1,24 @@
+# Windows thumbnail cache files
+Thumbs.db
+Thumbs.db:encryptable
+ehthumbs.db
+ehthumbs_vista.db
+
+# Dump file
+*.stackdump
+
+# Folder config file
+[Dd]esktop.ini
+
+# Recycle Bin used on file shares
+$RECYCLE.BIN/
+
+# Windows Installer files
+*.cab
+*.msi
+*.msix
+*.msm
+*.msp
+
+# Windows shortcuts
+*.lnk
diff --git a/macOS.gitignore b/macOS.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..135767fc075ec33f7f9966fb28968113e32b697e
--- /dev/null
+++ b/macOS.gitignore
@@ -0,0 +1,26 @@
+# General
+.DS_Store
+.AppleDouble
+.LSOverride
+
+# Icon must end with two \r
+Icon

+
+# Thumbnails
+._*
+
+# Files that might appear in the root of a volume
+.DocumentRevisions-V100
+.fseventsd
+.Spotlight-V100
+.TemporaryItems
+.Trashes
+.VolumeIcon.icns
+.com.apple.timemachine.donotpresent
+
+# Directories potentially created on remote AFP share
+.AppleDB
+.AppleDesktop
+Network Trash Folder
+Temporary Items
+.apdisk