├── .gitignore ├── Assets ├── Editor.meta ├── Editor │ ├── OTIEditorBase.cs │ ├── OTIEditorBase.cs.meta │ ├── OTIEditorUtility.cs │ ├── OTIEditorUtility.cs.meta │ ├── WorldMonitorsEditor.cs │ └── WorldMonitorsEditor.cs.meta ├── Gizmos.meta ├── Gizmos │ ├── marker.tif │ └── marker.tif.meta ├── License.meta ├── License │ ├── UnityOctree.meta │ └── UnityOctree │ │ ├── LICENCE │ │ ├── LICENCE.meta │ │ ├── README.md │ │ └── README.md.meta ├── Materials.meta ├── Materials │ ├── Black.mat │ ├── Black.mat.meta │ ├── Blue.mat │ ├── Blue.mat.meta │ ├── Bright.mat │ ├── Bright.mat.meta │ ├── ChocBlk.mat │ ├── ChocBlk.mat.meta │ ├── Dark Transparent.mat │ ├── Dark Transparent.mat.meta │ ├── Light Blue.mat │ ├── Light Blue.mat.meta │ ├── Lime Green.mat │ ├── Lime Green.mat.meta │ ├── Orange.mat │ ├── Orange.mat.meta │ ├── Pink.mat │ ├── Pink.mat.meta │ ├── Purple.mat │ ├── Purple.mat.meta │ ├── Yellow.mat │ └── Yellow.mat.meta ├── OTIJob.cs ├── OTIJob.cs.meta ├── OTIUtilities.cs ├── OTIUtilities.cs.meta ├── Octree.meta ├── Octree │ ├── Octree.cs │ └── Octree.cs.meta ├── Scenes.meta ├── Scenes │ ├── Example Scenes.meta │ └── Example Scenes │ │ ├── ExampleNavigator.cs │ │ ├── ExampleNavigator.cs.meta │ │ ├── SmallTrackingExample.unity │ │ ├── SmallTrackingExample.unity.meta │ │ ├── Tracker.cs │ │ ├── Tracker.cs.meta │ │ ├── TrackingExample.unity │ │ └── TrackingExample.unity.meta ├── TrackedObjectTriggers.cs ├── TrackedObjectTriggers.cs.meta ├── UnityOctree.meta ├── UnityOctree │ ├── BoundsOctree.cs │ ├── BoundsOctree.cs.meta │ ├── BoundsOctreeNode.cs │ ├── BoundsOctreeNode.cs.meta │ ├── PointOctree.cs │ ├── PointOctree.cs.meta │ ├── PointOctreeNode.cs │ └── PointOctreeNode.cs.meta ├── WorldMonitor.cs ├── WorldMonitor.cs.meta ├── WorldMonitors.cs └── WorldMonitors.cs.meta ├── Images ├── 20k.PNG ├── exampleTrack.PNG ├── inspInitial.PNG ├── inspSymmetricObjects.PNG ├── smallScene.PNG ├── trackingScene.PNG ├── triggerVsOctreeConflict.PNG └── worldMonitor.PNG ├── LICENSE ├── Packages └── manifest.json ├── ProjectSettings ├── AudioManager.asset ├── ClusterInputManager.asset ├── DynamicsManager.asset ├── EditorBuildSettings.asset ├── EditorSettings.asset ├── GraphicsSettings.asset ├── InputManager.asset ├── NavMeshAreas.asset ├── NetworkManager.asset ├── Physics2DSettings.asset ├── PresetManager.asset ├── ProjectSettings.asset ├── ProjectVersion.txt ├── QualitySettings.asset ├── TagManager.asset ├── TimeManager.asset └── UnityConnectSettings.asset ├── README.md └── THIRD_PARTY_NOTICES.md /.gitignore: -------------------------------------------------------------------------------- 1 | [Ll]ibrary/ 2 | [Tt]emp/ 3 | [Oo]bj/ 4 | [Bb]uild/ 5 | [Bb]uilds/ 6 | Assets/AssetStoreTools* 7 | 8 | # Visual Studio cache directory 9 | .vs/ 10 | 11 | # Autogenerated VS/MD/Consulo solution and project files 12 | ExportedObj/ 13 | .consulo/ 14 | *.csproj 15 | *.unityproj 16 | *.sln 17 | *.suo 18 | *.tmp 19 | *.user 20 | *.userprefs 21 | *.pidb 22 | *.booproj 23 | *.svd 24 | *.pdb 25 | *.opendb 26 | 27 | # Unity3D generated meta files 28 | *.pidb.meta 29 | *.pdb.meta 30 | 31 | # Unity3D Generated File On Crash Reports 32 | sysinfo.txt 33 | 34 | # Builds 35 | *.apk 36 | *.unitypackage 37 | -------------------------------------------------------------------------------- /Assets/Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9c657c6e0fb80574cae875ec85a97935 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Editor/OTIEditorBase.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | using UnityEditor; 5 | using oti.AI; 6 | 7 | namespace oti.Editors 8 | { 9 | /// 10 | /// This class is part of a much larger repository, not all of this may be used here. 11 | /// Feel free to use them if you wish. 12 | /// 13 | public class OTIEditorBase : Editor 14 | { 15 | public void Enable() 16 | { 17 | if (!OTIEditorUtility.Instance) 18 | { 19 | OTIEditorUtility AIE = ScriptableObject.CreateInstance(); 20 | OTIEditorUtility.Instance = AIE; 21 | } 22 | 23 | EditorFormat = OTIEditorFormat._ReturnSet(this, "The component that factors into this behavior's cost during decision making"); 24 | setFormats(); 25 | } 26 | 27 | public void spaces(int numberOfSpaces) 28 | { 29 | for (int i = 0; i < numberOfSpaces; i++) 30 | EditorGUILayout.Space(); 31 | } 32 | 33 | public OTIEditorFormat EditorFormat; 34 | public GUIStyle headingStyle; 35 | public GUIStyle subHeadingStyle; 36 | public GUIStyle guiStyle; 37 | public GUIStyle contentStyle; 38 | public GUIContent guiContent; 39 | public GUIContent gtSuccess; 40 | public GUIContent gtFailure; 41 | public GUIContent gtDestinations; 42 | 43 | void setFormats() 44 | { 45 | headingStyle = EditorFormat.HeaderFormat; 46 | subHeadingStyle = EditorFormat.SubHeaderFormat; 47 | contentStyle = EditorFormat.ContentStyle; 48 | 49 | guiStyle = new GUIStyle 50 | { 51 | fontSize = 16, 52 | fontStyle = FontStyle.Bold 53 | }; 54 | 55 | guiContent = new GUIContent 56 | { 57 | text = " Costs", 58 | tooltip = "The component that factors into this behavior's cost during decision making" 59 | }; 60 | 61 | gtSuccess = new GUIContent 62 | { 63 | text = "Successes", 64 | }; 65 | 66 | gtFailure = new GUIContent 67 | { 68 | text = " Failures", 69 | }; 70 | 71 | gtDestinations = new GUIContent 72 | { 73 | text = "Destinations", 74 | }; 75 | 76 | headingStyle.normal.textColor = OTIEditorFormat.OTINavy; 77 | contentStyle.normal.textColor = OTIEditorFormat.OTINavy; 78 | } 79 | 80 | public static string _WorldMonitoringExplanation = "Use this utility to give the agent awareness of events going on in the environment."; 81 | 82 | public static string _WorldMonitorSingleton = "The World Monitor: choose the parameters for your tracking system here."; 83 | } 84 | 85 | public struct OTIEditorFormat 86 | { 87 | public GUIStyle HeaderFormat; 88 | public GUIStyle SubHeaderFormat; 89 | public GUIStyle ContentStyle; 90 | public GUIContent GUIText; 91 | public static Color OTINavy = new Color(0, 0, 0.42f, 1); 92 | public static Color OTIOrange = new Color(1, 0.45f, 0, 1); 93 | 94 | public static OTIEditorFormat _ReturnSet(object sender, string _tooltip, int overrideFontSize = default(int)) 95 | { 96 | OTIEditorFormat ef = new OTIEditorFormat(); 97 | bool overFont = overrideFontSize != default(int); 98 | ef.HeaderFormat = new GUIStyle 99 | { 100 | fontSize = overFont ? overrideFontSize : 15, 101 | fontStyle = FontStyle.Bold, 102 | alignment = TextAnchor.MiddleCenter 103 | }; 104 | ef.SubHeaderFormat = new GUIStyle 105 | { 106 | fontSize = overFont ? overrideFontSize : 14, 107 | alignment = TextAnchor.LowerLeft, 108 | fontStyle = FontStyle.Bold, 109 | wordWrap = true 110 | }; 111 | ef.ContentStyle = new GUIStyle 112 | { 113 | fontSize = 11, 114 | alignment = TextAnchor.MiddleLeft, 115 | wordWrap = true 116 | }; 117 | ef.GUIText = new GUIContent 118 | { 119 | text = sender.ToString(), 120 | tooltip = _tooltip 121 | }; 122 | return ef; 123 | } 124 | } 125 | } 126 | 127 | -------------------------------------------------------------------------------- /Assets/Editor/OTIEditorBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 15911c7ddd311bf448347301b984de4a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Editor/OTIEditorUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEditor; 3 | using UnityEngine; 4 | using System.Collections.Generic; 5 | using oti.Editors; 6 | 7 | namespace oti.AI 8 | { 9 | /// 10 | /// This class is part of a much larger repository, many of these methods are not used in this repo. 11 | /// Feel free to use them if you wish. 12 | /// 13 | public class OTIEditorUtility : Editor 14 | { 15 | /// 16 | /// Singleton implementation 17 | /// 18 | private static OTIEditorUtility _instance = null; 19 | 20 | public static OTIEditorUtility Instance 21 | { 22 | get 23 | { 24 | return _instance; 25 | } 26 | set 27 | { 28 | _instance = value; 29 | } 30 | } 31 | 32 | public void OnEnable() 33 | { 34 | if (_instance != null && _instance != this) 35 | { 36 | DestroyImmediate(this); 37 | return; 38 | } 39 | if (headingStyle == null) 40 | setFormats(); 41 | } 42 | 43 | public static void _Enable() 44 | { 45 | _instance = new OTIEditorUtility(); 46 | } 47 | 48 | /// 49 | /// Style used for OTI headers 50 | /// 51 | private GUIStyle headingStyle; 52 | 53 | /// 54 | /// Style used for inspector content 55 | /// 56 | private GUIStyle contentStyle; 57 | 58 | /// 59 | /// Places consistent format title on each OTI inspector. 60 | /// 61 | public void OTIHead(string title, string explanation, int padding = default(int)) 62 | { 63 | spaces(2); 64 | 65 | if (headingStyle == null) 66 | setFormats(); 67 | 68 | headingStyle.normal.textColor = OTIEditorFormat.OTINavy; 69 | Color ctemp = contentStyle.normal.textColor; 70 | contentStyle.normal.textColor = OTIEditorFormat.OTINavy; 71 | 72 | EditorGUILayout.LabelField("| " + title + " |", headingStyle); 73 | contentStyle.fontStyle = FontStyle.Italic; 74 | EditorGUILayout.LabelField(explanation, contentStyle); 75 | contentStyle.fontStyle = FontStyle.Normal; 76 | 77 | contentStyle.normal.textColor = ctemp; 78 | spaces(padding); 79 | } 80 | 81 | void setFormats() 82 | { 83 | headingStyle = new GUIStyle 84 | { 85 | fontSize = 15, 86 | fontStyle = FontStyle.Bold, 87 | alignment = TextAnchor.MiddleCenter 88 | }; 89 | contentStyle = new GUIStyle 90 | { 91 | fontSize = 11, 92 | alignment = TextAnchor.MiddleLeft, 93 | wordWrap = true 94 | }; 95 | } 96 | 97 | private void spaces(int numberOfSpaces) 98 | { 99 | for(int i = 0; i < numberOfSpaces; i++) 100 | EditorGUILayout.Space(); 101 | } 102 | 103 | /// 104 | /// Places a horizontal bar in editor. 105 | /// 106 | /// (opt) Places bold text directly above bar. 107 | /// (opt) Helpful for elaborating on the title. 108 | /// (opt for title - default = 2) 109 | public void HorizontalLine(string titleBar = default(string), string appendedText = default(string), int padding = 2) 110 | { 111 | spaces(2); 112 | GUIStyle TitleStyle = new GUIStyle 113 | { 114 | fontSize = 9, 115 | fontStyle = FontStyle.Bold, 116 | alignment = TextAnchor.LowerLeft 117 | }; 118 | if(titleBar != default(string)) 119 | { 120 | spaces(padding); 121 | EditorGUILayout.LabelField(titleBar, TitleStyle); 122 | } 123 | 124 | EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); 125 | if(appendedText != default(string)) 126 | { 127 | Color cTemp = contentStyle.normal.textColor; 128 | contentStyle.normal.textColor = OTIEditorFormat.OTINavy; 129 | EditorGUILayout.LabelField(appendedText, contentStyle); 130 | contentStyle.normal.textColor = cTemp; 131 | spaces(1); 132 | } 133 | } 134 | 135 | /// 136 | /// Places a horizontal bar in editor with a float property. 137 | /// 138 | /// (opt) Places bold text directly above bar. 139 | /// (opt) Helpful for elaborating on the title. 140 | /// (opt for title - default = 2) 141 | public void HorizontalLineProperty(ref List components, int index, string titleBar = default(string), string fieldTitle = default(string), string appendedText = default(string), int padding = 2) 142 | { 143 | spaces(2); 144 | EditorGUIUtility.fieldWidth = 42; 145 | 146 | GUIStyle TitleStyle = new GUIStyle 147 | { 148 | fontSize = 9, 149 | fontStyle = FontStyle.Bold, 150 | alignment = TextAnchor.MiddleLeft 151 | }; 152 | 153 | if (titleBar != default(string)) 154 | { 155 | spaces(padding); 156 | EditorGUILayout.BeginHorizontal(); 157 | EditorGUILayout.LabelField(titleBar, TitleStyle); 158 | 159 | TitleStyle.alignment = TextAnchor.MiddleRight; 160 | TitleStyle.fontStyle = FontStyle.Normal; 161 | 162 | EditorGUILayout.PrefixLabel(fieldTitle, TitleStyle); 163 | components[index] = EditorGUILayout.FloatField(components[index]); 164 | EditorGUILayout.EndHorizontal(); 165 | } 166 | 167 | EditorGUILayout.LabelField("", GUI.skin.horizontalSlider); 168 | if (appendedText != default(string)) 169 | { 170 | Color cTemp = contentStyle.normal.textColor; 171 | contentStyle.normal.textColor = OTIEditorFormat.OTINavy; 172 | EditorGUILayout.LabelField(appendedText, contentStyle); 173 | contentStyle.normal.textColor = cTemp; 174 | spaces(1); 175 | } 176 | } 177 | 178 | } 179 | } -------------------------------------------------------------------------------- /Assets/Editor/OTIEditorUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff2b0c03a4895475bbb554a95947de6e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Editor/WorldMonitorsEditor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using UnityEditor; 4 | using oti.AI; 5 | using oti.Editors; 6 | using oti.Utilities; 7 | 8 | namespace oti.Editors 9 | { 10 | [CanEditMultipleObjects] 11 | [CustomEditor(typeof(WorldMonitors))] 12 | public class WorldMonitorsEditor : OTIEditorBase 13 | { 14 | /// 15 | /// Number of distinct tracked object fields 16 | /// 17 | private int numberTrackedFields; 18 | 19 | /// 20 | /// A limit imposed for performance. 21 | /// 22 | private int maxNumberTrackedFields; 23 | 24 | /// 25 | /// Used to determine if field inspector should be exposed 26 | /// 27 | bool[] show = new bool[701]; //limit 701 sets of tracked objects 28 | 29 | /// 30 | /// Access to components in WorldMonitors 31 | /// 32 | WorldMonitors instance; 33 | 34 | private void OnEnable() 35 | { 36 | instance = target as WorldMonitors; 37 | 38 | maxNumberTrackedFields = show.Length; 39 | numberTrackedFields = Mathf.Max(1, numberTrackedFields); 40 | 41 | if (instance.TrackedObjects.Count == 0) 42 | instance.TrackedObjects.Add(new TrackedObjectContainer()); 43 | 44 | base.Enable(); 45 | if (!OTIEditorUtility.Instance) 46 | { 47 | OTIEditorUtility AIE = ScriptableObject.CreateInstance(); 48 | OTIEditorUtility.Instance = AIE; 49 | } 50 | 51 | serializedObject.ApplyModifiedProperties(); 52 | } 53 | 54 | public override void OnInspectorGUI() 55 | { 56 | OTIEditorUtility.Instance.OTIHead("Agent World Monitoring", _WorldMonitoringExplanation); 57 | OTIEditorUtility.Instance.HorizontalLine(); 58 | 59 | numberTrackedFields = Mathf.Max(1, instance.TrackedObjects.Count); 60 | 61 | if (numberTrackedFields >= 701) 62 | Debug.LogWarning("701 tracked fields is the limit, additional fields must be added at runtime."); 63 | 64 | if (instance.TrackedObjects.Count == 0) 65 | instance.TrackedObjects.Add(new TrackedObjectContainer()); 66 | 67 | if (instance.ThresholdSet.Count == 0) 68 | instance.ThresholdSet.Add(new float()); 69 | 70 | addMinusIntValueButtons(ref numberTrackedFields, ref instance.TrackedObjects, ref instance.ThresholdSet, "Add Tracked Field", "Remove Tracked Field", maxNumber: maxNumberTrackedFields); 71 | 72 | if (instance.ThresholdSet.Count > 0) 73 | { 74 | float tThreshold = instance.ThresholdSet[0]; 75 | OTIEditorUtility.Instance.HorizontalLineProperty(ref instance.ThresholdSet, 0, "Tracked Object Set A", "Threshold Distance A", "Assign objects for tracking against each other. Set A will be tracked against all others."); 76 | trackedObjectListManager(0, guiContent, headingStyle, subHeadingStyle, "", "Tracked Objects", ref show[0], padding: 1); 77 | 78 | if (instance.ThresholdSet[0] != tThreshold) 79 | enforceStaticThreshold(0, instance.ThresholdSet[0]); 80 | 81 | for (int i = 1; i < numberTrackedFields; i++) 82 | { 83 | tThreshold = instance.ThresholdSet[i]; 84 | OTIEditorUtility.Instance.HorizontalLineProperty(ref instance.ThresholdSet, i, "Tracked Object Set " + OTIUtilities._AlphabetAssembler(i), "Threshold Distance " + OTIUtilities._AlphabetAssembler(i), "Assign objects for tracking against each other. Set " + OTIUtilities._AlphabetAssembler(i) + " will be tracked against all others."); 85 | trackedObjectListManager(i, guiContent, headingStyle, subHeadingStyle, "", "Tracked Objects", ref show[i], padding: 1); 86 | serializedObject.ApplyModifiedProperties(); 87 | 88 | if (instance.ThresholdSet[i] != tThreshold) 89 | enforceStaticThreshold(i, instance.ThresholdSet[i]); 90 | } 91 | } 92 | 93 | serializedObject.ApplyModifiedProperties(); 94 | } 95 | 96 | /// 97 | /// Ensures threshold sizes are consistent across all instances 98 | /// 99 | private void enforceStaticThreshold(int index, float threshold) 100 | { 101 | WorldMonitors[] agentMonitors = GameObject.FindObjectsOfType(); 102 | 103 | for (int i = 0; i < agentMonitors.Length; i++) 104 | { 105 | if (index < agentMonitors[i].ThresholdSet.Count) 106 | agentMonitors[i].ThresholdSet[index] = threshold; 107 | } 108 | } 109 | 110 | 111 | /// 112 | /// Similar to method in AIEditor class but modified for WorldMonitors. 113 | /// 114 | /// Current index of TrackedObjects list. 115 | private void trackedObjectListManager(int i, GUIContent guiText, GUIStyle headingStyle, GUIStyle subHeadingStyle, string typeOfFactor, string head, ref bool showField, int padding = default(int)) 116 | { 117 | Rect plotSpace = new Rect(); 118 | plotSpace = GUILayoutUtility.GetLastRect(); 119 | 120 | float viewWidth = EditorGUIUtility.currentViewWidth; 121 | plotSpace = new Rect(0, plotSpace.yMax + 2, 500, 1000); 122 | 123 | GUIStyle gs = headingStyle; 124 | Color ogc = gs.normal.textColor; 125 | gs.alignment = TextAnchor.MiddleLeft; 126 | 127 | EditorGUILayout.BeginHorizontal(); 128 | 129 | string buttonDisp = showField ? "-" : "+"; 130 | bool input = GUILayout.Button(buttonDisp, EditorStyles.miniButton, GUILayout.Width(42)); 131 | EditorGUILayout.LabelField(head, subHeadingStyle); 132 | EditorGUILayout.EndHorizontal(); 133 | 134 | if (input && showField) 135 | { 136 | showField = false; 137 | EditorGUILayout.EndHorizontal(); 138 | } 139 | else if (input || showField) 140 | { 141 | showField = true; 142 | GUILayoutOption miniButtonWidth = GUILayout.Width(viewWidth / 2 - 20); 143 | EditorGUILayout.BeginHorizontal(); 144 | 145 | if (GUILayout.Button("Add " + typeOfFactor, EditorStyles.miniButton, miniButtonWidth)) 146 | { 147 | instance.TrackedObjects[i].TrackedObjects.Add(null); 148 | } 149 | 150 | if (GUILayout.Button("Delete " + typeOfFactor, EditorStyles.miniButton, miniButtonWidth)) 151 | { 152 | if (instance.TrackedObjects[i].TrackedObjects.Count - 1 >= 0) 153 | instance.TrackedObjects[i].TrackedObjects.RemoveAt(instance.TrackedObjects[i].TrackedObjects.Count - 1); 154 | } 155 | 156 | EditorGUILayout.EndHorizontal(); 157 | for (int j = 0; j < instance.TrackedObjects[i].TrackedObjects.Count; j++) 158 | { 159 | EditorGUILayout.BeginHorizontal(); 160 | instance.TrackedObjects[i].TrackedObjects[j] = (GameObject)EditorGUILayout.ObjectField(instance.TrackedObjects[i].TrackedObjects[j], typeof(GameObject), true);//EditorGUILayout.PropertyField(so, new GUIContent(typeOfFactor), true); 161 | EditorGUILayout.EndHorizontal(); 162 | } 163 | } 164 | 165 | gs.normal.textColor = ogc; 166 | gs.alignment = TextAnchor.MiddleCenter; 167 | spaces(numberOfSpaces: padding); 168 | } 169 | 170 | /// 171 | /// Similar to method in AIEditor class but modified for WorldMonitors. 172 | /// 173 | private void addMinusIntValueButtons(ref int intComponent, ref List p1, ref List p2, string addButtonLabel = default(string), string minusButtonLabel = default(string), int minNumber = 1, int maxNumber = 4) 174 | { 175 | if (intComponent == maxNumber) 176 | return; 177 | 178 | addButtonLabel = addButtonLabel == default(string) ? "+" : addButtonLabel; 179 | minusButtonLabel = minusButtonLabel == default(string) ? "-" : minusButtonLabel; 180 | 181 | EditorGUILayout.BeginHorizontal(); 182 | if (GUILayout.Button(addButtonLabel, EditorStyles.miniButtonLeft, GUILayout.Width(142))) 183 | { 184 | p1.Add(new TrackedObjectContainer()); 185 | p2.Add(new float()); 186 | intComponent += 1; 187 | } 188 | 189 | if (GUILayout.Button(minusButtonLabel, EditorStyles.miniButtonRight, GUILayout.Width(142)) && intComponent != minNumber - 1) 190 | { 191 | p1.RemoveAt(p1.Count - 1); 192 | p2.RemoveAt(p2.Count - 1); 193 | intComponent -= 1; 194 | } 195 | EditorGUILayout.EndHorizontal(); 196 | } 197 | } 198 | } -------------------------------------------------------------------------------- /Assets/Editor/WorldMonitorsEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0c17e869e55910e439359242288ae258 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Gizmos.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ef897eb1e3ed2e94d93e0ec89883675b 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Gizmos/marker.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Assets/Gizmos/marker.tif -------------------------------------------------------------------------------- /Assets/Gizmos/marker.tif.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1107feee395f6bf449de6678527683c0 3 | timeCreated: 1481513783 4 | licenseType: Pro 5 | TextureImporter: 6 | fileIDToRecycleName: {} 7 | serializedVersion: 2 8 | mipmaps: 9 | mipMapMode: 0 10 | enableMipMap: 1 11 | linearTexture: 0 12 | correctGamma: 0 13 | fadeOut: 0 14 | borderMipMap: 0 15 | mipMapFadeDistanceStart: 1 16 | mipMapFadeDistanceEnd: 3 17 | bumpmap: 18 | convertToNormalMap: 0 19 | externalNormalMap: 0 20 | heightScale: 0.25 21 | normalMapFilter: 0 22 | isReadable: 0 23 | grayScaleToAlpha: 0 24 | generateCubemap: 0 25 | cubemapConvolution: 0 26 | cubemapConvolutionSteps: 7 27 | cubemapConvolutionExponent: 1.5 28 | seamlessCubemap: 0 29 | textureFormat: -1 30 | maxTextureSize: 2048 31 | textureSettings: 32 | filterMode: -1 33 | aniso: -1 34 | mipBias: -1 35 | wrapMode: -1 36 | nPOTScale: 1 37 | lightmap: 0 38 | rGBM: 0 39 | compressionQuality: 50 40 | allowsAlphaSplitting: 0 41 | spriteMode: 0 42 | spriteExtrude: 1 43 | spriteMeshType: 1 44 | alignment: 0 45 | spritePivot: {x: 0.5, y: 0.5} 46 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 47 | spritePixelsToUnits: 100 48 | alphaIsTransparency: 0 49 | spriteTessellationDetail: -1 50 | textureType: -1 51 | buildTargetSettings: [] 52 | spriteSheet: 53 | serializedVersion: 2 54 | sprites: [] 55 | outline: [] 56 | spritePackingTag: 57 | userData: 58 | assetBundleName: 59 | assetBundleVariant: 60 | -------------------------------------------------------------------------------- /Assets/License.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f304f146495c9c34c8edfff896cdaf72 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/License/UnityOctree.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 51f605a23c45c584685d0c696fc6f5d8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/License/UnityOctree/LICENCE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, Nition 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 18 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 21 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 22 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /Assets/License/UnityOctree/LICENCE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eca63f5432115bf49955c8431cc5852f 3 | timeCreated: 1481513782 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/License/UnityOctree/README.md: -------------------------------------------------------------------------------- 1 | UnityOctree 2 | =========== 3 | 4 | A dynamic octree implementation for Unity written in C#. 5 | Originally written for my game [Scraps](http://www.scrapsgame.com) but intended to be general-purpose. 6 | 7 | There are two octree implementations here: 8 | **BoundsOctree** stores any type of object, with the object boundaries defined as an axis-aligned bounding box. It's a dynamic octree and can also be a loose octree. 9 | **PointOctree** is the same basic implementation, but stores objects as a point in space instead of bounds. This allows some simplification of the code. It's a dynamic octree as well. 10 | 11 | **Octree:** An octree a tree data structure which divides 3D space into smaller partitions (nodes) and places objects into the appropriate nodes. This allows fast access to objects in an area of interest without having to check every object. 12 | 13 | **Dynamic:** The octree grows or shrinks as required when objects are added or removed. It also splits and merges nodes as appropriate. There is no maximum depth. Nodes have a constant (*numObjectsAllowed*) which sets the amount of items allowed in a node before it splits. 14 | 15 | **Loose:** The octree's nodes can be larger than 1/2 their parent's length and width, so they overlap to some extent. This can alleviate the problem of even tiny objects ending up in large nodes if they're near boundaries. A looseness value of 1.0 will make it a "normal" octree. 16 | 17 | **A few functions are implemented:** 18 | 19 | With BoundsOctree, you can pass in bounds and get a true/false answer for if it's colliding with anything (IsColliding), or get a list of everything it's collising with (GetColliding). 20 | With PointOctree, you can cast a ray and get a list of objects that are within x distance of that ray (GetNearby). You may also get a list of objects that are within x distance from a specified origin point. 21 | 22 | It shouldn't be too hard to implement additional functions if needed. For instance, PointOctree could check for points that fall inside a given bounds. 23 | 24 | **Considerations:** 25 | 26 | Tree searches are recursive, so there is technically the potential for a stack overflow on very large trees. The minNodeSize parameter limits node side and hence the depth of the tree, putting a cap on recursion. 27 | 28 | I tried switching to an iterative solution using my own stack, but creating and manipulating the stack made the results generally slower than the simple recursive solution. However, I wouldn't be surprised it someone smarter than me can come up with a faster solution. 29 | 30 | Another note: You may notice when viewing the bounds visualisation that the child nodes' outer edges are all inside the parent nodes. But loose octrees are meant to make the inner nodes bigger... aren't they? The answer is yes, but the parent nodes are *also* bigger, and e.g. ((1.2 * 10) - 10) is bigger than ((1.2 * 5) - 5), so the parent node ends up being bigger overall. 31 | 32 | This seems to be the standard way that loose octrees are done. I did an experiment: I tried making the child node dimensions looseness * the parent's actual size, instead of looseness * the parent's base size before looseness is applied. This seems more intuitively correct to me, but performance seems to be about the same. 33 | 34 | Example Usage 35 | =========== 36 | 37 | **Create An Octree** 38 | 39 | ```C# 40 | // Initial size (metres), initial centre position, minimum node size (metres), looseness 41 | BoundsOctree boundsTree = new BoundsOctree(15, MyContainer.position, 1, 1.25f); 42 | // Initial size (metres), initial centre position, minimum node size (metres) 43 | PointOctree pointTree = new PointOctree(15, MyContainer.position, 1); 44 | ``` 45 | 46 | - Here I've used GameObject, but the tree's content can be any type you like (as long as it's all the *same* type 47 | - The initial size should ideally cover an area just encompassing all your objects. If you guess too small, the octree will grow automatically, but it will be eight times the size (double dimensions), which could end up covering a large area unnecessarily. At the same time, the octree will be able to shrink down again if the outlying objects are removed. If you guess an initial size that's too big, it won't be able to shrink down, but that may be the safer option. Don't worry too much: In reality the starting value isn't hugely important for performance. 48 | - The initial position should ideally be in the centre of where your objects are. 49 | - The minimum node size is effectively a depth limit; it limits how many times the tree can divide. If all your objects are e.g. 1m+ wide, you wouldn't want to set it smaller than 1m. 50 | - The best way to choose a looseness value is to try different values (between 1 and maybe 1.5) and check the performance with your particular data. Generally around 1.2 is good. 51 | 52 | **Add And Remove** 53 | 54 | ```C# 55 | boundsTree.Add(myObject, myBounds); 56 | boundsTree.Remove(myObject); 57 | 58 | pointTree.Add(myObject, myVector3); 59 | boundsTree.Remove(myObject); 60 | ``` 61 | - The object's type depends on the tree's type. 62 | - The bounds or point determine where it's inserted. 63 | 64 | **Built-in Functions** 65 | 66 | ```C# 67 | bool isColliding = boundsTree.IsColliding(bounds); 68 | ``` 69 | 70 | ```C# 71 | List collidingWith = new List(); 72 | boundsTree.GetColliding(collidingWith, bounds); 73 | ``` 74 | - Where GameObject is the type of the octree 75 | 76 | ```C# 77 | pointTree.GetNearby(myRay, 4); 78 | ``` 79 | - Where myRay is a [Ray](http://docs.unity3d.com/Documentation/ScriptReference/Ray.html) 80 | - In this case we're looking for any point within 4m of the closest point on the ray 81 | 82 | ```C# 83 | pointTree.GetNearby(myPos, 4); 84 | ``` 85 | - Where myPos is a [Vector3](http://docs.unity3d.com/Documentation/ScriptReference/Vector3.html) 86 | 87 | **Debugging Visuals** 88 | 89 | ![Visualisation example.](https://raw.github.com/nition/UnityOctree/master/octree-visualisation.jpg) 90 | 91 | ```C# 92 | void OnDrawGizmos() { 93 | boundsTree.DrawAllBounds(); // Draw node boundaries 94 | boundsTree.DrawAllObjects(); // Draw object boundaries 95 | boundsTree.DrawCollisionChecks(); // Draw the last *numCollisionsToSave* collision check boundaries 96 | 97 | pointTree.DrawAllBounds(); // Draw node boundaries 98 | pointTree.DrawAllObjects(); // Mark object positions 99 | } 100 | ``` 101 | - Must be in Unity's OnDrawGizmos() method in a class that inherits from MonoBehaviour 102 | - Point octrees need the marker.tif file to be in your Unity /Assets/Gizmos subfolder for DrawAllObjects to work 103 | 104 | 105 | **Potential Improvements** 106 | 107 | A significant portion of the octree's time is taken just to traverse through the nodes themselves. There's potential for a performance increase there, maybe by linearising the tree - that is, representing all the nodes as a one-dimensional array lookup. 108 | 109 | -------------------------------------------------------------------------------- /Assets/License/UnityOctree/README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4fc9af6064d57b64781077cf839a35f5 3 | timeCreated: 1481513780 4 | licenseType: Pro 5 | DefaultImporter: 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 01e1b0d2efacb0149b62c3fd3152c2e2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Black.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Black 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _EMISSION _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: 3000 16 | stringTagMap: 17 | RenderType: Transparent 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 10 63 | - _GlossMapScale: 0.383 64 | - _Glossiness: 1 65 | - _GlossyReflections: 1 66 | - _Metallic: 1 67 | - _Mode: 3 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 1 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 0 75 | m_Colors: 76 | - _Color: {r: 0.09433961, g: 0.06710268, b: 0.030704873, a: 0.007843138} 77 | - _EmissionColor: {r: 0.8796968, g: 0.9696658, b: 1.9093419, a: 1} 78 | -------------------------------------------------------------------------------- /Assets/Materials/Black.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d6b586e5d1add28469f11f754f0df37f 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Blue.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Blue 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0.15953684, g: 0, b: 1, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Blue.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 33970c7b922d139448ee24fd7e7fc0f1 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Bright.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Bright 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION _GLOSSYREFLECTIONS_OFF _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A 12 | _SPECULARHIGHLIGHTS_OFF 13 | m_LightmapFlags: 2 14 | m_EnableInstancingVariants: 0 15 | m_DoubleSidedGI: 0 16 | m_CustomRenderQueue: -1 17 | stringTagMap: {} 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 10305, guid: 0000000000000000f000000000000000, type: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 0 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0 65 | - _GlossyReflections: 0 66 | - _Metallic: 0 67 | - _Mode: 0 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 1 71 | - _SpecularHighlights: 0 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 1 75 | m_Colors: 76 | - _Color: {r: 1, g: 1, b: 1, a: 1} 77 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 78 | -------------------------------------------------------------------------------- /Assets/Materials/Bright.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 08f8ce90b7528de41bd41945833c323c 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/ChocBlk.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: ChocBlk 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _ALPHAPREMULTIPLY_ON 12 | m_LightmapFlags: 6 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: 3000 16 | stringTagMap: 17 | RenderType: Transparent 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 10 63 | - _GlossMapScale: 1 64 | - _Glossiness: 1 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 3 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 0 75 | m_Colors: 76 | - _Color: {r: 0.09433961, g: 0.06710268, b: 0.030704873, a: 0.007843138} 77 | - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} 78 | -------------------------------------------------------------------------------- /Assets/Materials/ChocBlk.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1d0082690775b4b47b0f4927c9934d20 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Dark Transparent.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Dark Transparent 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: 3000 16 | stringTagMap: 17 | RenderType: Transparent 18 | disabledShaderPasses: [] 19 | m_SavedProperties: 20 | serializedVersion: 3 21 | m_TexEnvs: 22 | - _BumpMap: 23 | m_Texture: {fileID: 0} 24 | m_Scale: {x: 1, y: 1} 25 | m_Offset: {x: 0, y: 0} 26 | - _DetailAlbedoMap: 27 | m_Texture: {fileID: 0} 28 | m_Scale: {x: 1, y: 1} 29 | m_Offset: {x: 0, y: 0} 30 | - _DetailMask: 31 | m_Texture: {fileID: 0} 32 | m_Scale: {x: 1, y: 1} 33 | m_Offset: {x: 0, y: 0} 34 | - _DetailNormalMap: 35 | m_Texture: {fileID: 0} 36 | m_Scale: {x: 1, y: 1} 37 | m_Offset: {x: 0, y: 0} 38 | - _EmissionMap: 39 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 40 | m_Scale: {x: 1, y: 1} 41 | m_Offset: {x: 0, y: 0} 42 | - _MainTex: 43 | m_Texture: {fileID: 0} 44 | m_Scale: {x: 1, y: 1} 45 | m_Offset: {x: 0, y: 0} 46 | - _MetallicGlossMap: 47 | m_Texture: {fileID: 0} 48 | m_Scale: {x: 1, y: 1} 49 | m_Offset: {x: 0, y: 0} 50 | - _OcclusionMap: 51 | m_Texture: {fileID: 0} 52 | m_Scale: {x: 1, y: 1} 53 | m_Offset: {x: 0, y: 0} 54 | - _ParallaxMap: 55 | m_Texture: {fileID: 0} 56 | m_Scale: {x: 1, y: 1} 57 | m_Offset: {x: 0, y: 0} 58 | m_Floats: 59 | - _BumpScale: 1 60 | - _Cutoff: 0.5 61 | - _DetailNormalMapScale: 1 62 | - _DstBlend: 10 63 | - _GlossMapScale: 1 64 | - _Glossiness: 0.5 65 | - _GlossyReflections: 1 66 | - _Metallic: 0 67 | - _Mode: 3 68 | - _OcclusionStrength: 1 69 | - _Parallax: 0.02 70 | - _SmoothnessTextureChannel: 0 71 | - _SpecularHighlights: 1 72 | - _SrcBlend: 1 73 | - _UVSec: 0 74 | - _ZWrite: 0 75 | m_Colors: 76 | - _Color: {r: 0.1981132, g: 0.14671591, b: 0.14671591, a: 0.32156864} 77 | - _EmissionColor: {r: 0.0625, g: 0.0625, b: 0.0625, a: 1} 78 | -------------------------------------------------------------------------------- /Assets/Materials/Dark Transparent.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 06b149c62298ef147b389f3cdd47d54a 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Light Blue.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Light Blue 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0, g: 0.8982549, b: 1, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Light Blue.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 261946f79a335714eae1a475e8e4d69b 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Lime Green.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Lime Green 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10914, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0.16239214, g: 1, b: 0, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Lime Green.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a83a6eb254d82db4d9a3b42c4727bcc3 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Orange.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Orange 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10900, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 0.449203, b: 0, a: 1} 76 | - _EmissionColor: {r: 0.2462014, g: 0.2462014, b: 0.2462014, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Orange.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e5f7b92cecf5fc448965070f100e7125 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Pink.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Pink 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 0.11372548, b: 0.8656726, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Pink.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 417e24f513c60dc41bf805d9aa3baa27 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Purple.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Purple 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 0 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10900, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 0.49497414, g: 0.11372549, b: 1, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Purple.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0f24ee3757d512847b34accda43131a4 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Materials/Yellow.mat: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!21 &2100000 4 | Material: 5 | serializedVersion: 6 6 | m_ObjectHideFlags: 0 7 | m_PrefabParentObject: {fileID: 0} 8 | m_PrefabInternal: {fileID: 0} 9 | m_Name: Yellow 10 | m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} 11 | m_ShaderKeywords: _EMISSION 12 | m_LightmapFlags: 2 13 | m_EnableInstancingVariants: 1 14 | m_DoubleSidedGI: 0 15 | m_CustomRenderQueue: -1 16 | stringTagMap: {} 17 | disabledShaderPasses: [] 18 | m_SavedProperties: 19 | serializedVersion: 3 20 | m_TexEnvs: 21 | - _BumpMap: 22 | m_Texture: {fileID: 0} 23 | m_Scale: {x: 1, y: 1} 24 | m_Offset: {x: 0, y: 0} 25 | - _DetailAlbedoMap: 26 | m_Texture: {fileID: 0} 27 | m_Scale: {x: 1, y: 1} 28 | m_Offset: {x: 0, y: 0} 29 | - _DetailMask: 30 | m_Texture: {fileID: 0} 31 | m_Scale: {x: 1, y: 1} 32 | m_Offset: {x: 0, y: 0} 33 | - _DetailNormalMap: 34 | m_Texture: {fileID: 0} 35 | m_Scale: {x: 1, y: 1} 36 | m_Offset: {x: 0, y: 0} 37 | - _EmissionMap: 38 | m_Texture: {fileID: 10300, guid: 0000000000000000f000000000000000, type: 0} 39 | m_Scale: {x: 1, y: 1} 40 | m_Offset: {x: 0, y: 0} 41 | - _MainTex: 42 | m_Texture: {fileID: 0} 43 | m_Scale: {x: 1, y: 1} 44 | m_Offset: {x: 0, y: 0} 45 | - _MetallicGlossMap: 46 | m_Texture: {fileID: 0} 47 | m_Scale: {x: 1, y: 1} 48 | m_Offset: {x: 0, y: 0} 49 | - _OcclusionMap: 50 | m_Texture: {fileID: 0} 51 | m_Scale: {x: 1, y: 1} 52 | m_Offset: {x: 0, y: 0} 53 | - _ParallaxMap: 54 | m_Texture: {fileID: 0} 55 | m_Scale: {x: 1, y: 1} 56 | m_Offset: {x: 0, y: 0} 57 | m_Floats: 58 | - _BumpScale: 1 59 | - _Cutoff: 0.5 60 | - _DetailNormalMapScale: 1 61 | - _DstBlend: 0 62 | - _GlossMapScale: 1 63 | - _Glossiness: 1 64 | - _GlossyReflections: 1 65 | - _Metallic: 0 66 | - _Mode: 0 67 | - _OcclusionStrength: 1 68 | - _Parallax: 0.02 69 | - _SmoothnessTextureChannel: 0 70 | - _SpecularHighlights: 1 71 | - _SrcBlend: 1 72 | - _UVSec: 0 73 | - _ZWrite: 1 74 | m_Colors: 75 | - _Color: {r: 1, g: 0.974868, b: 0.11372548, a: 1} 76 | - _EmissionColor: {r: 1, g: 1, b: 1, a: 1} 77 | -------------------------------------------------------------------------------- /Assets/Materials/Yellow.mat.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1b6ed89a57154524ebca90be889fc3cf 3 | NativeFormatImporter: 4 | externalObjects: {} 5 | mainObjectFileID: 2100000 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/OTIJob.cs: -------------------------------------------------------------------------------- 1 | namespace oti.AI 2 | { 3 | using UnityEngine; 4 | using System.Threading; 5 | using System.Collections.Generic; 6 | 7 | public class OctreeThreadParameters 8 | { 9 | public int TotalTrackedObjects; 10 | public List ObjectIDs; 11 | public Dictionary> Coordinates; 12 | public Dictionary DynamicObjects; 13 | 14 | } 15 | 16 | public class OTIJob 17 | { 18 | private bool JobIsDone = false; 19 | 20 | private readonly object JobHandle = new object(); 21 | 22 | private Thread JobThread = null; 23 | 24 | public bool IsDone 25 | { 26 | get 27 | { 28 | bool tmp; 29 | lock (JobHandle) 30 | { 31 | tmp = JobIsDone; 32 | } 33 | return tmp; 34 | } 35 | set 36 | { 37 | lock (JobHandle) 38 | { 39 | JobIsDone = value; 40 | } 41 | } 42 | } 43 | 44 | public virtual void StartOctree(OctreeThreadParameters otp) 45 | { 46 | JobThread = new Thread(new ParameterizedThreadStart(runOctree)); 47 | JobThread.Start(otp); 48 | } 49 | 50 | public virtual void Abort() 51 | { 52 | JobThread?.Abort(); 53 | } 54 | 55 | protected virtual void ThreadOctree(OctreeThreadParameters otp) { } 56 | 57 | protected virtual void OctreeThreadFinished() { } 58 | 59 | public virtual bool UpdateOctree() 60 | { 61 | if (IsDone) 62 | { 63 | OctreeThreadFinished(); 64 | return true; 65 | } 66 | return false; 67 | } 68 | 69 | private void runOctree(object otp) 70 | { 71 | ThreadOctree((OctreeThreadParameters)otp); 72 | } 73 | } 74 | } 75 | 76 | -------------------------------------------------------------------------------- /Assets/OTIJob.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7450d06bb0e3e2d41a38d34c778cbb88 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/OTIUtilities.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace oti.Utilities 4 | { 5 | public static class OTIUtilities 6 | { 7 | public static string[] _Alphabetic = new string[26] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z" }; 8 | 9 | /// 10 | /// Assembles a continuous alphabetic unique string from index i: A (i = 0), ...., AB (i = 27), ....., BC (i = 54), ... AAB etc 11 | /// 12 | public static string _AlphabetAssembler(int i) 13 | { 14 | string s = ""; 15 | int wh = -1; 16 | 17 | for (int j = 0; j <= i; j += _Alphabetic.Length) 18 | { 19 | wh += 1; 20 | } 21 | 22 | for (int j = 0; j <= wh; j++) 23 | { 24 | if (j > 0) 25 | { 26 | j = wh + 1; 27 | s += _Alphabetic[i % _Alphabetic.Length]; 28 | } 29 | else 30 | { 31 | s += wh >= 1 ? _Alphabetic[wh - 1] : _Alphabetic[i % _Alphabetic.Length]; 32 | } 33 | } 34 | 35 | return s; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Assets/OTIUtilities.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 33649b6b61241b3449e6dfc5325e699f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Octree.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff6c142fc87f9b34fa30da29f2b3a8d7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Octree/Octree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | using System.Threading; 4 | 5 | namespace oti.AI 6 | { 7 | /// 8 | /// OTI AI access point for tracked objects calculations run on auxilliary thread. 9 | /// 10 | public class Octree : OTIJob 11 | { 12 | /* 13 | Using Nition Octree https://github.com/Nition/UnityOctree 14 | See license in Assets/License/UnityOctree 15 | */ 16 | 17 | /// 18 | /// The octree. Access should be restricted to this class. Using int to ID GameObjects outside main thread. 19 | /// 20 | public PointOctree PointOctree; 21 | 22 | /// 23 | /// True entire time Octree thread is running 24 | /// 25 | public bool ThreadRunning; 26 | 27 | /// 28 | /// Do not access this cache of object states as it is volatile, instead reference WorldMonitor's copy 29 | /// 30 | public TrackedObjectStates TrackedObjectStates; 31 | 32 | /// 33 | /// Record of every tracked object's current state of conflict and which categories it's in conflict with 34 | /// 35 | public Dictionary> MasterList = new Dictionary>(); 36 | 37 | /// 38 | /// Positions of tracked objects. 39 | /// 40 | private Vector3[] updatePositions; 41 | 42 | /// 43 | /// Generate Nition PointOctree 44 | /// 45 | public void Initialize(int initialWorldSize, Vector3 initialPosition, int smallestObjectSize) 46 | { 47 | PointOctree = new PointOctree(initialWorldSize, initialPosition, smallestObjectSize); 48 | } 49 | 50 | /// 51 | /// Call this method to begin the threaded Octree operations. 52 | /// 53 | /// 54 | public void ThreadOctreeInit(OctreeThreadParameters otp, bool restrictToMainThread) 55 | { 56 | if(restrictToMainThread) 57 | { 58 | TrackedObjectStates = evaluateOctree(otp); 59 | return; 60 | } 61 | 62 | ThreadRunning = true; 63 | 64 | IsDone = false; 65 | base.StartOctree(otp); 66 | } 67 | 68 | protected override void ThreadOctree(OctreeThreadParameters otp) 69 | { 70 | TrackedObjectStates = evaluateOctree(otp); 71 | IsDone = true; // TrackedObjectStates are defined - - eliminating race conditions 72 | } 73 | 74 | /// 75 | /// Non essential method used to monitor threading 76 | /// 77 | protected override void OctreeThreadFinished() 78 | { 79 | ThreadRunning = false; 80 | } 81 | 82 | /// 83 | /// Runs current tracked object data through Octree. 84 | /// 85 | private TrackedObjectStates evaluateOctree(OctreeThreadParameters otp) 86 | { 87 | int alloc = WorldMonitor.Instance.AllocationSpace; 88 | updatePositions = new Vector3[alloc]; // otp.ObjectIDs.Count 89 | float[] thresholds = new float[alloc]; // otp.ObjectIDs.Count 90 | 91 | //for (int i = 0; i < otp.ObjectIDs.Count; i++) 92 | foreach (int id in otp.ObjectIDs) 93 | { 94 | KeyValuePair pos; 95 | 96 | if (!otp.Coordinates.TryGetValue(id, out pos)) 97 | Debug.LogError("unknown object position request in octree eval"); 98 | 99 | thresholds[id] = pos.Key; 100 | updatePositions[id] = pos.Value; 101 | 102 | PointOctree.Remove(id); 103 | PointOctree.Add(id, pos.Value); 104 | } 105 | 106 | List enteringIDs = new List(); 107 | List leavingIDs = new List(); 108 | 109 | List parentIDLeavers = new List(); 110 | List parentIDEnterers = new List(); 111 | 112 | int ind = 0; 113 | foreach(int id in otp.ObjectIDs) 114 | { 115 | List validConflicts = new List(); 116 | List stayers = new List(); 117 | 118 | int[] areaObjects = PointOctree.GetNearby(updatePositions[id], thresholds[id]); 119 | 120 | for (int j = 0; j < areaObjects.Length; j++) 121 | { 122 | string affiliateObj = WorldMonitor.Instance.TrackedObjectAffiliations[id]; 123 | string affiliateCompare = WorldMonitor.Instance.TrackedObjectAffiliations[areaObjects[j]]; 124 | 125 | /* 126 | * run conflict validity checks: if not the same object && not an object of the same class type && is a new conflict 127 | */ 128 | 129 | if (areaObjects[j] != id && !MasterList[id].Contains(areaObjects[j]) && string.Compare(affiliateObj, affiliateCompare) != 0) 130 | { 131 | if (!parentIDEnterers.Contains(id)) 132 | parentIDEnterers.Add(id); 133 | 134 | MasterList[id].Add(areaObjects[j]); // add conflicting object to master list of current conflicts 135 | validConflicts.Add(areaObjects[j]); // *new* conflicts 136 | stayers.Add(areaObjects[j]); // use to look for conflicts that have ended 137 | } 138 | else if (MasterList[id].Contains(areaObjects[j])) 139 | { 140 | stayers.Add(areaObjects[j]); // this is an object staying in conflict 141 | } 142 | } 143 | 144 | bool leaverDetected = false; 145 | List leavers = new List(); 146 | 147 | foreach (int _id in MasterList[id]) // look at master list's record of conflicts for this parent ID - if it isn't in stayers, it has left the conflict area or been destroyed 148 | { 149 | if (!stayers.Contains(_id)) 150 | { 151 | leaverDetected = true; 152 | leavers.Add(_id); 153 | } 154 | 155 | switch (WorldMonitor.Instance.ConflictEndMode) 156 | { 157 | case ConflictEndMode.OnAllConflictsEnded: 158 | if (leavers.Count == MasterList[id].Count) 159 | parentIDLeavers.Add(id); 160 | break; 161 | case ConflictEndMode.OnIndividualConflictEnded: 162 | if (leaverDetected && !parentIDEnterers.Contains(id) && !parentIDLeavers.Contains(id)) 163 | parentIDLeavers.Add(id); 164 | break; 165 | } 166 | } 167 | 168 | foreach (int leaver in leavers) 169 | MasterList[id].Remove(leaver); 170 | 171 | int numValid = leavers.ToArray().Length; 172 | 173 | if (numValid > 0) 174 | leavingIDs.Add(leavers.ToArray()); 175 | 176 | numValid = validConflicts.ToArray().Length; 177 | 178 | if (numValid > 0) 179 | enteringIDs.Add(validConflicts.ToArray()); 180 | 181 | ind++; 182 | } 183 | 184 | return new TrackedObjectStates 185 | { 186 | ParentIDEnterers = parentIDEnterers.ToArray(), // parent IDs of new or increased conflict states 187 | ParentIDLeavers = parentIDLeavers.ToArray(), // parent IDs of expired or reduced conflict states 188 | LeavingIDs = leavingIDs, // child IDs - ended conflict(s) 189 | EnteringIDs = enteringIDs, // child IDs - the conflict(s) 190 | PriorConflictingIDs = parentIDLeavers // parent IDs that need informed all conflicts have ceased 191 | }; 192 | } 193 | } 194 | 195 | /// 196 | /// A reference of states for tracked objects 197 | /// 198 | public class TrackedObjectStates 199 | { 200 | public int[] ParentIDEnterers; 201 | public int[] ParentIDLeavers; 202 | public List EnteringIDs; 203 | public List LeavingIDs; 204 | public List PriorConflictingIDs; 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /Assets/Octree/Octree.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cf02a59650f4b0c48934a4837c10d202 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4f704ae4b4f98ae41a0bce26658850c1 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b2f565eb0b69fff49bf7e5753a256c95 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/ExampleNavigator.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace oti.AI 4 | { 5 | /// 6 | /// Moves tracked objects in Dynamic Objects Tracking example scene 7 | /// 8 | public class ExampleNavigator : MonoBehaviour 9 | { 10 | /// 11 | /// Setting false will allow user to investigate collision reporting on their own accord 12 | /// 13 | public bool MoveAuto; 14 | 15 | /// 16 | /// Speed of translation 17 | /// 18 | public float Speed = 5; 19 | 20 | /// 21 | /// Max speed an object can reach after collision. 22 | /// 23 | public float MaxSpeed = 20; 24 | 25 | /// 26 | /// represents length of size of box used for navigation 27 | /// 28 | private float boundingBoxScale = 50; 29 | 30 | /// 31 | /// direction of travel 32 | /// 33 | private Vector3 direction = Vector3.forward; 34 | 35 | /// 36 | /// Corrals objects that can leave bounds in Update 37 | /// 38 | private bool escapedBounds; 39 | 40 | void Start() 41 | { 42 | if (!MoveAuto) 43 | { 44 | Speed = 0; 45 | return; 46 | } 47 | 48 | direction = new Vector3(Random.Range(-1, 1), 0, Random.Range(-1, 1)); 49 | 50 | // ensure all objects move with some velocity >> 0 51 | float xMin = Mathf.Max(Mathf.Abs(direction.x), 0.5f) * Mathf.Sign(direction.x); 52 | float zMin = Mathf.Max(Mathf.Abs(direction.z), 0.5f) * Mathf.Sign(direction.z); 53 | 54 | direction = new Vector3(xMin, 0, zMin); 55 | } 56 | 57 | /// 58 | /// Limit gizmos to one component 59 | /// 60 | public static bool _GizmosDrawn; 61 | 62 | /// 63 | /// Method called from subscriber in Tracker 64 | /// 65 | public void ObjectConflict(Vector3 positionOfInitiator) 66 | { 67 | float fr = Random.Range(-0.01f, 0.01f); 68 | //do something with the information -- note that object affiliation and all conflicting objects and types are available in the event 69 | direction = Vector3.Cross(direction + new Vector3(fr,fr,fr), positionOfInitiator - transform.position).normalized; // jump into 3 dimensions 70 | } 71 | 72 | void Update() 73 | { 74 | if (!MoveAuto) 75 | return; 76 | 77 | bool xCrossed = Mathf.Abs(transform.position.x) > boundingBoxScale; 78 | bool zCrossed = Mathf.Abs(transform.position.z) > boundingBoxScale; 79 | bool yCrossed = Mathf.Abs(transform.position.y) > boundingBoxScale; 80 | 81 | if (escapedBounds && (xCrossed || zCrossed || yCrossed)) //object has been outside of bounds for more than one frame so force it back 82 | { 83 | float signX = Mathf.Sign(transform.position.x); 84 | float signY = Mathf.Sign(transform.position.z); 85 | float signZ = Mathf.Sign(transform.position.z); 86 | 87 | transform.position = xCrossed ? new Vector3(signX * boundingBoxScale * 0.9975f, transform.position.y, transform.position.z) : transform.position; 88 | transform.position = yCrossed ? new Vector3(transform.position.x, signY * boundingBoxScale * 0.9975f, transform.position.z) : transform.position; 89 | transform.position = zCrossed ? new Vector3(transform.position.x, transform.position.y, signZ * boundingBoxScale * 0.9975f) : transform.position; 90 | 91 | escapedBounds = false; 92 | } 93 | else 94 | { 95 | escapedBounds = xCrossed || zCrossed || yCrossed; 96 | } 97 | 98 | direction = xCrossed ? new Vector3(-direction.x, direction.y, direction.z) : direction; 99 | direction = zCrossed ? new Vector3(direction.x, direction.y, -direction.z) : direction; 100 | direction = yCrossed ? new Vector3(direction.x, -direction.y, direction.z) : direction; 101 | 102 | 103 | transform.Translate(Speed * direction * Time.deltaTime, Space.World); 104 | 105 | if (Speed == MaxSpeed) 106 | Speed = 5/2; 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/ExampleNavigator.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3bb0f3934e618a24aad8bc1951a07beb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/SmallTrackingExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b69eed32be95be74aa55bd3f574bc6c4 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/Tracker.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | using System.Collections; 3 | namespace oti.AI 4 | { 5 | /// 6 | /// Class developed to show example usage of Dynamic Object Tracking 7 | /// 8 | public class Tracker : WorldMonitors 9 | { 10 | /* 11 | The purpose of Tracker.cs is to demonstrate usage of WorldMonitors and Worldmonitor classes. 12 | Your tracking agent will need to subscribe to the ObjectConflictHandler delegate in WorldMonitors 13 | like this: 14 | GetComponent().ConflictEnterers += yourFunction; 15 | 16 | 17 | Events in the ObjectConflictHandler: 18 | *** the optional arguments must be included by every method subscribing to this delegate 19 | 20 | ConflictEnterers: emitted every time a new tracked object enters a parent object's tracked area 21 | Arguments(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 22 | TrackedObject: the object who's threshold has been penetrated 23 | ConflictingObjects: an array of objects that have entered the tracked object's space 24 | ConflictingTypes: an array of the object types ("A", "B", "C" etc) at matching index locations to ConflictingObjects[] 25 | 26 | ConflictLeavers: 27 | Arguments(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 28 | TrackedObject: the object who's threshold has been partially or entirely vacated 29 | ConflictingObjects: an array of objects that have vacated the tracked object's space 30 | ConflictingTypes: an array of the object types ("A", "B", "C" etc) at matching index locations to ConflictingObjects[] 31 | 32 | ConflictEnd: 33 | Arguments(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 34 | TrackedObject: the object who's threshold has been entirely vacated 35 | ConflictingObjects & ConflictingTypes are not passed into this method, but are still required by all subscribers. 36 | */ 37 | 38 | // Demonstration of event subscription 39 | void Start() 40 | { 41 | sColor = Color.blue; 42 | eColor = Color.red; 43 | 44 | if (GetComponent()) 45 | { 46 | WorldMonitors = GetComponent(); 47 | 48 | //subscribe to delegate for tracked object information 49 | WorldMonitors.ConflictEnterers += entererListener; 50 | WorldMonitors.ConflictLeavers += leaverListener; 51 | WorldMonitors.ConflictEnd += endListener; 52 | 53 | if (Demo) 54 | StartCoroutine(demo()); 55 | 56 | return; 57 | } 58 | 59 | Debug.LogWarning("Make sure the agent has a WorldMonitors component attached to it."); 60 | } 61 | 62 | /// 63 | /// Unsubscribe all Trackers that are destroyed 64 | /// 65 | private void OnDestroy() 66 | { 67 | WorldMonitors.ConflictEnterers -= entererListener; 68 | WorldMonitors.ConflictLeavers -= leaverListener; 69 | WorldMonitors.ConflictEnd -= endListener; 70 | } 71 | 72 | /// 73 | /// Cached ref to WorldMonitors class 74 | /// 75 | [HideInInspector] 76 | public WorldMonitors WorldMonitors; 77 | 78 | /// 79 | /// Prints conflicting object(s) and type 80 | /// 81 | [Tooltip("Shows tracking system interactions.")] 82 | public bool PrintConflictsToConsole; 83 | 84 | /// 85 | /// Can demonstrate how to add tracked objects at runtime 86 | /// 87 | [Tooltip("Uses a tracking system event to demonstrate how to add objects into tracking system.")] 88 | public bool InsertNewObjectOnEnter; 89 | 90 | /// 91 | /// This object will be inserted into tracking system if InsertNewObjectOnEnter is selected 92 | /// 93 | [Tooltip("If Insert New Object On Enter is true, this will be inserted at the origin on object entrance")] 94 | public GameObject ExampleInsertionObject; 95 | 96 | /// 97 | /// Will destroy objects that enter another's threshold 98 | /// 99 | [Tooltip("Uses a tracking system event to demonstrate how to remove objects from tracking system.")] 100 | public bool DestroyConflictingObjects; 101 | 102 | /// 103 | /// Runs an example method in example navigator class. 104 | /// 105 | [Tooltip("Uses a tracking system event to run a method for pure demo purposes You cannot destroy objects if using this method.")] 106 | public bool CrossProductCollisions; 107 | 108 | /// 109 | /// Triggers a coroutine to wait and change parameters for visual effects 110 | /// 111 | public bool Demo; 112 | 113 | /// 114 | /// Starting interpolation color value for added objects 115 | /// 116 | static Color sColor; 117 | 118 | /// 119 | /// Ending interpolation color value for added objects 120 | /// 121 | static Color eColor; 122 | 123 | /// 124 | /// This method shows how to handle objects raising a conflict with a TrackedObject 125 | /// 126 | private void entererListener(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 127 | { 128 | if (PrintConflictsToConsole) 129 | Debug.Log("Conflict has STARTED for (" + gameObject.name + ") " + TrackedObject + " with:"); 130 | 131 | for (int i = 0; i < ConflictingObjects.Length; i++) 132 | { 133 | if (PrintConflictsToConsole) 134 | Debug.Log(" -- (" + gameObject.name + ") " + ConflictingObjects[i] + " of type: " + ConflictingTypes[i]); 135 | 136 | if (InsertNewObjectOnEnter && WorldMonitor.Instance.FreeSpace) 137 | { 138 | GameObject go = Instantiate(ExampleInsertionObject, Vector3.zero, Quaternion.identity); 139 | go.name = "NewGameObject_" + WorldMonitor.Instance.AllocationSpace; 140 | go.AddComponent(); 141 | go.SetActive(true); 142 | go.GetComponent().material.color = Color.Lerp(sColor, eColor, Mathf.Sin(0.5f * Time.time)); 143 | go.transform.position = new Vector3(Random.Range(-6, 6), Random.Range(-6, 6), Random.Range(-6, 6)); // [-6,6] ensures eventual collision with center object. 144 | WorldMonitor.Instance.InsertNewTrackedObject(go, WorldMonitors, "YouCanMakeThisAnything", 2); 145 | } 146 | 147 | if (DestroyConflictingObjects) 148 | { 149 | WorldMonitor.Instance.RemoveTrackedObject(ConflictingObjects[i]); 150 | Destroy(ConflictingObjects[i]); 151 | } 152 | 153 | if (CrossProductCollisions && !DestroyConflictingObjects) 154 | { 155 | if(ConflictingObjects[i]) 156 | ConflictingObjects[i].GetComponent().ObjectConflict(TrackedObject.transform.position); 157 | } 158 | } 159 | } 160 | 161 | /// 162 | /// This method shows how to handle objects leaving the conflict area of a Tracked Object 163 | /// 164 | /// The user can choose to only subscribe to events raised when all conflicts have ended, or none at all. 165 | private void leaverListener(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 166 | { 167 | if (PrintConflictsToConsole) 168 | Debug.Log("Conflict has ENDED for (" + gameObject.name + ") " + TrackedObject + " with:"); 169 | 170 | for (int i = 0; i < ConflictingObjects.Length; i++) 171 | { 172 | if (PrintConflictsToConsole) 173 | Debug.Log(" -- (" + gameObject.name + ") " + ConflictingObjects[i] + " of type: " + ConflictingTypes[i]); 174 | } 175 | } 176 | 177 | /// 178 | /// This method shows how to handle events when a conflict ceases entirely. 179 | /// 180 | /// The user can choose to only subscribe to events raised when any oject leaves a Tracked Object's conflict area, or none at all. 181 | private void endListener(GameObject TrackedObject, GameObject[] ConflictingObjects, string[] ConflictingTypes) 182 | { 183 | if (PrintConflictsToConsole) 184 | Debug.Log("GameObject " + TrackedObject + "'s conflict(s) have ended and logged for " + gameObject.name); 185 | } 186 | 187 | /// 188 | /// Solely to look interesting :) 189 | /// 190 | private IEnumerator demo() 191 | { 192 | float t = Time.time; 193 | yield return new WaitWhile(() => Time.time - t < 10); 194 | 195 | sColor = Color.red; 196 | eColor = Color.yellow; 197 | 198 | CrossProductCollisions = true; 199 | } 200 | } 201 | } -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/Tracker.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83bed73bc2468f7419add006d59d22e4 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/Scenes/Example Scenes/TrackingExample.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 99c9720ab356a0642a771bea13969a05 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Assets/TrackedObjectTriggers.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace oti.AI 6 | { 7 | public class TrackedObjectTriggers : MonoBehaviour 8 | { 9 | /// 10 | /// How many agents are tracking this object 11 | /// 12 | public int Owners; 13 | 14 | /// 15 | /// The uID for this tracked object. 16 | /// 17 | public int TrackedObjectID; 18 | 19 | /// 20 | /// The agents following this tracked object 21 | /// 22 | public List wms = new List(); 23 | 24 | /// 25 | /// Record of how many conflicts occurring 26 | /// 27 | private int insiders = 0; 28 | 29 | /// 30 | /// Agents who find this object in a field will add themselves as owners here 31 | /// 32 | public void AcceptOwner(WorldMonitors wm) 33 | { 34 | Owners++; // quicker than wms.Count 35 | wms.Add(wm); 36 | } 37 | 38 | /// 39 | /// Agents notify objects when they are destroyed 40 | /// 41 | public void LoseOwner(WorldMonitors wm) 42 | { 43 | Owners--; 44 | wms.Remove(wm); 45 | } 46 | 47 | /// 48 | /// Set up unity components to user config 49 | /// 50 | public void Initialize() 51 | { 52 | SphereCollider collider; 53 | 54 | if (!GetComponent()) 55 | gameObject.AddComponent(); 56 | 57 | collider = GetComponent(); 58 | collider.isTrigger = true; 59 | collider.enabled = true; 60 | 61 | if(!GetComponent()) 62 | gameObject.AddComponent(); 63 | 64 | GetComponent().useGravity = WorldMonitor.Instance.TrackedObjectsUseGravity; 65 | 66 | TrackedObjectID = WorldMonitor.Instance.GameObjectIDReference[gameObject]; 67 | 68 | TrackedObjectData todata; 69 | WorldMonitor.Instance.TrackedObjectDataRef.TryGetValue(TrackedObjectID, out todata); 70 | 71 | collider.radius = WorldMonitor.Instance.TriggersMimicOctree ? 0.75f * todata.Threshold : todata.Threshold; // allow triggers to mimic point octree 72 | } 73 | 74 | // MonoBehaviour method 75 | private void OnTriggerEnter(Collider other) 76 | { 77 | if (other.gameObject) 78 | { 79 | GameObject[] goPass = new GameObject[1]; 80 | goPass[0] = other.gameObject; 81 | 82 | int childID; 83 | int parentID; 84 | 85 | if (WorldMonitor.Instance.GameObjectIDReference.TryGetValue(goPass[0], out childID)) // not all gameObjects may be in tracking system 86 | { 87 | if (!WorldMonitor.Instance.GameObjectIDReference.TryGetValue(gameObject, out parentID)) 88 | Debug.LogError("TrackedObjectTriggers cannot be used on objects not located in a field of a WorldMonitors instance"); 89 | 90 | insiders++; 91 | 92 | string[] sPass = new string[1]; 93 | sPass[0] = WorldMonitor.Instance.TrackedObjectAffiliations[childID]; 94 | 95 | if (string.Compare(WorldMonitor.Instance.TrackedObjectAffiliations[TrackedObjectID], sPass[0]) != 0) 96 | { 97 | foreach (WorldMonitors wm in wms) 98 | wm.RaiseConflictEnterers(gameObject, goPass, sPass); 99 | } 100 | } 101 | } 102 | } 103 | 104 | // MonoBehaviour method 105 | private void OnTriggerExit(Collider other) 106 | { 107 | ConflictEndMode cem = WorldMonitor.Instance.ConflictEndMode; 108 | 109 | if (cem == ConflictEndMode.NoConflictEndEvents) 110 | return; 111 | 112 | if (other.gameObject) 113 | { 114 | GameObject[] goPass = new GameObject[1]; 115 | goPass[0] = other.gameObject; 116 | 117 | int childID; 118 | int parentID; 119 | 120 | if (WorldMonitor.Instance.GameObjectIDReference.TryGetValue(goPass[0], out childID)) // not all gameObjects may be in tracking system 121 | { 122 | if (!WorldMonitor.Instance.GameObjectIDReference.TryGetValue(gameObject, out parentID)) 123 | Debug.LogError("TrackedObjectTriggers cannot be used on objects not located in a field of a WorldMonitors instance"); 124 | 125 | insiders--; 126 | 127 | string[] sPass = new string[1]; 128 | sPass[0] = WorldMonitor.Instance.TrackedObjectAffiliations[childID]; 129 | 130 | if (string.Compare(WorldMonitor.Instance.TrackedObjectAffiliations[TrackedObjectID], sPass[0]) != 0) 131 | { 132 | if (cem == ConflictEndMode.OnAllConflictsEnded && insiders > 0) 133 | return; 134 | // else: both OnAll and OnIndividual modes will be handled the same from here out 135 | 136 | foreach (WorldMonitors wm in wms) 137 | wm.RaiseConflictLeavers(gameObject, goPass, sPass); 138 | } 139 | } 140 | } 141 | } 142 | } 143 | } -------------------------------------------------------------------------------- /Assets/TrackedObjectTriggers.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 27bec2c7144b9f443b81cab3adbf7308 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/UnityOctree.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c417392861d01d40b9df69477b9d75a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Assets/UnityOctree/BoundsOctree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | // A Dynamic, Loose Octree for storing any objects that can be described with AABB bounds 5 | // See also: PointOctree, where objects are stored as single points and some code can be simplified 6 | // Octree: An octree is a tree data structure which divides 3D space into smaller partitions (nodes) 7 | // and places objects into the appropriate nodes. This allows fast access to objects 8 | // in an area of interest without having to check every object. 9 | // Dynamic: The octree grows or shrinks as required when objects as added or removed 10 | // It also splits and merges nodes as appropriate. There is no maximum depth. 11 | // Nodes have a constant - numObjectsAllowed - which sets the amount of items allowed in a node before it splits. 12 | // Loose: The octree's nodes can be larger than 1/2 their parent's length and width, so they overlap to some extent. 13 | // This can alleviate the problem of even tiny objects ending up in large nodes if they're near boundaries. 14 | // A looseness value of 1.0 will make it a "normal" octree. 15 | // T: The content of the octree can be anything, since the bounds data is supplied separately. 16 | 17 | // Originally written for my game Scraps (http://www.scrapsgame.com) but intended to be general-purpose. 18 | // Copyright 2014 Nition, BSD licence (see LICENCE file). www.momentstudio.co.nz 19 | // Unity-based, but could be adapted to work in pure C# 20 | 21 | // Note: For loops are often used here since in some cases (e.g. the IsColliding method) 22 | // they actually give much better performance than using Foreach, even in the compiled build. 23 | // Using a LINQ expression is worse again than Foreach. 24 | public class BoundsOctree { 25 | // The total amount of objects currently in the tree 26 | public int Count { get; private set; } 27 | 28 | // Root node of the octree 29 | BoundsOctreeNode rootNode; 30 | 31 | // Should be a value between 1 and 2. A multiplier for the base size of a node. 32 | // 1.0 is a "normal" octree, while values > 1 have overlap 33 | readonly float looseness; 34 | 35 | // Size that the octree was on creation 36 | readonly float initialSize; 37 | 38 | // Minimum side length that a node can be - essentially an alternative to having a max depth 39 | readonly float minSize; 40 | // For collision visualisation. Automatically removed in builds. 41 | #if UNITY_EDITOR 42 | const int numCollisionsToSave = 4; 43 | readonly Queue lastBoundsCollisionChecks = new Queue(); 44 | readonly Queue lastRayCollisionChecks = new Queue(); 45 | #endif 46 | 47 | /// 48 | /// Constructor for the bounds octree. 49 | /// 50 | /// Size of the sides of the initial node, in metres. The octree will never shrink smaller than this. 51 | /// Position of the centre of the initial node. 52 | /// Nodes will stop splitting if the new nodes would be smaller than this (metres). 53 | /// Clamped between 1 and 2. Values > 1 let nodes overlap. 54 | public BoundsOctree(float initialWorldSize, Vector3 initialWorldPos, float minNodeSize, float loosenessVal) { 55 | if (minNodeSize > initialWorldSize) { 56 | Debug.LogWarning("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize); 57 | minNodeSize = initialWorldSize; 58 | } 59 | Count = 0; 60 | initialSize = initialWorldSize; 61 | minSize = minNodeSize; 62 | looseness = Mathf.Clamp(loosenessVal, 1.0f, 2.0f); 63 | rootNode = new BoundsOctreeNode(initialSize, minSize, looseness, initialWorldPos); 64 | } 65 | 66 | // #### PUBLIC METHODS #### 67 | 68 | /// 69 | /// Add an object. 70 | /// 71 | /// Object to add. 72 | /// 3D bounding box around the object. 73 | public void Add(T obj, Bounds objBounds) { 74 | // Add object or expand the octree until it can be added 75 | int count = 0; // Safety check against infinite/excessive growth 76 | while (!rootNode.Add(obj, objBounds)) { 77 | Grow(objBounds.center - rootNode.Center); 78 | if (++count > 20) { 79 | Debug.LogError("Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree."); 80 | return; 81 | } 82 | } 83 | Count++; 84 | } 85 | 86 | /// 87 | /// Remove an object. Makes the assumption that the object only exists once in the tree. 88 | /// 89 | /// Object to remove. 90 | /// True if the object was removed successfully. 91 | public bool Remove(T obj) { 92 | bool removed = rootNode.Remove(obj); 93 | 94 | // See if we can shrink the octree down now that we've removed the item 95 | if (removed) { 96 | Count--; 97 | Shrink(); 98 | } 99 | 100 | return removed; 101 | } 102 | 103 | /// 104 | /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree. 105 | /// 106 | /// Object to remove. 107 | /// 3D bounding box around the object. 108 | /// True if the object was removed successfully. 109 | public bool Remove(T obj, Bounds objBounds) { 110 | bool removed = rootNode.Remove(obj, objBounds); 111 | 112 | // See if we can shrink the octree down now that we've removed the item 113 | if (removed) { 114 | Count--; 115 | Shrink(); 116 | } 117 | 118 | return removed; 119 | } 120 | 121 | /// 122 | /// Check if the specified bounds intersect with anything in the tree. See also: GetColliding. 123 | /// 124 | /// bounds to check. 125 | /// True if there was a collision. 126 | public bool IsColliding(Bounds checkBounds) { 127 | //#if UNITY_EDITOR 128 | // For debugging 129 | //AddCollisionCheck(checkBounds); 130 | //#endif 131 | return rootNode.IsColliding(ref checkBounds); 132 | } 133 | 134 | /// 135 | /// Check if the specified ray intersects with anything in the tree. See also: GetColliding. 136 | /// 137 | /// ray to check. 138 | /// distance to check. 139 | /// True if there was a collision. 140 | public bool IsColliding(Ray checkRay, float maxDistance) { 141 | //#if UNITY_EDITOR 142 | // For debugging 143 | //AddCollisionCheck(checkRay); 144 | //#endif 145 | return rootNode.IsColliding(ref checkRay, maxDistance); 146 | } 147 | 148 | /// 149 | /// Returns an array of objects that intersect with the specified bounds, if any. Otherwise returns an empty array. See also: IsColliding. 150 | /// 151 | /// list to store intersections. 152 | /// bounds to check. 153 | /// Objects that intersect with the specified bounds. 154 | public void GetColliding(List collidingWith, Bounds checkBounds) { 155 | //#if UNITY_EDITOR 156 | // For debugging 157 | //AddCollisionCheck(checkBounds); 158 | //#endif 159 | rootNode.GetColliding(ref checkBounds, collidingWith); 160 | } 161 | 162 | /// 163 | /// Returns an array of objects that intersect with the specified ray, if any. Otherwise returns an empty array. See also: IsColliding. 164 | /// 165 | /// list to store intersections. 166 | /// ray to check. 167 | /// distance to check. 168 | /// Objects that intersect with the specified ray. 169 | public void GetColliding(List collidingWith, Ray checkRay, float maxDistance = float.PositiveInfinity) { 170 | //#if UNITY_EDITOR 171 | // For debugging 172 | //AddCollisionCheck(checkRay); 173 | //#endif 174 | rootNode.GetColliding(ref checkRay, collidingWith, maxDistance); 175 | } 176 | 177 | public List GetWithinFrustum(Camera cam) { 178 | var planes = GeometryUtility.CalculateFrustumPlanes(cam); 179 | 180 | var list = new List(); 181 | rootNode.GetWithinFrustum(planes, list); 182 | return list; 183 | } 184 | 185 | public Bounds GetMaxBounds() { 186 | return rootNode.GetBounds(); 187 | } 188 | 189 | /// 190 | /// Draws node boundaries visually for debugging. 191 | /// Must be called from OnDrawGizmos externally. See also: DrawAllObjects. 192 | /// 193 | public void DrawAllBounds() { 194 | rootNode.DrawAllBounds(); 195 | } 196 | 197 | /// 198 | /// Draws the bounds of all objects in the tree visually for debugging. 199 | /// Must be called from OnDrawGizmos externally. See also: DrawAllBounds. 200 | /// 201 | public void DrawAllObjects() { 202 | rootNode.DrawAllObjects(); 203 | } 204 | 205 | // Intended for debugging. Must be called from OnDrawGizmos externally 206 | // See also DrawAllBounds and DrawAllObjects 207 | /// 208 | /// Visualises collision checks from IsColliding and GetColliding. 209 | /// Collision visualisation code is automatically removed from builds so that collision checks aren't slowed down. 210 | /// 211 | #if UNITY_EDITOR 212 | public void DrawCollisionChecks() { 213 | int count = 0; 214 | foreach (Bounds collisionCheck in lastBoundsCollisionChecks) { 215 | Gizmos.color = new Color(1.0f, 1.0f - ((float)count / numCollisionsToSave), 1.0f); 216 | Gizmos.DrawCube(collisionCheck.center, collisionCheck.size); 217 | count++; 218 | } 219 | 220 | foreach (Ray collisionCheck in lastRayCollisionChecks) { 221 | Gizmos.color = new Color(1.0f, 1.0f - ((float)count / numCollisionsToSave), 1.0f); 222 | Gizmos.DrawRay(collisionCheck.origin, collisionCheck.direction); 223 | count++; 224 | } 225 | Gizmos.color = Color.white; 226 | } 227 | #endif 228 | 229 | // #### PRIVATE METHODS #### 230 | 231 | /// 232 | /// Used for visualising collision checks with DrawCollisionChecks. 233 | /// Automatically removed from builds so that collision checks aren't slowed down. 234 | /// 235 | /// bounds that were passed in to check for collisions. 236 | #if UNITY_EDITOR 237 | void AddCollisionCheck(Bounds checkBounds) { 238 | lastBoundsCollisionChecks.Enqueue(checkBounds); 239 | if (lastBoundsCollisionChecks.Count > numCollisionsToSave) { 240 | lastBoundsCollisionChecks.Dequeue(); 241 | } 242 | } 243 | #endif 244 | 245 | /// 246 | /// Used for visualising collision checks with DrawCollisionChecks. 247 | /// Automatically removed from builds so that collision checks aren't slowed down. 248 | /// 249 | /// ray that was passed in to check for collisions. 250 | #if UNITY_EDITOR 251 | void AddCollisionCheck(Ray checkRay) { 252 | lastRayCollisionChecks.Enqueue(checkRay); 253 | if (lastRayCollisionChecks.Count > numCollisionsToSave) { 254 | lastRayCollisionChecks.Dequeue(); 255 | } 256 | } 257 | #endif 258 | 259 | /// 260 | /// Grow the octree to fit in all objects. 261 | /// 262 | /// Direction to grow. 263 | void Grow(Vector3 direction) { 264 | int xDirection = direction.x >= 0 ? 1 : -1; 265 | int yDirection = direction.y >= 0 ? 1 : -1; 266 | int zDirection = direction.z >= 0 ? 1 : -1; 267 | BoundsOctreeNode oldRoot = rootNode; 268 | float half = rootNode.BaseLength / 2; 269 | float newLength = rootNode.BaseLength * 2; 270 | Vector3 newCenter = rootNode.Center + new Vector3(xDirection * half, yDirection * half, zDirection * half); 271 | 272 | // Create a new, bigger octree root node 273 | rootNode = new BoundsOctreeNode(newLength, minSize, looseness, newCenter); 274 | 275 | if (oldRoot.HasAnyObjects()) { 276 | // Create 7 new octree children to go with the old root as children of the new root 277 | int rootPos = rootNode.BestFitChild(oldRoot.Center); 278 | BoundsOctreeNode[] children = new BoundsOctreeNode[8]; 279 | for (int i = 0; i < 8; i++) { 280 | if (i == rootPos) { 281 | children[i] = oldRoot; 282 | } 283 | else { 284 | xDirection = i % 2 == 0 ? -1 : 1; 285 | yDirection = i > 3 ? -1 : 1; 286 | zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; 287 | children[i] = new BoundsOctreeNode(oldRoot.BaseLength, minSize, looseness, newCenter + new Vector3(xDirection * half, yDirection * half, zDirection * half)); 288 | } 289 | } 290 | 291 | // Attach the new children to the new root node 292 | rootNode.SetChildren(children); 293 | } 294 | } 295 | 296 | /// 297 | /// Shrink the octree if possible, else leave it the same. 298 | /// 299 | void Shrink() { 300 | rootNode = rootNode.ShrinkIfPossible(initialSize); 301 | } 302 | } 303 | -------------------------------------------------------------------------------- /Assets/UnityOctree/BoundsOctree.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: acb06913ab8ee284b8b436ed59cce729 3 | timeCreated: 1481513782 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/UnityOctree/BoundsOctreeNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 098c3a5fece947a4ba701dc1f6723c21 3 | timeCreated: 1481513782 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/UnityOctree/PointOctree.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using UnityEngine; 3 | 4 | // A Dynamic Octree for storing any objects that can be described as a single point 5 | // See also: BoundsOctree, where objects are described by AABB bounds 6 | // Octree: An octree is a tree data structure which divides 3D space into smaller partitions (nodes) 7 | // and places objects into the appropriate nodes. This allows fast access to objects 8 | // in an area of interest without having to check every object. 9 | // Dynamic: The octree grows or shrinks as required when objects as added or removed 10 | // It also splits and merges nodes as appropriate. There is no maximum depth. 11 | // Nodes have a constant - numObjectsAllowed - which sets the amount of items allowed in a node before it splits. 12 | // T: The content of the octree can be anything, since the bounds data is supplied separately. 13 | 14 | // Originally written for my game Scraps (http://www.scrapsgame.com) but intended to be general-purpose. 15 | // Copyright 2014 Nition, BSD licence (see LICENCE file). www.momentstudio.co.nz 16 | // Unity-based, but could be adapted to work in pure C# 17 | public class PointOctree { 18 | // The total amount of objects currently in the tree 19 | public int Count { get; private set; } 20 | 21 | // Root node of the octree 22 | PointOctreeNode rootNode; 23 | 24 | // Size that the octree was on creation 25 | readonly float initialSize; 26 | 27 | // Minimum side length that a node can be - essentially an alternative to having a max depth 28 | readonly float minSize; 29 | 30 | /// 31 | /// Constructor for the point octree. 32 | /// 33 | /// Size of the sides of the initial node. The octree will never shrink smaller than this. 34 | /// Position of the centre of the initial node. 35 | /// Nodes will stop splitting if the new nodes would be smaller than this. 36 | public PointOctree(float initialWorldSize, Vector3 initialWorldPos, float minNodeSize) { 37 | if (minNodeSize > initialWorldSize) { 38 | Debug.LogWarning("Minimum node size must be at least as big as the initial world size. Was: " + minNodeSize + " Adjusted to: " + initialWorldSize); 39 | minNodeSize = initialWorldSize; 40 | } 41 | Count = 0; 42 | initialSize = initialWorldSize; 43 | minSize = minNodeSize; 44 | rootNode = new PointOctreeNode(initialSize, minSize, initialWorldPos); 45 | } 46 | 47 | // #### PUBLIC METHODS #### 48 | 49 | /// 50 | /// Add an object. 51 | /// 52 | /// Object to add. 53 | /// Position of the object. 54 | public void Add(T obj, Vector3 objPos) { 55 | // Add object or expand the octree until it can be added 56 | int count = 0; // Safety check against infinite/excessive growth 57 | while (!rootNode.Add(obj, objPos)) { 58 | Grow(objPos - rootNode.Center); 59 | if (++count > 20) { 60 | Debug.LogError("Aborted Add operation as it seemed to be going on forever (" + (count - 1) + ") attempts at growing the octree."); 61 | return; 62 | } 63 | } 64 | Count++; 65 | } 66 | 67 | /// 68 | /// Remove an object. Makes the assumption that the object only exists once in the tree. 69 | /// 70 | /// Object to remove. 71 | /// True if the object was removed successfully. 72 | public bool Remove(T obj) { 73 | bool removed = rootNode.Remove(obj); 74 | 75 | // See if we can shrink the octree down now that we've removed the item 76 | if (removed) { 77 | Count--; 78 | Shrink(); 79 | } 80 | 81 | return removed; 82 | } 83 | 84 | /// 85 | /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree. 86 | /// 87 | /// Object to remove. 88 | /// Position of the object. 89 | /// True if the object was removed successfully. 90 | public bool Remove(T obj, Vector3 objPos) { 91 | bool removed = rootNode.Remove(obj, objPos); 92 | 93 | // See if we can shrink the octree down now that we've removed the item 94 | if (removed) { 95 | Count--; 96 | Shrink(); 97 | } 98 | 99 | return removed; 100 | } 101 | 102 | /// 103 | /// Returns objects that are within of the specified ray. 104 | /// If none, returns false. Uses supplied list for results. 105 | /// 106 | /// The ray. Passing as ref to improve performance since it won't have to be copied. 107 | /// Maximum distance from the ray to consider 108 | /// Pre-initialized list to populate 109 | /// True if items are found, false if not 110 | public bool GetNearbyNonAlloc(Ray ray, float maxDistance, List nearBy) { 111 | nearBy.Clear(); 112 | rootNode.GetNearby(ref ray, maxDistance, nearBy); 113 | if (nearBy.Count > 0) 114 | return true; 115 | return false; 116 | } 117 | 118 | /// 119 | /// Returns objects that are within of the specified ray. 120 | /// If none, returns an empty array (not null). 121 | /// 122 | /// The ray. Passing as ref to improve performance since it won't have to be copied. 123 | /// Maximum distance from the ray to consider. 124 | /// Objects within range. 125 | public T[] GetNearby(Ray ray, float maxDistance) { 126 | List collidingWith = new List(); 127 | rootNode.GetNearby(ref ray, maxDistance, collidingWith); 128 | return collidingWith.ToArray(); 129 | } 130 | 131 | /// 132 | /// Returns objects that are within of the specified position. 133 | /// If none, returns an empty array (not null). 134 | /// 135 | /// The position. Passing as ref to improve performance since it won't have to be copied. 136 | /// Maximum distance from the position to consider. 137 | /// Objects within range. 138 | public T[] GetNearby(Vector3 position, float maxDistance) { 139 | List collidingWith = new List(); 140 | rootNode.GetNearby(ref position, maxDistance, collidingWith); 141 | return collidingWith.ToArray(); 142 | } 143 | 144 | /// 145 | /// Returns objects that are within of the specified position. 146 | /// If none, returns false. Uses supplied list for results. 147 | /// 148 | /// Maximum distance from the position to consider 149 | /// Pre-initialized list to populate 150 | /// True if items are found, false if not 151 | public bool GetNearbyNonAlloc(Vector3 position, float maxDistance, List nearBy) { 152 | nearBy.Clear(); 153 | rootNode.GetNearby(ref position, maxDistance, nearBy); 154 | if (nearBy.Count > 0) 155 | return true; 156 | return false; 157 | } 158 | 159 | /// 160 | /// Return all objects in the tree. 161 | /// If none, returns an empty array (not null). 162 | /// 163 | /// All objects. 164 | public ICollection GetAll() { 165 | List objects = new List(Count); 166 | rootNode.GetAll(objects); 167 | return objects; 168 | } 169 | 170 | /// 171 | /// Draws node boundaries visually for debugging. 172 | /// Must be called from OnDrawGizmos externally. See also: DrawAllObjects. 173 | /// 174 | public void DrawAllBounds() { 175 | rootNode.DrawAllBounds(); 176 | } 177 | 178 | /// 179 | /// Draws the bounds of all objects in the tree visually for debugging. 180 | /// Must be called from OnDrawGizmos externally. See also: DrawAllBounds. 181 | /// 182 | public void DrawAllObjects() { 183 | rootNode.DrawAllObjects(); 184 | } 185 | 186 | // #### PRIVATE METHODS #### 187 | 188 | /// 189 | /// Grow the octree to fit in all objects. 190 | /// 191 | /// Direction to grow. 192 | void Grow(Vector3 direction) { 193 | int xDirection = direction.x >= 0 ? 1 : -1; 194 | int yDirection = direction.y >= 0 ? 1 : -1; 195 | int zDirection = direction.z >= 0 ? 1 : -1; 196 | PointOctreeNode oldRoot = rootNode; 197 | float half = rootNode.SideLength / 2; 198 | float newLength = rootNode.SideLength * 2; 199 | Vector3 newCenter = rootNode.Center + new Vector3(xDirection * half, yDirection * half, zDirection * half); 200 | 201 | // Create a new, bigger octree root node 202 | rootNode = new PointOctreeNode(newLength, minSize, newCenter); 203 | 204 | if (oldRoot.HasAnyObjects()) { 205 | // Create 7 new octree children to go with the old root as children of the new root 206 | int rootPos = rootNode.BestFitChild(oldRoot.Center); 207 | PointOctreeNode[] children = new PointOctreeNode[8]; 208 | for (int i = 0; i < 8; i++) { 209 | if (i == rootPos) { 210 | children[i] = oldRoot; 211 | } 212 | else { 213 | xDirection = i % 2 == 0 ? -1 : 1; 214 | yDirection = i > 3 ? -1 : 1; 215 | zDirection = (i < 2 || (i > 3 && i < 6)) ? -1 : 1; 216 | children[i] = new PointOctreeNode(oldRoot.SideLength, minSize, newCenter + new Vector3(xDirection * half, yDirection * half, zDirection * half)); 217 | } 218 | } 219 | 220 | // Attach the new children to the new root node 221 | rootNode.SetChildren(children); 222 | } 223 | } 224 | 225 | /// 226 | /// Shrink the octree if possible, else leave it the same. 227 | /// 228 | void Shrink() { 229 | rootNode = rootNode.ShrinkIfPossible(initialSize); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /Assets/UnityOctree/PointOctree.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9db0c90c9ab9af246b08fa68962659ae 3 | timeCreated: 1481513782 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/UnityOctree/PointOctreeNode.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using UnityEngine; 4 | 5 | // A node in a PointOctree 6 | // Copyright 2014 Nition, BSD licence (see LICENCE file). www.momentstudio.co.nz 7 | public class PointOctreeNode { 8 | // Centre of this node 9 | public Vector3 Center { get; private set; } 10 | 11 | // Length of the sides of this node 12 | public float SideLength { get; private set; } 13 | 14 | // Minimum size for a node in this octree 15 | float minSize; 16 | 17 | // Bounding box that represents this node 18 | Bounds bounds = default(Bounds); 19 | 20 | // Objects in this node 21 | readonly List objects = new List(); 22 | 23 | // Child nodes, if any 24 | PointOctreeNode[] children = null; 25 | 26 | bool HasChildren { get { return children != null; } } 27 | 28 | // bounds of potential children to this node. These are actual size (with looseness taken into account), not base size 29 | Bounds[] childBounds; 30 | 31 | // If there are already NUM_OBJECTS_ALLOWED in a node, we split it into children 32 | // A generally good number seems to be something around 8-15 33 | const int NUM_OBJECTS_ALLOWED = 8; 34 | 35 | // For reverting the bounds size after temporary changes 36 | Vector3 actualBoundsSize; 37 | 38 | // An object in the octree 39 | class OctreeObject { 40 | public T Obj; 41 | public Vector3 Pos; 42 | } 43 | 44 | /// 45 | /// Constructor. 46 | /// 47 | /// Length of this node, not taking looseness into account. 48 | /// Minimum size of nodes in this octree. 49 | /// Centre position of this node. 50 | public PointOctreeNode(float baseLengthVal, float minSizeVal, Vector3 centerVal) { 51 | SetValues(baseLengthVal, minSizeVal, centerVal); 52 | } 53 | 54 | // #### PUBLIC METHODS #### 55 | 56 | /// 57 | /// Add an object. 58 | /// 59 | /// Object to add. 60 | /// Position of the object. 61 | /// 62 | public bool Add(T obj, Vector3 objPos) { 63 | if (!Encapsulates(bounds, objPos)) { 64 | return false; 65 | } 66 | SubAdd(obj, objPos); 67 | return true; 68 | } 69 | 70 | /// 71 | /// Remove an object. Makes the assumption that the object only exists once in the tree. 72 | /// 73 | /// Object to remove. 74 | /// True if the object was removed successfully. 75 | public bool Remove(T obj) { 76 | bool removed = false; 77 | 78 | for (int i = 0; i < objects.Count; i++) { 79 | if (objects[i].Obj.Equals(obj)) { 80 | removed = objects.Remove(objects[i]); 81 | break; 82 | } 83 | } 84 | 85 | if (!removed && children != null) { 86 | for (int i = 0; i < 8; i++) { 87 | removed = children[i].Remove(obj); 88 | if (removed) break; 89 | } 90 | } 91 | 92 | if (removed && children != null) { 93 | // Check if we should merge nodes now that we've removed an item 94 | if (ShouldMerge()) { 95 | Merge(); 96 | } 97 | } 98 | 99 | return removed; 100 | } 101 | 102 | /// 103 | /// Removes the specified object at the given position. Makes the assumption that the object only exists once in the tree. 104 | /// 105 | /// Object to remove. 106 | /// Position of the object. 107 | /// True if the object was removed successfully. 108 | public bool Remove(T obj, Vector3 objPos) { 109 | if (!Encapsulates(bounds, objPos)) { 110 | return false; 111 | } 112 | return SubRemove(obj, objPos); 113 | } 114 | 115 | /// 116 | /// Return objects that are within maxDistance of the specified ray. 117 | /// 118 | /// The ray. 119 | /// Maximum distance from the ray to consider. 120 | /// List result. 121 | /// Objects within range. 122 | public void GetNearby(ref Ray ray, float maxDistance, List result) { 123 | // Does the ray hit this node at all? 124 | // Note: Expanding the bounds is not exactly the same as a real distance check, but it's fast. 125 | // TODO: Does someone have a fast AND accurate formula to do this check? 126 | bounds.Expand(new Vector3(maxDistance * 2, maxDistance * 2, maxDistance * 2)); 127 | bool intersected = bounds.IntersectRay(ray); 128 | bounds.size = actualBoundsSize; 129 | if (!intersected) { 130 | return; 131 | } 132 | 133 | // Check against any objects in this node 134 | for (int i = 0; i < objects.Count; i++) { 135 | if (SqrDistanceToRay(ray, objects[i].Pos) <= (maxDistance * maxDistance)) { 136 | result.Add(objects[i].Obj); 137 | } 138 | } 139 | 140 | // Check children 141 | if (children != null) { 142 | for (int i = 0; i < 8; i++) { 143 | children[i].GetNearby(ref ray, maxDistance, result); 144 | } 145 | } 146 | } 147 | 148 | /// 149 | /// Return objects that are within of the specified position. 150 | /// 151 | /// The position. 152 | /// Maximum distance from the position to consider. 153 | /// List result. 154 | /// Objects within range. 155 | public void GetNearby(ref Vector3 position, float maxDistance, List result) { 156 | float sqrMaxDistance = maxDistance * maxDistance; 157 | 158 | #if UNITY_2017_1_OR_NEWER 159 | // Does the node intersect with the sphere of center = position and radius = maxDistance? 160 | if ((bounds.ClosestPoint(position) - position).sqrMagnitude > sqrMaxDistance) { 161 | return; 162 | } 163 | #else 164 | // Does the ray hit this node at all? 165 | // Note: Expanding the bounds is not exactly the same as a real distance check, but it's fast 166 | // TODO: Does someone have a fast AND accurate formula to do this check? 167 | bounds.Expand(new Vector3(maxDistance * 2, maxDistance * 2, maxDistance * 2)); 168 | bool contained = bounds.Contains(position); 169 | bounds.size = actualBoundsSize; 170 | if (!contained) { 171 | return; 172 | } 173 | #endif 174 | 175 | // Check against any objects in this node 176 | for (int i = 0; i < objects.Count; i++) { 177 | if ((position - objects[i].Pos).sqrMagnitude <= sqrMaxDistance) { 178 | result.Add(objects[i].Obj); 179 | } 180 | } 181 | 182 | // Check children 183 | if (children != null) { 184 | for (int i = 0; i < 8; i++) { 185 | children[i].GetNearby(ref position, maxDistance, result); 186 | } 187 | } 188 | } 189 | 190 | /// 191 | /// Return all objects in the tree. 192 | /// 193 | /// All objects. 194 | public void GetAll(List result) { 195 | // add directly contained objects 196 | result.AddRange(objects.Select(o => o.Obj)); 197 | 198 | // add children objects 199 | if (children != null) { 200 | for (int i = 0; i < 8; i++) { 201 | children[i].GetAll(result); 202 | } 203 | } 204 | } 205 | 206 | /// 207 | /// Set the 8 children of this octree. 208 | /// 209 | /// The 8 new child nodes. 210 | public void SetChildren(PointOctreeNode[] childOctrees) { 211 | if (childOctrees.Length != 8) { 212 | Debug.LogError("Child octree array must be length 8. Was length: " + childOctrees.Length); 213 | return; 214 | } 215 | 216 | children = childOctrees; 217 | } 218 | 219 | /// 220 | /// Draws node boundaries visually for debugging. 221 | /// Must be called from OnDrawGizmos externally. See also: DrawAllObjects. 222 | /// 223 | /// Used for recurcive calls to this method. 224 | public void DrawAllBounds(float depth = 0) { 225 | float tintVal = depth / 7; // Will eventually get values > 1. Color rounds to 1 automatically 226 | Gizmos.color = new Color(tintVal, 0, 1.0f - tintVal); 227 | 228 | Bounds thisBounds = new Bounds(Center, new Vector3(SideLength, SideLength, SideLength)); 229 | Gizmos.DrawWireCube(thisBounds.center, thisBounds.size); 230 | 231 | if (children != null) { 232 | depth++; 233 | for (int i = 0; i < 8; i++) { 234 | children[i].DrawAllBounds(depth); 235 | } 236 | } 237 | Gizmos.color = Color.white; 238 | } 239 | 240 | /// 241 | /// Draws the bounds of all objects in the tree visually for debugging. 242 | /// Must be called from OnDrawGizmos externally. See also: DrawAllBounds. 243 | /// NOTE: marker.tif must be placed in your Unity /Assets/Gizmos subfolder for this to work. 244 | /// 245 | public void DrawAllObjects() { 246 | float tintVal = SideLength / 20; 247 | Gizmos.color = new Color(0, 1.0f - tintVal, tintVal, 0.25f); 248 | 249 | foreach (OctreeObject obj in objects) { 250 | Gizmos.DrawIcon(obj.Pos, "marker.tif", true); 251 | } 252 | 253 | if (children != null) { 254 | for (int i = 0; i < 8; i++) { 255 | children[i].DrawAllObjects(); 256 | } 257 | } 258 | 259 | Gizmos.color = Color.white; 260 | } 261 | 262 | /// 263 | /// We can shrink the octree if: 264 | /// - This node is >= double minLength in length 265 | /// - All objects in the root node are within one octant 266 | /// - This node doesn't have children, or does but 7/8 children are empty 267 | /// We can also shrink it if there are no objects left at all! 268 | /// 269 | /// Minimum dimensions of a node in this octree. 270 | /// The new root, or the existing one if we didn't shrink. 271 | public PointOctreeNode ShrinkIfPossible(float minLength) { 272 | if (SideLength < (2 * minLength)) { 273 | return this; 274 | } 275 | if (objects.Count == 0 && (children == null || children.Length == 0)) { 276 | return this; 277 | } 278 | 279 | // Check objects in root 280 | int bestFit = -1; 281 | for (int i = 0; i < objects.Count; i++) { 282 | OctreeObject curObj = objects[i]; 283 | int newBestFit = BestFitChild(curObj.Pos); 284 | if (i == 0 || newBestFit == bestFit) { 285 | if (bestFit < 0) { 286 | bestFit = newBestFit; 287 | } 288 | } 289 | else { 290 | return this; // Can't reduce - objects fit in different octants 291 | } 292 | } 293 | 294 | // Check objects in children if there are any 295 | if (children != null) { 296 | bool childHadContent = false; 297 | for (int i = 0; i < children.Length; i++) { 298 | if (children[i].HasAnyObjects()) { 299 | if (childHadContent) { 300 | return this; // Can't shrink - another child had content already 301 | } 302 | if (bestFit >= 0 && bestFit != i) { 303 | return this; // Can't reduce - objects in root are in a different octant to objects in child 304 | } 305 | childHadContent = true; 306 | bestFit = i; 307 | } 308 | } 309 | } 310 | 311 | // Can reduce 312 | if (children == null) { 313 | // We don't have any children, so just shrink this node to the new size 314 | // We already know that everything will still fit in it 315 | SetValues(SideLength / 2, minSize, childBounds[bestFit].center); 316 | return this; 317 | } 318 | 319 | // We have children. Use the appropriate child as the new root node 320 | return children[bestFit]; 321 | } 322 | 323 | /// 324 | /// Find which child node this object would be most likely to fit in. 325 | /// 326 | /// The object's position. 327 | /// One of the eight child octants. 328 | public int BestFitChild(Vector3 objPos) { 329 | return (objPos.x <= Center.x ? 0 : 1) + (objPos.y >= Center.y ? 0 : 4) + (objPos.z <= Center.z ? 0 : 2); 330 | } 331 | 332 | /// 333 | /// Checks if this node or anything below it has something in it. 334 | /// 335 | /// True if this node or any of its children, grandchildren etc have something in them 336 | public bool HasAnyObjects() { 337 | if (objects.Count > 0) return true; 338 | 339 | if (children != null) { 340 | for (int i = 0; i < 8; i++) { 341 | if (children[i].HasAnyObjects()) return true; 342 | } 343 | } 344 | 345 | return false; 346 | } 347 | 348 | /* 349 | /// 350 | /// Get the total amount of objects in this node and all its children, grandchildren etc. Useful for debugging. 351 | /// 352 | /// Used by recursive calls to add to the previous total. 353 | /// Total objects in this node and its children, grandchildren etc. 354 | public int GetTotalObjects(int startingNum = 0) { 355 | int totalObjects = startingNum + objects.Count; 356 | if (children != null) { 357 | for (int i = 0; i < 8; i++) { 358 | totalObjects += children[i].GetTotalObjects(); 359 | } 360 | } 361 | return totalObjects; 362 | } 363 | */ 364 | 365 | // #### PRIVATE METHODS #### 366 | 367 | /// 368 | /// Set values for this node. 369 | /// 370 | /// Length of this node, not taking looseness into account. 371 | /// Minimum size of nodes in this octree. 372 | /// Centre position of this node. 373 | void SetValues(float baseLengthVal, float minSizeVal, Vector3 centerVal) { 374 | SideLength = baseLengthVal; 375 | minSize = minSizeVal; 376 | Center = centerVal; 377 | 378 | // Create the bounding box. 379 | actualBoundsSize = new Vector3(SideLength, SideLength, SideLength); 380 | bounds = new Bounds(Center, actualBoundsSize); 381 | 382 | float quarter = SideLength / 4f; 383 | float childActualLength = SideLength / 2; 384 | Vector3 childActualSize = new Vector3(childActualLength, childActualLength, childActualLength); 385 | childBounds = new Bounds[8]; 386 | childBounds[0] = new Bounds(Center + new Vector3(-quarter, quarter, -quarter), childActualSize); 387 | childBounds[1] = new Bounds(Center + new Vector3(quarter, quarter, -quarter), childActualSize); 388 | childBounds[2] = new Bounds(Center + new Vector3(-quarter, quarter, quarter), childActualSize); 389 | childBounds[3] = new Bounds(Center + new Vector3(quarter, quarter, quarter), childActualSize); 390 | childBounds[4] = new Bounds(Center + new Vector3(-quarter, -quarter, -quarter), childActualSize); 391 | childBounds[5] = new Bounds(Center + new Vector3(quarter, -quarter, -quarter), childActualSize); 392 | childBounds[6] = new Bounds(Center + new Vector3(-quarter, -quarter, quarter), childActualSize); 393 | childBounds[7] = new Bounds(Center + new Vector3(quarter, -quarter, quarter), childActualSize); 394 | } 395 | 396 | /// 397 | /// Private counterpart to the public Add method. 398 | /// 399 | /// Object to add. 400 | /// Position of the object. 401 | void SubAdd(T obj, Vector3 objPos) { 402 | // We know it fits at this level if we've got this far 403 | 404 | // We always put things in the deepest possible child 405 | // So we can skip checks and simply move down if there are children aleady 406 | if (!HasChildren) { 407 | // Just add if few objects are here, or children would be below min size 408 | if (objects.Count < NUM_OBJECTS_ALLOWED || (SideLength / 2) < minSize) { 409 | OctreeObject newObj = new OctreeObject { Obj = obj, Pos = objPos }; 410 | objects.Add(newObj); 411 | return; // We're done. No children yet 412 | } 413 | 414 | // Enough objects in this node already: Create the 8 children 415 | int bestFitChild; 416 | if (children == null) { 417 | Split(); 418 | if (children == null) { 419 | Debug.LogError("Child creation failed for an unknown reason. Early exit."); 420 | return; 421 | } 422 | 423 | // Now that we have the new children, move this node's existing objects into them 424 | for (int i = objects.Count - 1; i >= 0; i--) { 425 | OctreeObject existingObj = objects[i]; 426 | // Find which child the object is closest to based on where the 427 | // object's center is located in relation to the octree's center 428 | bestFitChild = BestFitChild(existingObj.Pos); 429 | children[bestFitChild].SubAdd(existingObj.Obj, existingObj.Pos); // Go a level deeper 430 | objects.Remove(existingObj); // Remove from here 431 | } 432 | } 433 | } 434 | 435 | // Handle the new object we're adding now 436 | int bestFit = BestFitChild(objPos); 437 | children[bestFit].SubAdd(obj, objPos); 438 | } 439 | 440 | /// 441 | /// Private counterpart to the public method. 442 | /// 443 | /// Object to remove. 444 | /// Position of the object. 445 | /// True if the object was removed successfully. 446 | bool SubRemove(T obj, Vector3 objPos) { 447 | bool removed = false; 448 | 449 | for (int i = 0; i < objects.Count; i++) { 450 | if (objects[i].Obj.Equals(obj)) { 451 | removed = objects.Remove(objects[i]); 452 | break; 453 | } 454 | } 455 | 456 | if (!removed && children != null) { 457 | int bestFitChild = BestFitChild(objPos); 458 | removed = children[bestFitChild].SubRemove(obj, objPos); 459 | } 460 | 461 | if (removed && children != null) { 462 | // Check if we should merge nodes now that we've removed an item 463 | if (ShouldMerge()) { 464 | Merge(); 465 | } 466 | } 467 | 468 | return removed; 469 | } 470 | 471 | /// 472 | /// Splits the octree into eight children. 473 | /// 474 | void Split() { 475 | float quarter = SideLength / 4f; 476 | float newLength = SideLength / 2; 477 | children = new PointOctreeNode[8]; 478 | children[0] = new PointOctreeNode(newLength, minSize, Center + new Vector3(-quarter, quarter, -quarter)); 479 | children[1] = new PointOctreeNode(newLength, minSize, Center + new Vector3(quarter, quarter, -quarter)); 480 | children[2] = new PointOctreeNode(newLength, minSize, Center + new Vector3(-quarter, quarter, quarter)); 481 | children[3] = new PointOctreeNode(newLength, minSize, Center + new Vector3(quarter, quarter, quarter)); 482 | children[4] = new PointOctreeNode(newLength, minSize, Center + new Vector3(-quarter, -quarter, -quarter)); 483 | children[5] = new PointOctreeNode(newLength, minSize, Center + new Vector3(quarter, -quarter, -quarter)); 484 | children[6] = new PointOctreeNode(newLength, minSize, Center + new Vector3(-quarter, -quarter, quarter)); 485 | children[7] = new PointOctreeNode(newLength, minSize, Center + new Vector3(quarter, -quarter, quarter)); 486 | } 487 | 488 | /// 489 | /// Merge all children into this node - the opposite of Split. 490 | /// Note: We only have to check one level down since a merge will never happen if the children already have children, 491 | /// since THAT won't happen unless there are already too many objects to merge. 492 | /// 493 | void Merge() { 494 | // Note: We know children != null or we wouldn't be merging 495 | for (int i = 0; i < 8; i++) { 496 | PointOctreeNode curChild = children[i]; 497 | int numObjects = curChild.objects.Count; 498 | for (int j = numObjects - 1; j >= 0; j--) { 499 | OctreeObject curObj = curChild.objects[j]; 500 | objects.Add(curObj); 501 | } 502 | } 503 | // Remove the child nodes (and the objects in them - they've been added elsewhere now) 504 | children = null; 505 | } 506 | 507 | /// 508 | /// Checks if outerBounds encapsulates the given point. 509 | /// 510 | /// Outer bounds. 511 | /// Point. 512 | /// True if innerBounds is fully encapsulated by outerBounds. 513 | static bool Encapsulates(Bounds outerBounds, Vector3 point) { 514 | return outerBounds.Contains(point); 515 | } 516 | 517 | /// 518 | /// Checks if there are few enough objects in this node and its children that the children should all be merged into this. 519 | /// 520 | /// True there are less or the same abount of objects in this and its children than numObjectsAllowed. 521 | bool ShouldMerge() { 522 | int totalObjects = objects.Count; 523 | if (children != null) { 524 | foreach (PointOctreeNode child in children) { 525 | if (child.children != null) { 526 | // If any of the *children* have children, there are definitely too many to merge, 527 | // or the child woudl have been merged already 528 | return false; 529 | } 530 | totalObjects += child.objects.Count; 531 | } 532 | } 533 | return totalObjects <= NUM_OBJECTS_ALLOWED; 534 | } 535 | 536 | /// 537 | /// Returns the closest distance to the given ray from a point. 538 | /// 539 | /// The ray. 540 | /// The point to check distance from the ray. 541 | /// Squared distance from the point to the closest point of the ray. 542 | public static float SqrDistanceToRay(Ray ray, Vector3 point) { 543 | return Vector3.Cross(ray.direction, point - ray.origin).sqrMagnitude; 544 | } 545 | } 546 | -------------------------------------------------------------------------------- /Assets/UnityOctree/PointOctreeNode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a3117d130f3f2b46b4761386f25c3b8 3 | timeCreated: 1481513782 4 | licenseType: Pro 5 | MonoImporter: 6 | serializedVersion: 2 7 | defaultReferences: [] 8 | executionOrder: 0 9 | icon: {instanceID: 0} 10 | userData: 11 | assetBundleName: 12 | assetBundleVariant: 13 | -------------------------------------------------------------------------------- /Assets/WorldMonitor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 877efc7026ea890479a88c338061bb10 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Assets/WorldMonitors.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace oti.AI 6 | { 7 | public class WorldMonitors : MonoBehaviour 8 | { 9 | /// 10 | /// User defined list of GameObject to track 11 | /// 12 | [HideInInspector] // hides in child classes only 13 | public List TrackedObjects = new List(); 14 | 15 | /// 16 | /// User defined area for defining close objects 17 | /// 18 | [HideInInspector] // hides in child classes only 19 | public List ThresholdSet = new List(); 20 | 21 | /// 22 | /// Delegate for tracked object conflicts. 23 | /// 24 | /// The types of objects as defined in WorldMonitors 25 | /// The positions of the objects causing the conflict 26 | public delegate void ObjectConflictHandler(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes); 27 | 28 | /// 29 | /// Event to raise awareness to listeners of the increase tracked object conflict 30 | /// 31 | public event ObjectConflictHandler ConflictEnterers; 32 | 33 | /// 34 | /// Event to raise awareness to listeners of the reduced tracked object conflict 35 | /// 36 | public event ObjectConflictHandler ConflictLeavers; 37 | 38 | /// 39 | /// Event to inform listeners all conflicting objects have ended 40 | /// 41 | public event ObjectConflictHandler ConflictEnd; 42 | 43 | //Provide WorldMonitor a method to raise event from 44 | public void RaiseConflictEnterers(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes) 45 | { 46 | ConflictEnterers?.Invoke(objectWithConflict, conflictingObjects, conflictingTypes); 47 | } 48 | 49 | //Provide WorldMonitor a method to raise event from 50 | public void RaiseConflictLeavers(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes) 51 | { 52 | ConflictLeavers?.Invoke(objectWithConflict, conflictingObjects, conflictingTypes); 53 | } 54 | 55 | //Provide WorldMonitor a method to raise event from 56 | public void EndConflicts(GameObject objectWithEndedConflict) 57 | { 58 | ConflictEnd?.Invoke(objectWithEndedConflict, default(GameObject[]), default(string[])); 59 | } 60 | 61 | private void Start() 62 | { 63 | //if user hasn't created a GameObject with WorldMonitor singleton 64 | if (!WorldMonitor.Instance) 65 | { 66 | new GameObject(gameObject.name + "_WMContainer", typeof(WorldMonitor)); 67 | } 68 | 69 | if(WorldMonitor.Instance.TrackingMode == TrackingMode.UnityTriggers) 70 | { 71 | foreach (TrackedObjectContainer toc in TrackedObjects) 72 | { 73 | foreach (GameObject go in toc.TrackedObjects) 74 | { 75 | if (!go.GetComponent()) 76 | go.AddComponent(); 77 | 78 | go.GetComponent().AcceptOwner(this); 79 | } 80 | } 81 | } 82 | } 83 | } 84 | 85 | [System.Serializable] 86 | public class TrackedObjectContainer 87 | { 88 | public List TrackedObjects = new List(); 89 | } 90 | } -------------------------------------------------------------------------------- /Assets/WorldMonitors.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56a76824d65be454581186658dd2b4c0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Images/20k.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/20k.PNG -------------------------------------------------------------------------------- /Images/exampleTrack.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/exampleTrack.PNG -------------------------------------------------------------------------------- /Images/inspInitial.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/inspInitial.PNG -------------------------------------------------------------------------------- /Images/inspSymmetricObjects.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/inspSymmetricObjects.PNG -------------------------------------------------------------------------------- /Images/smallScene.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/smallScene.PNG -------------------------------------------------------------------------------- /Images/trackingScene.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/trackingScene.PNG -------------------------------------------------------------------------------- /Images/triggerVsOctreeConflict.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/triggerVsOctreeConflict.PNG -------------------------------------------------------------------------------- /Images/worldMonitor.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/phatboysh/DynamicObjectTracking/0eca5e19ac230e4a71bca647deebcd2de25b71a4/Images/worldMonitor.PNG -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Joey Mansfield 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Packages/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | } 4 | } 5 | -------------------------------------------------------------------------------- /ProjectSettings/AudioManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!11 &1 4 | AudioManager: 5 | m_ObjectHideFlags: 0 6 | m_Volume: 1 7 | Rolloff Scale: 1 8 | Doppler Factor: 1 9 | Default Speaker Mode: 2 10 | m_SampleRate: 0 11 | m_DSPBufferSize: 1024 12 | m_VirtualVoiceCount: 512 13 | m_RealVoiceCount: 32 14 | m_SpatializerPlugin: 15 | m_AmbisonicDecoderPlugin: 16 | m_DisableAudio: 0 17 | m_VirtualizeEffects: 1 18 | -------------------------------------------------------------------------------- /ProjectSettings/ClusterInputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!236 &1 4 | ClusterInputManager: 5 | m_ObjectHideFlags: 0 6 | m_Inputs: [] 7 | -------------------------------------------------------------------------------- /ProjectSettings/DynamicsManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!55 &1 4 | PhysicsManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_Gravity: {x: 0, y: -9.81, z: 0} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_BounceThreshold: 2 10 | m_SleepThreshold: 0.005 11 | m_DefaultContactOffset: 0.01 12 | m_DefaultSolverIterations: 6 13 | m_DefaultSolverVelocityIterations: 1 14 | m_QueriesHitBackfaces: 0 15 | m_QueriesHitTriggers: 1 16 | m_EnableAdaptiveForce: 0 17 | m_ClothInterCollisionDistance: 0 18 | m_ClothInterCollisionStiffness: 0 19 | m_ContactsGeneration: 1 20 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 21 | m_AutoSimulation: 1 22 | m_AutoSyncTransforms: 1 23 | m_ClothInterCollisionSettingsToggle: 0 24 | m_ContactPairsMode: 0 25 | m_BroadphaseType: 0 26 | m_WorldBounds: 27 | m_Center: {x: 0, y: 0, z: 0} 28 | m_Extent: {x: 250, y: 250, z: 250} 29 | m_WorldSubdivisions: 8 30 | -------------------------------------------------------------------------------- /ProjectSettings/EditorBuildSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1045 &1 4 | EditorBuildSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Scenes: 8 | - enabled: 1 9 | path: Assets/Scenes/SampleScene.unity 10 | guid: 99c9720ab356a0642a771bea13969a05 11 | m_configObjects: {} 12 | -------------------------------------------------------------------------------- /ProjectSettings/EditorSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!159 &1 4 | EditorSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 7 7 | m_ExternalVersionControlSupport: Visible Meta Files 8 | m_SerializationMode: 2 9 | m_LineEndingsForNewScripts: 2 10 | m_DefaultBehaviorMode: 0 11 | m_SpritePackerMode: 0 12 | m_SpritePackerPaddingPower: 1 13 | m_EtcTextureCompressorBehavior: 1 14 | m_EtcTextureFastCompressor: 1 15 | m_EtcTextureNormalCompressor: 2 16 | m_EtcTextureBestCompressor: 4 17 | m_ProjectGenerationIncludedExtensions: txt;xml;fnt;cd 18 | m_ProjectGenerationRootNamespace: 19 | m_UserGeneratedProjectSuffix: 20 | m_CollabEditorSettings: 21 | inProgressEnabled: 1 22 | -------------------------------------------------------------------------------- /ProjectSettings/GraphicsSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!30 &1 4 | GraphicsSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 12 7 | m_Deferred: 8 | m_Mode: 1 9 | m_Shader: {fileID: 69, guid: 0000000000000000f000000000000000, type: 0} 10 | m_DeferredReflections: 11 | m_Mode: 1 12 | m_Shader: {fileID: 74, guid: 0000000000000000f000000000000000, type: 0} 13 | m_ScreenSpaceShadows: 14 | m_Mode: 1 15 | m_Shader: {fileID: 64, guid: 0000000000000000f000000000000000, type: 0} 16 | m_LegacyDeferred: 17 | m_Mode: 1 18 | m_Shader: {fileID: 63, guid: 0000000000000000f000000000000000, type: 0} 19 | m_DepthNormals: 20 | m_Mode: 1 21 | m_Shader: {fileID: 62, guid: 0000000000000000f000000000000000, type: 0} 22 | m_MotionVectors: 23 | m_Mode: 1 24 | m_Shader: {fileID: 75, guid: 0000000000000000f000000000000000, type: 0} 25 | m_LightHalo: 26 | m_Mode: 1 27 | m_Shader: {fileID: 105, guid: 0000000000000000f000000000000000, type: 0} 28 | m_LensFlare: 29 | m_Mode: 1 30 | m_Shader: {fileID: 102, guid: 0000000000000000f000000000000000, type: 0} 31 | m_AlwaysIncludedShaders: 32 | - {fileID: 7, guid: 0000000000000000f000000000000000, type: 0} 33 | - {fileID: 15104, guid: 0000000000000000f000000000000000, type: 0} 34 | - {fileID: 15105, guid: 0000000000000000f000000000000000, type: 0} 35 | - {fileID: 15106, guid: 0000000000000000f000000000000000, type: 0} 36 | - {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0} 37 | - {fileID: 10770, guid: 0000000000000000f000000000000000, type: 0} 38 | - {fileID: 17000, guid: 0000000000000000f000000000000000, type: 0} 39 | - {fileID: 16000, guid: 0000000000000000f000000000000000, type: 0} 40 | m_PreloadedShaders: [] 41 | m_SpritesDefaultMaterial: {fileID: 10754, guid: 0000000000000000f000000000000000, 42 | type: 0} 43 | m_CustomRenderPipeline: {fileID: 0} 44 | m_TransparencySortMode: 0 45 | m_TransparencySortAxis: {x: 0, y: 0, z: 1} 46 | m_DefaultRenderingPath: 1 47 | m_DefaultMobileRenderingPath: 1 48 | m_TierSettings: [] 49 | m_LightmapStripping: 0 50 | m_FogStripping: 0 51 | m_InstancingStripping: 0 52 | m_LightmapKeepPlain: 1 53 | m_LightmapKeepDirCombined: 1 54 | m_LightmapKeepDynamicPlain: 1 55 | m_LightmapKeepDynamicDirCombined: 1 56 | m_LightmapKeepShadowMask: 1 57 | m_LightmapKeepSubtractive: 1 58 | m_FogKeepLinear: 1 59 | m_FogKeepExp: 1 60 | m_FogKeepExp2: 1 61 | m_AlbedoSwatchInfos: [] 62 | m_LightsUseLinearIntensity: 0 63 | m_LightsUseColorTemperature: 0 64 | -------------------------------------------------------------------------------- /ProjectSettings/InputManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!13 &1 4 | InputManager: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | m_Axes: 8 | - serializedVersion: 3 9 | m_Name: Horizontal 10 | descriptiveName: 11 | descriptiveNegativeName: 12 | negativeButton: left 13 | positiveButton: right 14 | altNegativeButton: a 15 | altPositiveButton: d 16 | gravity: 3 17 | dead: 0.001 18 | sensitivity: 3 19 | snap: 1 20 | invert: 0 21 | type: 0 22 | axis: 0 23 | joyNum: 0 24 | - serializedVersion: 3 25 | m_Name: Vertical 26 | descriptiveName: 27 | descriptiveNegativeName: 28 | negativeButton: down 29 | positiveButton: up 30 | altNegativeButton: s 31 | altPositiveButton: w 32 | gravity: 3 33 | dead: 0.001 34 | sensitivity: 3 35 | snap: 1 36 | invert: 0 37 | type: 0 38 | axis: 0 39 | joyNum: 0 40 | - serializedVersion: 3 41 | m_Name: Fire1 42 | descriptiveName: 43 | descriptiveNegativeName: 44 | negativeButton: 45 | positiveButton: left ctrl 46 | altNegativeButton: 47 | altPositiveButton: mouse 0 48 | gravity: 1000 49 | dead: 0.001 50 | sensitivity: 1000 51 | snap: 0 52 | invert: 0 53 | type: 0 54 | axis: 0 55 | joyNum: 0 56 | - serializedVersion: 3 57 | m_Name: Fire2 58 | descriptiveName: 59 | descriptiveNegativeName: 60 | negativeButton: 61 | positiveButton: left alt 62 | altNegativeButton: 63 | altPositiveButton: mouse 1 64 | gravity: 1000 65 | dead: 0.001 66 | sensitivity: 1000 67 | snap: 0 68 | invert: 0 69 | type: 0 70 | axis: 0 71 | joyNum: 0 72 | - serializedVersion: 3 73 | m_Name: Fire3 74 | descriptiveName: 75 | descriptiveNegativeName: 76 | negativeButton: 77 | positiveButton: left shift 78 | altNegativeButton: 79 | altPositiveButton: mouse 2 80 | gravity: 1000 81 | dead: 0.001 82 | sensitivity: 1000 83 | snap: 0 84 | invert: 0 85 | type: 0 86 | axis: 0 87 | joyNum: 0 88 | - serializedVersion: 3 89 | m_Name: Jump 90 | descriptiveName: 91 | descriptiveNegativeName: 92 | negativeButton: 93 | positiveButton: space 94 | altNegativeButton: 95 | altPositiveButton: 96 | gravity: 1000 97 | dead: 0.001 98 | sensitivity: 1000 99 | snap: 0 100 | invert: 0 101 | type: 0 102 | axis: 0 103 | joyNum: 0 104 | - serializedVersion: 3 105 | m_Name: Mouse X 106 | descriptiveName: 107 | descriptiveNegativeName: 108 | negativeButton: 109 | positiveButton: 110 | altNegativeButton: 111 | altPositiveButton: 112 | gravity: 0 113 | dead: 0 114 | sensitivity: 0.1 115 | snap: 0 116 | invert: 0 117 | type: 1 118 | axis: 0 119 | joyNum: 0 120 | - serializedVersion: 3 121 | m_Name: Mouse Y 122 | descriptiveName: 123 | descriptiveNegativeName: 124 | negativeButton: 125 | positiveButton: 126 | altNegativeButton: 127 | altPositiveButton: 128 | gravity: 0 129 | dead: 0 130 | sensitivity: 0.1 131 | snap: 0 132 | invert: 0 133 | type: 1 134 | axis: 1 135 | joyNum: 0 136 | - serializedVersion: 3 137 | m_Name: Mouse ScrollWheel 138 | descriptiveName: 139 | descriptiveNegativeName: 140 | negativeButton: 141 | positiveButton: 142 | altNegativeButton: 143 | altPositiveButton: 144 | gravity: 0 145 | dead: 0 146 | sensitivity: 0.1 147 | snap: 0 148 | invert: 0 149 | type: 1 150 | axis: 2 151 | joyNum: 0 152 | - serializedVersion: 3 153 | m_Name: Horizontal 154 | descriptiveName: 155 | descriptiveNegativeName: 156 | negativeButton: 157 | positiveButton: 158 | altNegativeButton: 159 | altPositiveButton: 160 | gravity: 0 161 | dead: 0.19 162 | sensitivity: 1 163 | snap: 0 164 | invert: 0 165 | type: 2 166 | axis: 0 167 | joyNum: 0 168 | - serializedVersion: 3 169 | m_Name: Vertical 170 | descriptiveName: 171 | descriptiveNegativeName: 172 | negativeButton: 173 | positiveButton: 174 | altNegativeButton: 175 | altPositiveButton: 176 | gravity: 0 177 | dead: 0.19 178 | sensitivity: 1 179 | snap: 0 180 | invert: 1 181 | type: 2 182 | axis: 1 183 | joyNum: 0 184 | - serializedVersion: 3 185 | m_Name: Fire1 186 | descriptiveName: 187 | descriptiveNegativeName: 188 | negativeButton: 189 | positiveButton: joystick button 0 190 | altNegativeButton: 191 | altPositiveButton: 192 | gravity: 1000 193 | dead: 0.001 194 | sensitivity: 1000 195 | snap: 0 196 | invert: 0 197 | type: 0 198 | axis: 0 199 | joyNum: 0 200 | - serializedVersion: 3 201 | m_Name: Fire2 202 | descriptiveName: 203 | descriptiveNegativeName: 204 | negativeButton: 205 | positiveButton: joystick button 1 206 | altNegativeButton: 207 | altPositiveButton: 208 | gravity: 1000 209 | dead: 0.001 210 | sensitivity: 1000 211 | snap: 0 212 | invert: 0 213 | type: 0 214 | axis: 0 215 | joyNum: 0 216 | - serializedVersion: 3 217 | m_Name: Fire3 218 | descriptiveName: 219 | descriptiveNegativeName: 220 | negativeButton: 221 | positiveButton: joystick button 2 222 | altNegativeButton: 223 | altPositiveButton: 224 | gravity: 1000 225 | dead: 0.001 226 | sensitivity: 1000 227 | snap: 0 228 | invert: 0 229 | type: 0 230 | axis: 0 231 | joyNum: 0 232 | - serializedVersion: 3 233 | m_Name: Jump 234 | descriptiveName: 235 | descriptiveNegativeName: 236 | negativeButton: 237 | positiveButton: joystick button 3 238 | altNegativeButton: 239 | altPositiveButton: 240 | gravity: 1000 241 | dead: 0.001 242 | sensitivity: 1000 243 | snap: 0 244 | invert: 0 245 | type: 0 246 | axis: 0 247 | joyNum: 0 248 | - serializedVersion: 3 249 | m_Name: Submit 250 | descriptiveName: 251 | descriptiveNegativeName: 252 | negativeButton: 253 | positiveButton: return 254 | altNegativeButton: 255 | altPositiveButton: joystick button 0 256 | gravity: 1000 257 | dead: 0.001 258 | sensitivity: 1000 259 | snap: 0 260 | invert: 0 261 | type: 0 262 | axis: 0 263 | joyNum: 0 264 | - serializedVersion: 3 265 | m_Name: Submit 266 | descriptiveName: 267 | descriptiveNegativeName: 268 | negativeButton: 269 | positiveButton: enter 270 | altNegativeButton: 271 | altPositiveButton: space 272 | gravity: 1000 273 | dead: 0.001 274 | sensitivity: 1000 275 | snap: 0 276 | invert: 0 277 | type: 0 278 | axis: 0 279 | joyNum: 0 280 | - serializedVersion: 3 281 | m_Name: Cancel 282 | descriptiveName: 283 | descriptiveNegativeName: 284 | negativeButton: 285 | positiveButton: escape 286 | altNegativeButton: 287 | altPositiveButton: joystick button 1 288 | gravity: 1000 289 | dead: 0.001 290 | sensitivity: 1000 291 | snap: 0 292 | invert: 0 293 | type: 0 294 | axis: 0 295 | joyNum: 0 296 | -------------------------------------------------------------------------------- /ProjectSettings/NavMeshAreas.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!126 &1 4 | NavMeshProjectSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 2 7 | areas: 8 | - name: Walkable 9 | cost: 1 10 | - name: Not Walkable 11 | cost: 1 12 | - name: Jump 13 | cost: 2 14 | - name: 15 | cost: 1 16 | - name: 17 | cost: 1 18 | - name: 19 | cost: 1 20 | - name: 21 | cost: 1 22 | - name: 23 | cost: 1 24 | - name: 25 | cost: 1 26 | - name: 27 | cost: 1 28 | - name: 29 | cost: 1 30 | - name: 31 | cost: 1 32 | - name: 33 | cost: 1 34 | - name: 35 | cost: 1 36 | - name: 37 | cost: 1 38 | - name: 39 | cost: 1 40 | - name: 41 | cost: 1 42 | - name: 43 | cost: 1 44 | - name: 45 | cost: 1 46 | - name: 47 | cost: 1 48 | - name: 49 | cost: 1 50 | - name: 51 | cost: 1 52 | - name: 53 | cost: 1 54 | - name: 55 | cost: 1 56 | - name: 57 | cost: 1 58 | - name: 59 | cost: 1 60 | - name: 61 | cost: 1 62 | - name: 63 | cost: 1 64 | - name: 65 | cost: 1 66 | - name: 67 | cost: 1 68 | - name: 69 | cost: 1 70 | - name: 71 | cost: 1 72 | m_LastAgentTypeID: -1372625422 73 | m_Settings: 74 | - serializedVersion: 2 75 | agentTypeID: 0 76 | agentRadius: 0.5 77 | agentHeight: 2 78 | agentSlope: 45 79 | agentClimb: 0.75 80 | ledgeDropHeight: 0 81 | maxJumpAcrossDistance: 0 82 | minRegionArea: 2 83 | manualCellSize: 0 84 | cellSize: 0.16666667 85 | manualTileSize: 0 86 | tileSize: 256 87 | accuratePlacement: 0 88 | debug: 89 | m_Flags: 0 90 | m_SettingNames: 91 | - Humanoid 92 | -------------------------------------------------------------------------------- /ProjectSettings/NetworkManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!149 &1 4 | NetworkManager: 5 | m_ObjectHideFlags: 0 6 | m_DebugLevel: 0 7 | m_Sendrate: 15 8 | m_AssetToPrefab: {} 9 | -------------------------------------------------------------------------------- /ProjectSettings/Physics2DSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!19 &1 4 | Physics2DSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 3 7 | m_Gravity: {x: 0, y: -9.81} 8 | m_DefaultMaterial: {fileID: 0} 9 | m_VelocityIterations: 8 10 | m_PositionIterations: 3 11 | m_VelocityThreshold: 1 12 | m_MaxLinearCorrection: 0.2 13 | m_MaxAngularCorrection: 8 14 | m_MaxTranslationSpeed: 100 15 | m_MaxRotationSpeed: 360 16 | m_BaumgarteScale: 0.2 17 | m_BaumgarteTimeOfImpactScale: 0.75 18 | m_TimeToSleep: 0.5 19 | m_LinearSleepTolerance: 0.01 20 | m_AngularSleepTolerance: 2 21 | m_DefaultContactOffset: 0.01 22 | m_AutoSimulation: 1 23 | m_QueriesHitTriggers: 1 24 | m_QueriesStartInColliders: 1 25 | m_ChangeStopsCallbacks: 0 26 | m_CallbacksOnDisable: 1 27 | m_AutoSyncTransforms: 1 28 | m_AlwaysShowColliders: 0 29 | m_ShowColliderSleep: 1 30 | m_ShowColliderContacts: 0 31 | m_ShowColliderAABB: 0 32 | m_ContactArrowScale: 0.2 33 | m_ColliderAwakeColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.7529412} 34 | m_ColliderAsleepColor: {r: 0.5686275, g: 0.95686275, b: 0.54509807, a: 0.36078432} 35 | m_ColliderContactColor: {r: 1, g: 0, b: 1, a: 0.6862745} 36 | m_ColliderAABBColor: {r: 1, g: 1, b: 0, a: 0.2509804} 37 | m_LayerCollisionMatrix: ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 38 | -------------------------------------------------------------------------------- /ProjectSettings/PresetManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!1386491679 &1 4 | PresetManager: 5 | m_ObjectHideFlags: 0 6 | m_DefaultList: 7 | - type: 8 | m_NativeTypeID: 108 9 | m_ManagedTypePPtr: {fileID: 0} 10 | m_ManagedTypeFallback: 11 | defaultPresets: 12 | - m_Preset: {fileID: 2655988077585873504, guid: c1cf8506f04ef2c4a88b64b6c4202eea, 13 | type: 2} 14 | - type: 15 | m_NativeTypeID: 1020 16 | m_ManagedTypePPtr: {fileID: 0} 17 | m_ManagedTypeFallback: 18 | defaultPresets: 19 | - m_Preset: {fileID: 2655988077585873504, guid: 0cd792cc87e492d43b4e95b205fc5cc6, 20 | type: 2} 21 | - type: 22 | m_NativeTypeID: 1006 23 | m_ManagedTypePPtr: {fileID: 0} 24 | m_ManagedTypeFallback: 25 | defaultPresets: 26 | - m_Preset: {fileID: 2655988077585873504, guid: 7a99f8aa944efe94cb9bd74562b7d5f9, 27 | type: 2} 28 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!129 &1 4 | PlayerSettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 15 7 | productGUID: 7ae494ae49d7a0b44bb40661eca326e1 8 | AndroidProfiler: 0 9 | AndroidFilterTouchesWhenObscured: 0 10 | AndroidEnableSustainedPerformanceMode: 0 11 | defaultScreenOrientation: 4 12 | targetDevice: 2 13 | useOnDemandResources: 0 14 | accelerometerFrequency: 60 15 | companyName: DefaultCompany 16 | productName: Buckets AI 17 | defaultCursor: {fileID: 0} 18 | cursorHotspot: {x: 0, y: 0} 19 | m_SplashScreenBackgroundColor: {r: 0.13725491, g: 0.12156863, b: 0.1254902, a: 1} 20 | m_ShowUnitySplashScreen: 1 21 | m_ShowUnitySplashLogo: 1 22 | m_SplashScreenOverlayOpacity: 1 23 | m_SplashScreenAnimation: 1 24 | m_SplashScreenLogoStyle: 1 25 | m_SplashScreenDrawMode: 0 26 | m_SplashScreenBackgroundAnimationZoom: 1 27 | m_SplashScreenLogoAnimationZoom: 1 28 | m_SplashScreenBackgroundLandscapeAspect: 1 29 | m_SplashScreenBackgroundPortraitAspect: 1 30 | m_SplashScreenBackgroundLandscapeUvs: 31 | serializedVersion: 2 32 | x: 0 33 | y: 0 34 | width: 1 35 | height: 1 36 | m_SplashScreenBackgroundPortraitUvs: 37 | serializedVersion: 2 38 | x: 0 39 | y: 0 40 | width: 1 41 | height: 1 42 | m_SplashScreenLogos: [] 43 | m_VirtualRealitySplashScreen: {fileID: 0} 44 | m_HolographicTrackingLossScreen: {fileID: 0} 45 | defaultScreenWidth: 1024 46 | defaultScreenHeight: 768 47 | defaultScreenWidthWeb: 960 48 | defaultScreenHeightWeb: 600 49 | m_StereoRenderingPath: 0 50 | m_ActiveColorSpace: 0 51 | m_MTRendering: 1 52 | m_StackTraceTypes: 010000000100000001000000010000000100000001000000 53 | iosShowActivityIndicatorOnLoading: -1 54 | androidShowActivityIndicatorOnLoading: -1 55 | tizenShowActivityIndicatorOnLoading: -1 56 | iosAppInBackgroundBehavior: 0 57 | displayResolutionDialog: 1 58 | iosAllowHTTPDownload: 1 59 | allowedAutorotateToPortrait: 1 60 | allowedAutorotateToPortraitUpsideDown: 1 61 | allowedAutorotateToLandscapeRight: 1 62 | allowedAutorotateToLandscapeLeft: 1 63 | useOSAutorotation: 1 64 | use32BitDisplayBuffer: 1 65 | preserveFramebufferAlpha: 0 66 | disableDepthAndStencilBuffers: 0 67 | androidBlitType: 0 68 | defaultIsNativeResolution: 1 69 | macRetinaSupport: 1 70 | runInBackground: 1 71 | captureSingleScreen: 0 72 | muteOtherAudioSources: 0 73 | Prepare IOS For Recording: 0 74 | Force IOS Speakers When Recording: 0 75 | deferSystemGesturesMode: 0 76 | hideHomeButton: 0 77 | submitAnalytics: 1 78 | usePlayerLog: 1 79 | bakeCollisionMeshes: 0 80 | forceSingleInstance: 0 81 | resizableWindow: 0 82 | useMacAppStoreValidation: 0 83 | macAppStoreCategory: public.app-category.games 84 | gpuSkinning: 1 85 | graphicsJobs: 0 86 | xboxPIXTextureCapture: 0 87 | xboxEnableAvatar: 0 88 | xboxEnableKinect: 0 89 | xboxEnableKinectAutoTracking: 0 90 | xboxEnableFitness: 0 91 | visibleInBackground: 1 92 | allowFullscreenSwitch: 1 93 | graphicsJobMode: 0 94 | fullscreenMode: 1 95 | xboxSpeechDB: 0 96 | xboxEnableHeadOrientation: 0 97 | xboxEnableGuest: 0 98 | xboxEnablePIXSampling: 0 99 | metalFramebufferOnly: 0 100 | n3dsDisableStereoscopicView: 0 101 | n3dsEnableSharedListOpt: 1 102 | n3dsEnableVSync: 0 103 | xboxOneResolution: 0 104 | xboxOneSResolution: 0 105 | xboxOneXResolution: 3 106 | xboxOneMonoLoggingLevel: 0 107 | xboxOneLoggingLevel: 1 108 | xboxOneDisableEsram: 0 109 | xboxOnePresentImmediateThreshold: 0 110 | switchQueueCommandMemory: 0 111 | videoMemoryForVertexBuffers: 0 112 | psp2PowerMode: 0 113 | psp2AcquireBGM: 1 114 | m_SupportedAspectRatios: 115 | 4:3: 1 116 | 5:4: 1 117 | 16:10: 1 118 | 16:9: 1 119 | Others: 1 120 | bundleVersion: 0.1 121 | preloadedAssets: [] 122 | metroInputSource: 0 123 | wsaTransparentSwapchain: 0 124 | m_HolographicPauseOnTrackingLoss: 1 125 | xboxOneDisableKinectGpuReservation: 0 126 | xboxOneEnable7thCore: 0 127 | vrSettings: 128 | cardboard: 129 | depthFormat: 0 130 | enableTransitionView: 0 131 | daydream: 132 | depthFormat: 0 133 | useSustainedPerformanceMode: 0 134 | enableVideoLayer: 0 135 | useProtectedVideoMemory: 0 136 | minimumSupportedHeadTracking: 0 137 | maximumSupportedHeadTracking: 1 138 | hololens: 139 | depthFormat: 1 140 | depthBufferSharingEnabled: 0 141 | enable360StereoCapture: 0 142 | oculus: 143 | sharedDepthBuffer: 0 144 | dashSupport: 0 145 | protectGraphicsMemory: 0 146 | useHDRDisplay: 0 147 | m_ColorGamuts: 00000000 148 | targetPixelDensity: 30 149 | resolutionScalingMode: 0 150 | androidSupportedAspectRatio: 1 151 | androidMaxAspectRatio: 2.1 152 | applicationIdentifier: {} 153 | buildNumber: {} 154 | AndroidBundleVersionCode: 1 155 | AndroidMinSdkVersion: 16 156 | AndroidTargetSdkVersion: 0 157 | AndroidPreferredInstallLocation: 1 158 | aotOptions: 159 | stripEngineCode: 1 160 | iPhoneStrippingLevel: 0 161 | iPhoneScriptCallOptimization: 0 162 | ForceInternetPermission: 0 163 | ForceSDCardPermission: 0 164 | CreateWallpaper: 0 165 | APKExpansionFiles: 0 166 | keepLoadedShadersAlive: 0 167 | StripUnusedMeshComponents: 1 168 | VertexChannelCompressionMask: 4054 169 | iPhoneSdkVersion: 988 170 | iOSTargetOSVersionString: 8.0 171 | tvOSSdkVersion: 0 172 | tvOSRequireExtendedGameController: 0 173 | tvOSTargetOSVersionString: 9.0 174 | uIPrerenderedIcon: 0 175 | uIRequiresPersistentWiFi: 0 176 | uIRequiresFullScreen: 1 177 | uIStatusBarHidden: 1 178 | uIExitOnSuspend: 0 179 | uIStatusBarStyle: 0 180 | iPhoneSplashScreen: {fileID: 0} 181 | iPhoneHighResSplashScreen: {fileID: 0} 182 | iPhoneTallHighResSplashScreen: {fileID: 0} 183 | iPhone47inSplashScreen: {fileID: 0} 184 | iPhone55inPortraitSplashScreen: {fileID: 0} 185 | iPhone55inLandscapeSplashScreen: {fileID: 0} 186 | iPhone58inPortraitSplashScreen: {fileID: 0} 187 | iPhone58inLandscapeSplashScreen: {fileID: 0} 188 | iPadPortraitSplashScreen: {fileID: 0} 189 | iPadHighResPortraitSplashScreen: {fileID: 0} 190 | iPadLandscapeSplashScreen: {fileID: 0} 191 | iPadHighResLandscapeSplashScreen: {fileID: 0} 192 | appleTVSplashScreen: {fileID: 0} 193 | appleTVSplashScreen2x: {fileID: 0} 194 | tvOSSmallIconLayers: [] 195 | tvOSSmallIconLayers2x: [] 196 | tvOSLargeIconLayers: [] 197 | tvOSLargeIconLayers2x: [] 198 | tvOSTopShelfImageLayers: [] 199 | tvOSTopShelfImageLayers2x: [] 200 | tvOSTopShelfImageWideLayers: [] 201 | tvOSTopShelfImageWideLayers2x: [] 202 | iOSLaunchScreenType: 0 203 | iOSLaunchScreenPortrait: {fileID: 0} 204 | iOSLaunchScreenLandscape: {fileID: 0} 205 | iOSLaunchScreenBackgroundColor: 206 | serializedVersion: 2 207 | rgba: 0 208 | iOSLaunchScreenFillPct: 100 209 | iOSLaunchScreenSize: 100 210 | iOSLaunchScreenCustomXibPath: 211 | iOSLaunchScreeniPadType: 0 212 | iOSLaunchScreeniPadImage: {fileID: 0} 213 | iOSLaunchScreeniPadBackgroundColor: 214 | serializedVersion: 2 215 | rgba: 0 216 | iOSLaunchScreeniPadFillPct: 100 217 | iOSLaunchScreeniPadSize: 100 218 | iOSLaunchScreeniPadCustomXibPath: 219 | iOSUseLaunchScreenStoryboard: 0 220 | iOSLaunchScreenCustomStoryboardPath: 221 | iOSDeviceRequirements: [] 222 | iOSURLSchemes: [] 223 | iOSBackgroundModes: 0 224 | iOSMetalForceHardShadows: 0 225 | metalEditorSupport: 1 226 | metalAPIValidation: 1 227 | iOSRenderExtraFrameOnPause: 0 228 | appleDeveloperTeamID: 229 | iOSManualSigningProvisioningProfileID: 230 | tvOSManualSigningProvisioningProfileID: 231 | iOSManualSigningProvisioningProfileType: 0 232 | tvOSManualSigningProvisioningProfileType: 0 233 | appleEnableAutomaticSigning: 0 234 | iOSRequireARKit: 0 235 | appleEnableProMotion: 0 236 | clonedFromGUID: 56e7a2d3a00f33d44bdd161b773c35b5 237 | templatePackageId: com.unity.template.3d@1.0.0 238 | templateDefaultScene: Assets/Scenes/SampleScene.unity 239 | AndroidTargetArchitectures: 5 240 | AndroidSplashScreenScale: 0 241 | androidSplashScreen: {fileID: 0} 242 | AndroidKeystoreName: 243 | AndroidKeyaliasName: 244 | AndroidTVCompatibility: 1 245 | AndroidIsGame: 1 246 | AndroidEnableTango: 0 247 | androidEnableBanner: 1 248 | androidUseLowAccuracyLocation: 0 249 | m_AndroidBanners: 250 | - width: 320 251 | height: 180 252 | banner: {fileID: 0} 253 | androidGamepadSupportLevel: 0 254 | resolutionDialogBanner: {fileID: 0} 255 | m_BuildTargetIcons: [] 256 | m_BuildTargetPlatformIcons: [] 257 | m_BuildTargetBatching: 258 | - m_BuildTarget: Standalone 259 | m_StaticBatching: 1 260 | m_DynamicBatching: 0 261 | - m_BuildTarget: tvOS 262 | m_StaticBatching: 1 263 | m_DynamicBatching: 0 264 | - m_BuildTarget: Android 265 | m_StaticBatching: 1 266 | m_DynamicBatching: 0 267 | - m_BuildTarget: iPhone 268 | m_StaticBatching: 1 269 | m_DynamicBatching: 0 270 | - m_BuildTarget: WebGL 271 | m_StaticBatching: 0 272 | m_DynamicBatching: 0 273 | m_BuildTargetGraphicsAPIs: 274 | - m_BuildTarget: AndroidPlayer 275 | m_APIs: 0b00000015000000 276 | m_Automatic: 1 277 | - m_BuildTarget: iOSSupport 278 | m_APIs: 10000000 279 | m_Automatic: 1 280 | - m_BuildTarget: AppleTVSupport 281 | m_APIs: 10000000 282 | m_Automatic: 0 283 | - m_BuildTarget: WebGLSupport 284 | m_APIs: 0b000000 285 | m_Automatic: 1 286 | m_BuildTargetVRSettings: 287 | - m_BuildTarget: Standalone 288 | m_Enabled: 0 289 | m_Devices: 290 | - Oculus 291 | - OpenVR 292 | m_BuildTargetEnableVuforiaSettings: [] 293 | openGLRequireES31: 0 294 | openGLRequireES31AEP: 0 295 | m_TemplateCustomTags: {} 296 | mobileMTRendering: 297 | Android: 1 298 | iPhone: 1 299 | tvOS: 1 300 | m_BuildTargetGroupLightmapEncodingQuality: [] 301 | playModeTestRunnerEnabled: 0 302 | runPlayModeTestAsEditModeTest: 0 303 | actionOnDotNetUnhandledException: 1 304 | enableInternalProfiler: 0 305 | logObjCUncaughtExceptions: 1 306 | enableCrashReportAPI: 0 307 | cameraUsageDescription: 308 | locationUsageDescription: 309 | microphoneUsageDescription: 310 | switchNetLibKey: 311 | switchSocketMemoryPoolSize: 6144 312 | switchSocketAllocatorPoolSize: 128 313 | switchSocketConcurrencyLimit: 14 314 | switchScreenResolutionBehavior: 2 315 | switchUseCPUProfiler: 0 316 | switchApplicationID: 0x01004b9000490000 317 | switchNSODependencies: 318 | switchTitleNames_0: 319 | switchTitleNames_1: 320 | switchTitleNames_2: 321 | switchTitleNames_3: 322 | switchTitleNames_4: 323 | switchTitleNames_5: 324 | switchTitleNames_6: 325 | switchTitleNames_7: 326 | switchTitleNames_8: 327 | switchTitleNames_9: 328 | switchTitleNames_10: 329 | switchTitleNames_11: 330 | switchTitleNames_12: 331 | switchTitleNames_13: 332 | switchTitleNames_14: 333 | switchPublisherNames_0: 334 | switchPublisherNames_1: 335 | switchPublisherNames_2: 336 | switchPublisherNames_3: 337 | switchPublisherNames_4: 338 | switchPublisherNames_5: 339 | switchPublisherNames_6: 340 | switchPublisherNames_7: 341 | switchPublisherNames_8: 342 | switchPublisherNames_9: 343 | switchPublisherNames_10: 344 | switchPublisherNames_11: 345 | switchPublisherNames_12: 346 | switchPublisherNames_13: 347 | switchPublisherNames_14: 348 | switchIcons_0: {fileID: 0} 349 | switchIcons_1: {fileID: 0} 350 | switchIcons_2: {fileID: 0} 351 | switchIcons_3: {fileID: 0} 352 | switchIcons_4: {fileID: 0} 353 | switchIcons_5: {fileID: 0} 354 | switchIcons_6: {fileID: 0} 355 | switchIcons_7: {fileID: 0} 356 | switchIcons_8: {fileID: 0} 357 | switchIcons_9: {fileID: 0} 358 | switchIcons_10: {fileID: 0} 359 | switchIcons_11: {fileID: 0} 360 | switchIcons_12: {fileID: 0} 361 | switchIcons_13: {fileID: 0} 362 | switchIcons_14: {fileID: 0} 363 | switchSmallIcons_0: {fileID: 0} 364 | switchSmallIcons_1: {fileID: 0} 365 | switchSmallIcons_2: {fileID: 0} 366 | switchSmallIcons_3: {fileID: 0} 367 | switchSmallIcons_4: {fileID: 0} 368 | switchSmallIcons_5: {fileID: 0} 369 | switchSmallIcons_6: {fileID: 0} 370 | switchSmallIcons_7: {fileID: 0} 371 | switchSmallIcons_8: {fileID: 0} 372 | switchSmallIcons_9: {fileID: 0} 373 | switchSmallIcons_10: {fileID: 0} 374 | switchSmallIcons_11: {fileID: 0} 375 | switchSmallIcons_12: {fileID: 0} 376 | switchSmallIcons_13: {fileID: 0} 377 | switchSmallIcons_14: {fileID: 0} 378 | switchManualHTML: 379 | switchAccessibleURLs: 380 | switchLegalInformation: 381 | switchMainThreadStackSize: 1048576 382 | switchPresenceGroupId: 383 | switchLogoHandling: 0 384 | switchReleaseVersion: 0 385 | switchDisplayVersion: 1.0.0 386 | switchStartupUserAccount: 0 387 | switchTouchScreenUsage: 0 388 | switchSupportedLanguagesMask: 0 389 | switchLogoType: 0 390 | switchApplicationErrorCodeCategory: 391 | switchUserAccountSaveDataSize: 0 392 | switchUserAccountSaveDataJournalSize: 0 393 | switchApplicationAttribute: 0 394 | switchCardSpecSize: -1 395 | switchCardSpecClock: -1 396 | switchRatingsMask: 0 397 | switchRatingsInt_0: 0 398 | switchRatingsInt_1: 0 399 | switchRatingsInt_2: 0 400 | switchRatingsInt_3: 0 401 | switchRatingsInt_4: 0 402 | switchRatingsInt_5: 0 403 | switchRatingsInt_6: 0 404 | switchRatingsInt_7: 0 405 | switchRatingsInt_8: 0 406 | switchRatingsInt_9: 0 407 | switchRatingsInt_10: 0 408 | switchRatingsInt_11: 0 409 | switchLocalCommunicationIds_0: 410 | switchLocalCommunicationIds_1: 411 | switchLocalCommunicationIds_2: 412 | switchLocalCommunicationIds_3: 413 | switchLocalCommunicationIds_4: 414 | switchLocalCommunicationIds_5: 415 | switchLocalCommunicationIds_6: 416 | switchLocalCommunicationIds_7: 417 | switchParentalControl: 0 418 | switchAllowsScreenshot: 1 419 | switchAllowsVideoCapturing: 1 420 | switchAllowsRuntimeAddOnContentInstall: 0 421 | switchDataLossConfirmation: 0 422 | switchSupportedNpadStyles: 3 423 | switchSocketConfigEnabled: 0 424 | switchTcpInitialSendBufferSize: 32 425 | switchTcpInitialReceiveBufferSize: 64 426 | switchTcpAutoSendBufferSizeMax: 256 427 | switchTcpAutoReceiveBufferSizeMax: 256 428 | switchUdpSendBufferSize: 9 429 | switchUdpReceiveBufferSize: 42 430 | switchSocketBufferEfficiency: 4 431 | switchSocketInitializeEnabled: 1 432 | switchNetworkInterfaceManagerInitializeEnabled: 1 433 | switchPlayerConnectionEnabled: 1 434 | ps4NPAgeRating: 12 435 | ps4NPTitleSecret: 436 | ps4NPTrophyPackPath: 437 | ps4ParentalLevel: 11 438 | ps4ContentID: ED1633-NPXX51362_00-0000000000000000 439 | ps4Category: 0 440 | ps4MasterVersion: 01.00 441 | ps4AppVersion: 01.00 442 | ps4AppType: 0 443 | ps4ParamSfxPath: 444 | ps4VideoOutPixelFormat: 0 445 | ps4VideoOutInitialWidth: 1920 446 | ps4VideoOutBaseModeInitialWidth: 1920 447 | ps4VideoOutReprojectionRate: 60 448 | ps4PronunciationXMLPath: 449 | ps4PronunciationSIGPath: 450 | ps4BackgroundImagePath: 451 | ps4StartupImagePath: 452 | ps4StartupImagesFolder: 453 | ps4IconImagesFolder: 454 | ps4SaveDataImagePath: 455 | ps4SdkOverride: 456 | ps4BGMPath: 457 | ps4ShareFilePath: 458 | ps4ShareOverlayImagePath: 459 | ps4PrivacyGuardImagePath: 460 | ps4NPtitleDatPath: 461 | ps4RemotePlayKeyAssignment: -1 462 | ps4RemotePlayKeyMappingDir: 463 | ps4PlayTogetherPlayerCount: 0 464 | ps4EnterButtonAssignment: 1 465 | ps4ApplicationParam1: 0 466 | ps4ApplicationParam2: 0 467 | ps4ApplicationParam3: 0 468 | ps4ApplicationParam4: 0 469 | ps4DownloadDataSize: 0 470 | ps4GarlicHeapSize: 2048 471 | ps4ProGarlicHeapSize: 2560 472 | ps4Passcode: frAQBc8Wsa1xVPfvJcrgRYwTiizs2trQ 473 | ps4pnSessions: 1 474 | ps4pnPresence: 1 475 | ps4pnFriends: 1 476 | ps4pnGameCustomData: 1 477 | playerPrefsSupport: 0 478 | enableApplicationExit: 0 479 | restrictedAudioUsageRights: 0 480 | ps4UseResolutionFallback: 0 481 | ps4ReprojectionSupport: 0 482 | ps4UseAudio3dBackend: 0 483 | ps4SocialScreenEnabled: 0 484 | ps4ScriptOptimizationLevel: 0 485 | ps4Audio3dVirtualSpeakerCount: 14 486 | ps4attribCpuUsage: 0 487 | ps4PatchPkgPath: 488 | ps4PatchLatestPkgPath: 489 | ps4PatchChangeinfoPath: 490 | ps4PatchDayOne: 0 491 | ps4attribUserManagement: 0 492 | ps4attribMoveSupport: 0 493 | ps4attrib3DSupport: 0 494 | ps4attribShareSupport: 0 495 | ps4attribExclusiveVR: 0 496 | ps4disableAutoHideSplash: 0 497 | ps4videoRecordingFeaturesUsed: 0 498 | ps4contentSearchFeaturesUsed: 0 499 | ps4attribEyeToEyeDistanceSettingVR: 0 500 | ps4IncludedModules: [] 501 | monoEnv: 502 | psp2Splashimage: {fileID: 0} 503 | psp2NPTrophyPackPath: 504 | psp2NPSupportGBMorGJP: 0 505 | psp2NPAgeRating: 12 506 | psp2NPTitleDatPath: 507 | psp2NPCommsID: 508 | psp2NPCommunicationsID: 509 | psp2NPCommsPassphrase: 510 | psp2NPCommsSig: 511 | psp2ParamSfxPath: 512 | psp2ManualPath: 513 | psp2LiveAreaGatePath: 514 | psp2LiveAreaBackroundPath: 515 | psp2LiveAreaPath: 516 | psp2LiveAreaTrialPath: 517 | psp2PatchChangeInfoPath: 518 | psp2PatchOriginalPackage: 519 | psp2PackagePassword: F69AzBlax3CF3EDNhm3soLBPh71Yexui 520 | psp2KeystoneFile: 521 | psp2MemoryExpansionMode: 0 522 | psp2DRMType: 0 523 | psp2StorageType: 0 524 | psp2MediaCapacity: 0 525 | psp2DLCConfigPath: 526 | psp2ThumbnailPath: 527 | psp2BackgroundPath: 528 | psp2SoundPath: 529 | psp2TrophyCommId: 530 | psp2TrophyPackagePath: 531 | psp2PackagedResourcesPath: 532 | psp2SaveDataQuota: 10240 533 | psp2ParentalLevel: 1 534 | psp2ShortTitle: Not Set 535 | psp2ContentID: IV0000-ABCD12345_00-0123456789ABCDEF 536 | psp2Category: 0 537 | psp2MasterVersion: 01.00 538 | psp2AppVersion: 01.00 539 | psp2TVBootMode: 0 540 | psp2EnterButtonAssignment: 2 541 | psp2TVDisableEmu: 0 542 | psp2AllowTwitterDialog: 1 543 | psp2Upgradable: 0 544 | psp2HealthWarning: 0 545 | psp2UseLibLocation: 0 546 | psp2InfoBarOnStartup: 0 547 | psp2InfoBarColor: 0 548 | psp2ScriptOptimizationLevel: 0 549 | splashScreenBackgroundSourceLandscape: {fileID: 0} 550 | splashScreenBackgroundSourcePortrait: {fileID: 0} 551 | spritePackerPolicy: 552 | webGLMemorySize: 256 553 | webGLExceptionSupport: 1 554 | webGLNameFilesAsHashes: 0 555 | webGLDataCaching: 0 556 | webGLDebugSymbols: 0 557 | webGLEmscriptenArgs: 558 | webGLModulesDirectory: 559 | webGLTemplate: APPLICATION:Default 560 | webGLAnalyzeBuildSize: 0 561 | webGLUseEmbeddedResources: 0 562 | webGLCompressionFormat: 1 563 | webGLLinkerTarget: 0 564 | scriptingDefineSymbols: 565 | 1: UNITY_POST_PROCESSING_STACK_V2 566 | 4: UNITY_POST_PROCESSING_STACK_V2 567 | 7: UNITY_POST_PROCESSING_STACK_V2 568 | 13: UNITY_POST_PROCESSING_STACK_V2 569 | 17: UNITY_POST_PROCESSING_STACK_V2 570 | 18: UNITY_POST_PROCESSING_STACK_V2 571 | 19: UNITY_POST_PROCESSING_STACK_V2 572 | 21: UNITY_POST_PROCESSING_STACK_V2 573 | 23: UNITY_POST_PROCESSING_STACK_V2 574 | 24: UNITY_POST_PROCESSING_STACK_V2 575 | 25: UNITY_POST_PROCESSING_STACK_V2 576 | 26: UNITY_POST_PROCESSING_STACK_V2 577 | 27: UNITY_POST_PROCESSING_STACK_V2 578 | platformArchitecture: {} 579 | scriptingBackend: {} 580 | il2cppCompilerConfiguration: {} 581 | incrementalIl2cppBuild: {} 582 | allowUnsafeCode: 1 583 | additionalIl2CppArgs: 584 | scriptingRuntimeVersion: 1 585 | apiCompatibilityLevelPerPlatform: 586 | Standalone: 1 587 | m_RenderingPath: 1 588 | m_MobileRenderingPath: 1 589 | metroPackageName: Template_3D 590 | metroPackageVersion: 591 | metroCertificatePath: 592 | metroCertificatePassword: 593 | metroCertificateSubject: 594 | metroCertificateIssuer: 595 | metroCertificateNotAfter: 0000000000000000 596 | metroApplicationDescription: Template_3D 597 | wsaImages: {} 598 | metroTileShortName: 599 | metroCommandLineArgsFile: 600 | metroTileShowName: 0 601 | metroMediumTileShowName: 0 602 | metroLargeTileShowName: 0 603 | metroWideTileShowName: 0 604 | metroDefaultTileSize: 1 605 | metroTileForegroundText: 2 606 | metroTileBackgroundColor: {r: 0.13333334, g: 0.17254902, b: 0.21568628, a: 0} 607 | metroSplashScreenBackgroundColor: {r: 0.12941177, g: 0.17254902, b: 0.21568628, 608 | a: 1} 609 | metroSplashScreenUseBackgroundColor: 0 610 | platformCapabilities: {} 611 | metroFTAName: 612 | metroFTAFileTypes: [] 613 | metroProtocolName: 614 | metroCompilationOverrides: 1 615 | tizenProductDescription: 616 | tizenProductURL: 617 | tizenSigningProfileName: 618 | tizenGPSPermissions: 0 619 | tizenMicrophonePermissions: 0 620 | tizenDeploymentTarget: 621 | tizenDeploymentTargetType: -1 622 | tizenMinOSVersion: 1 623 | n3dsUseExtSaveData: 0 624 | n3dsCompressStaticMem: 1 625 | n3dsExtSaveDataNumber: 0x12345 626 | n3dsStackSize: 131072 627 | n3dsTargetPlatform: 2 628 | n3dsRegion: 7 629 | n3dsMediaSize: 0 630 | n3dsLogoStyle: 3 631 | n3dsTitle: GameName 632 | n3dsProductCode: 633 | n3dsApplicationId: 0xFF3FF 634 | XboxOneProductId: 635 | XboxOneUpdateKey: 636 | XboxOneSandboxId: 637 | XboxOneContentId: 638 | XboxOneTitleId: 639 | XboxOneSCId: 640 | XboxOneGameOsOverridePath: 641 | XboxOnePackagingOverridePath: 642 | XboxOneAppManifestOverridePath: 643 | XboxOnePackageEncryption: 0 644 | XboxOnePackageUpdateGranularity: 2 645 | XboxOneDescription: 646 | XboxOneLanguage: 647 | - enus 648 | XboxOneCapability: [] 649 | XboxOneGameRating: {} 650 | XboxOneIsContentPackage: 0 651 | XboxOneEnableGPUVariability: 0 652 | XboxOneSockets: {} 653 | XboxOneSplashScreen: {fileID: 0} 654 | XboxOneAllowedProductIds: [] 655 | XboxOnePersistentLocalStorageSize: 0 656 | XboxOneXTitleMemory: 8 657 | xboxOneScriptCompiler: 0 658 | vrEditorSettings: 659 | daydream: 660 | daydreamIconForeground: {fileID: 0} 661 | daydreamIconBackground: {fileID: 0} 662 | cloudServicesEnabled: 663 | Collab: 1 664 | UNet: 1 665 | facebookSdkVersion: 7.9.4 666 | apiCompatibilityLevel: 2 667 | cloudProjectId: db2e33cc-849c-4d1a-95ce-77620e527424 668 | projectName: Buckets AI 669 | organizationId: ot-interactive 670 | cloudEnabled: 0 671 | enableNativePlatformBackendsForNewInputSystem: 0 672 | disableOldInputManagerSupport: 0 673 | -------------------------------------------------------------------------------- /ProjectSettings/ProjectVersion.txt: -------------------------------------------------------------------------------- 1 | m_EditorVersion: 2018.1.0f2 2 | -------------------------------------------------------------------------------- /ProjectSettings/QualitySettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!47 &1 4 | QualitySettings: 5 | m_ObjectHideFlags: 0 6 | serializedVersion: 5 7 | m_CurrentQuality: 4 8 | m_QualitySettings: 9 | - serializedVersion: 2 10 | name: Very Low 11 | pixelLightCount: 0 12 | shadows: 0 13 | shadowResolution: 0 14 | shadowProjection: 1 15 | shadowCascades: 1 16 | shadowDistance: 15 17 | shadowNearPlaneOffset: 3 18 | shadowCascade2Split: 0.33333334 19 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 20 | shadowmaskMode: 0 21 | blendWeights: 1 22 | textureQuality: 1 23 | anisotropicTextures: 0 24 | antiAliasing: 0 25 | softParticles: 0 26 | softVegetation: 0 27 | realtimeReflectionProbes: 0 28 | billboardsFaceCameraPosition: 0 29 | vSyncCount: 0 30 | lodBias: 0.3 31 | maximumLODLevel: 0 32 | particleRaycastBudget: 4 33 | asyncUploadTimeSlice: 2 34 | asyncUploadBufferSize: 4 35 | resolutionScalingFixedDPIFactor: 1 36 | excludedTargetPlatforms: [] 37 | - serializedVersion: 2 38 | name: Low 39 | pixelLightCount: 0 40 | shadows: 0 41 | shadowResolution: 0 42 | shadowProjection: 1 43 | shadowCascades: 1 44 | shadowDistance: 20 45 | shadowNearPlaneOffset: 3 46 | shadowCascade2Split: 0.33333334 47 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 48 | shadowmaskMode: 0 49 | blendWeights: 2 50 | textureQuality: 0 51 | anisotropicTextures: 0 52 | antiAliasing: 0 53 | softParticles: 0 54 | softVegetation: 0 55 | realtimeReflectionProbes: 0 56 | billboardsFaceCameraPosition: 0 57 | vSyncCount: 0 58 | lodBias: 0.4 59 | maximumLODLevel: 0 60 | particleRaycastBudget: 16 61 | asyncUploadTimeSlice: 2 62 | asyncUploadBufferSize: 4 63 | resolutionScalingFixedDPIFactor: 1 64 | excludedTargetPlatforms: [] 65 | - serializedVersion: 2 66 | name: Medium 67 | pixelLightCount: 1 68 | shadows: 1 69 | shadowResolution: 0 70 | shadowProjection: 1 71 | shadowCascades: 1 72 | shadowDistance: 20 73 | shadowNearPlaneOffset: 3 74 | shadowCascade2Split: 0.33333334 75 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 76 | shadowmaskMode: 0 77 | blendWeights: 2 78 | textureQuality: 0 79 | anisotropicTextures: 1 80 | antiAliasing: 0 81 | softParticles: 0 82 | softVegetation: 0 83 | realtimeReflectionProbes: 0 84 | billboardsFaceCameraPosition: 0 85 | vSyncCount: 1 86 | lodBias: 0.7 87 | maximumLODLevel: 0 88 | particleRaycastBudget: 64 89 | asyncUploadTimeSlice: 2 90 | asyncUploadBufferSize: 4 91 | resolutionScalingFixedDPIFactor: 1 92 | excludedTargetPlatforms: [] 93 | - serializedVersion: 2 94 | name: High 95 | pixelLightCount: 2 96 | shadows: 2 97 | shadowResolution: 1 98 | shadowProjection: 1 99 | shadowCascades: 2 100 | shadowDistance: 40 101 | shadowNearPlaneOffset: 3 102 | shadowCascade2Split: 0.33333334 103 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 104 | shadowmaskMode: 1 105 | blendWeights: 2 106 | textureQuality: 0 107 | anisotropicTextures: 1 108 | antiAliasing: 2 109 | softParticles: 0 110 | softVegetation: 1 111 | realtimeReflectionProbes: 1 112 | billboardsFaceCameraPosition: 1 113 | vSyncCount: 1 114 | lodBias: 1 115 | maximumLODLevel: 0 116 | particleRaycastBudget: 256 117 | asyncUploadTimeSlice: 2 118 | asyncUploadBufferSize: 4 119 | resolutionScalingFixedDPIFactor: 1 120 | excludedTargetPlatforms: [] 121 | - serializedVersion: 2 122 | name: Very High 123 | pixelLightCount: 3 124 | shadows: 2 125 | shadowResolution: 2 126 | shadowProjection: 1 127 | shadowCascades: 2 128 | shadowDistance: 40 129 | shadowNearPlaneOffset: 3 130 | shadowCascade2Split: 0.33333334 131 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 132 | shadowmaskMode: 1 133 | blendWeights: 4 134 | textureQuality: 0 135 | anisotropicTextures: 1 136 | antiAliasing: 4 137 | softParticles: 1 138 | softVegetation: 1 139 | realtimeReflectionProbes: 1 140 | billboardsFaceCameraPosition: 1 141 | vSyncCount: 0 142 | lodBias: 1.5 143 | maximumLODLevel: 0 144 | particleRaycastBudget: 1024 145 | asyncUploadTimeSlice: 2 146 | asyncUploadBufferSize: 4 147 | resolutionScalingFixedDPIFactor: 1 148 | excludedTargetPlatforms: [] 149 | - serializedVersion: 2 150 | name: Ultra 151 | pixelLightCount: 4 152 | shadows: 2 153 | shadowResolution: 2 154 | shadowProjection: 1 155 | shadowCascades: 4 156 | shadowDistance: 150 157 | shadowNearPlaneOffset: 3 158 | shadowCascade2Split: 0.33333334 159 | shadowCascade4Split: {x: 0.06666667, y: 0.2, z: 0.46666667} 160 | shadowmaskMode: 1 161 | blendWeights: 4 162 | textureQuality: 0 163 | anisotropicTextures: 1 164 | antiAliasing: 4 165 | softParticles: 1 166 | softVegetation: 1 167 | realtimeReflectionProbes: 1 168 | billboardsFaceCameraPosition: 1 169 | vSyncCount: 1 170 | lodBias: 2 171 | maximumLODLevel: 0 172 | particleRaycastBudget: 4096 173 | asyncUploadTimeSlice: 2 174 | asyncUploadBufferSize: 4 175 | resolutionScalingFixedDPIFactor: 1 176 | excludedTargetPlatforms: [] 177 | m_PerPlatformDefaultQuality: 178 | Android: 2 179 | Nintendo 3DS: 5 180 | Nintendo Switch: 5 181 | PS4: 5 182 | PSP2: 2 183 | Standalone: 5 184 | Tizen: 2 185 | WebGL: 3 186 | WiiU: 5 187 | Windows Store Apps: 5 188 | XboxOne: 5 189 | iPhone: 2 190 | tvOS: 2 191 | -------------------------------------------------------------------------------- /ProjectSettings/TagManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!78 &1 4 | TagManager: 5 | serializedVersion: 2 6 | tags: [] 7 | layers: 8 | - Default 9 | - TransparentFX 10 | - Ignore Raycast 11 | - 12 | - Water 13 | - UI 14 | - 15 | - 16 | - PostProcessing 17 | - 18 | - 19 | - 20 | - 21 | - 22 | - 23 | - 24 | - 25 | - 26 | - 27 | - 28 | - 29 | - 30 | - 31 | - 32 | - 33 | - 34 | - 35 | - 36 | - 37 | - 38 | - 39 | - 40 | m_SortingLayers: 41 | - name: Default 42 | uniqueID: 0 43 | locked: 0 44 | -------------------------------------------------------------------------------- /ProjectSettings/TimeManager.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!5 &1 4 | TimeManager: 5 | m_ObjectHideFlags: 0 6 | Fixed Timestep: 0.0167 7 | Maximum Allowed Timestep: 0.1 8 | m_TimeScale: 1 9 | Maximum Particle Timestep: 0.03 10 | -------------------------------------------------------------------------------- /ProjectSettings/UnityConnectSettings.asset: -------------------------------------------------------------------------------- 1 | %YAML 1.1 2 | %TAG !u! tag:unity3d.com,2011: 3 | --- !u!310 &1 4 | UnityConnectSettings: 5 | m_ObjectHideFlags: 0 6 | m_Enabled: 0 7 | m_TestMode: 0 8 | m_TestEventUrl: 9 | m_TestConfigUrl: 10 | m_TestInitMode: 0 11 | CrashReportingSettings: 12 | m_EventUrl: https://perf-events.cloud.unity3d.com/api/events/crashes 13 | m_NativeEventUrl: https://perf-events.cloud.unity3d.com/symbolicate 14 | m_Enabled: 0 15 | m_CaptureEditorExceptions: 1 16 | UnityPurchasingSettings: 17 | m_Enabled: 0 18 | m_TestMode: 0 19 | UnityAnalyticsSettings: 20 | m_Enabled: 1 21 | m_InitializeOnStartup: 1 22 | m_TestMode: 0 23 | m_TestEventUrl: 24 | m_TestConfigUrl: 25 | UnityAdsSettings: 26 | m_Enabled: 0 27 | m_InitializeOnStartup: 1 28 | m_TestMode: 0 29 | m_IosGameId: 30 | m_AndroidGameId: 31 | m_GameIds: {} 32 | m_GameId: 33 | PerformanceReportingSettings: 34 | m_Enabled: 0 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DynamicObjectTracking 2 | 3 | A multithreaded implementation of [Nition's Octree for Unity](https://github.com/Nition/UnityOctree) allowing for discriminatory 4 | object tracking with large numbers of moving GameObjects. 5 | 6 | Use of the point Octree system is comparable to using trigger colliders with hard coded switch or if else statements, however the objects tracked and 7 | the information receivers are easily selected at your discretion (no more sifting through enormous amounts of collider data). This 8 | is also a viable option for collision detection if you wish to escape PhysX (and spherical colliders can meet your needs). The primary benefit 9 | is getting optimized spatial calculations without interfering with anything you (or perhaps your users) are doing with trigger colliders. 10 | 11 | Any number of agents can track up to 701 classes / fields of objects (a thru zz), and *each field may contain any number of tracked objects*. 12 | Although 701 different fields of tracked objects is likely beyond any need - additional fields can be added at runtime (see public methods). 13 | 14 | Every field has its own distance threshold value defining when it registers other tracked objects. Once another tracked object registers, 15 | an event is published to the subscribers (typically an agent or a game manager) monitoring that object. The event publishes the registered 16 | GameObjects inside the threshold (GameObject[]) and their associated object field types (string[] "a","b","c"...). 17 | 18 | Additionally, this package can be configured to forego Octree implementation and simply automate Unity's Collider trigger configuration across your 19 | selected fields of tracked objects. Both the Octree and Trigger configurations produce the same discriminatory data - reported the same way - to 20 | monitoring agents. You can easily benchmark the two against each other. Choosing to have this system automate trigger configurations for you will 21 | obviously negate any benefits afforded by using the Octree implementation. 22 | 23 | 20k Tracked Objects - colliding *only* with objects with that are different in color - using *no colliders or rigidbodies.* 24 | 25 |
26 | 27 | The above scene uses a collision method that simply sets object direction to it's position minus the colliding objects position. Object scales are set to 28 | match their *threshold* size. This scene averaged 20 fps on a 15" Surfacebook. When scene sizes get this large, collision detection loses accuracy, 29 | but crucially - the main thread remains unblocked (unless you choose the Unity Trigger implementation). 30 | 31 | # Getting Started 32 | 33 | **The Empty WorldMonitors Component** 34 |
35 | 36 |
37 | 38 | To start tracking, add a WorldMonitors component as shown above. This component is added to every "tracker" - i.e. a GameObject that will track 39 | the movement of a selected group of GameObjects. The + button will open up the *Tracked Field*, where you can add tracked objects. Add at least 40 | one more *Tracked Field* (in any instance of WorldMonitors) where the tracked objects will raise conflict with objects in other *Tracked Fields*. 41 | 42 | Any number of WorldMonitors can be used. If multiple instances of WorldMonitors will be tracking the same object, that object must appear under 43 | the same field for every instance of WorldMonitors tracking it. See how PinkSphere (1) appears in the following (separate) instances of 44 | WorldMonitors - it is under "Set B" for each instance. The order of objects in Set B can be different for each WorldMonitors instance. Also note 45 | that the threshold sizes are the same for each field; this is enforced by the custom inspector code every time a value is changed so you won't 46 | need to check across all instances of WorldMonitors for continuity. 47 | 48 | **Multiple WorldMonitors Instances - Use Symmetrical Fields** 49 |
50 | 51 |
52 |
53 | 54 | **The WorldMonitor Component - Singleton** 55 |
56 | 57 |
58 | 59 | If you do not add this component it will be created for you, however you should make a sincere effort to set the parameters beforehand. 60 | Failing to do so can result in an unnecessarily large Octree which can consume resources. Place it on any GameObject you'd like. 61 | 62 | This system will *never* use more than one auxilliary thread. If you wish, you may restrict the object tracking to the main thread 63 | at the expense of performance. 64 | 65 | The exhaustive calculation is intended for benchmarking - however if you are using a very small number of tracked objects, exhaustive calculations 66 | may be faster for your use case. This method raises the conflict event every frame, as such it's functionality is similar to OnTriggerStay(). It 67 | is of no value if you choose to implement the system's automated Unity Trigger configuration. 68 | 69 | # Events 70 | 71 | *All events use the ObjectConflictHandler delegate* 72 | > delegate void ObjectConflictHandler(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes); 73 | 74 | * **GameObject objectWithConflict:** this is the object who's threshold has been crossed 75 | * **GameObject[] conflictingObjects:** an array of the objects who've crossed into the threshold 76 | * **string[] conflictingTypes:** an array of the object field names (e.g. "A", "B", "C" etc) 77 | 78 | It is possible for more than one object to cross thresholds during an Update cycle, as such the latter two arguments are arrays. 79 | 80 | > ConflictEnterers(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes) 81 | 82 | Subscribe to this event for notification every time a tracked object enters another's threshold. 83 | 84 | > ConflictLeavers(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes) 85 | > ConflictEnd(GameObject objectWithConflict, GameObject[] conflictingObjects, string[] conflictingTypes) 86 | 87 | These two events are mutually exclusive; subcribe to ConflictLeavers if you need an update every time an object leaves another's threshold area. 88 | ConflictEnd is only emitted when *all* tracked objects have vacated a threshold area. 89 | 90 | # Public Methods 91 | > void ChangeThresholdSize(float threshold, GameObject trackedObject, string objectType) 92 | 93 | * **float threshold** the new threshold size you wish to set. 94 | * **GameObject trackedObject** *(Optional)* the particular tracked object whos threshold you wish to change. 95 | * **string objectType** *(Optional)* the field name of the threshold you'd like to change 96 | 97 | *Remarks: you must include at least one of the optional arguments - - both options change the threshold size for an entire field, not individual objects. 98 | If you are using the trigger implementation, use the public ChangeTriggerSize() method instead.* 99 | 100 | > void InsertNewTrackedObject(GameObject trackedObject, WorldMonitors owner, string objectAffiliation, float threshold) 101 | 102 | * **GameObject trackedObject:** the object to be tracked. 103 | * **WorldMonitors owner:** the WorldMonitors component for the tracker tracking this object. 104 | * **string objectAffiliation** the type (field name) for this object. This can be anything -- here is where you can expand on the 701 field limit. 105 | * **float threshold:** the new threshold size you wish to set. 106 | 107 | *Remarks: see the example scenes for demonstration of usage.* 108 | 109 | > void RemoveTrackedObject(GameObject trackedObject, WorldMonitors whoToRemove, bool retainOtherTrackers) 110 | 111 | * **GameObject trackedObject:** the tracked object to be removed. 112 | * **WorldMonitors whoToRemove:** *(Optional)* you can remove individual trackers from tracked objects as they can be tracked by any number of agents 113 | * **bool retainOtherTrackers:** *(Optional)* set this argument true if you wish to remove only aspecified tracking agent. 114 | 115 | *Remarks: you should always remove the WorldMonitors owner when an agent is destroyed, or at the minimum unsubscribe from the events. see the example scenes for demonstration of usage.* 116 | 117 | **Tracker - an Example Object Tracker** 118 |
119 | 120 |
121 | 122 | You will find the Tracker class in the example scenes, which demonstrates how to use all of the public methods except for ChangeThresholdSize(). 123 | The last Tracking Agent in the heirarchy (in both scenes) is preconfigured to use some of the options. 124 | 125 | ## ** Scenes ** 126 | # TrackingExample 127 | 128 |
129 | TrackingExample demonstrates the system's large scale dynamic object tracking ability, and an example method is used to change the tracked object's 130 | trajectories when conflicts are incurred by one enabled object (you can enable this behavior in the Tracker inspector). This scene includes 131 | 500 initial tracked objects and inflates to 5,000 at runtime. All of these object's are configured to interact with thresholds beyond their size (like a trigger). 132 | On a SurfaceBook (i7, GTX 1060), this scene runs at 45 fps with the tracking system updating once 1-2 times per 10 frames (note the tracking refresh 133 | rate on smaller scenes is about once/ frame). 134 | 135 | # SmallTrackingExample 136 | 137 |
138 | This scene is preconfigured to log events to the console so you can quickly understand how and what data is published. 139 | 140 | # Important Points 141 | 142 | If you may be switching between the Octree and Trigger tracking methods, you should be aware of how the threshold and trigger radius differ. 143 | They are both a measure of the same thing (a spherical radius) however triggers emit collisions when the triggers cross each other's boundaries, 144 | not when the parent object crosses the boundary. **You can configure the WorldMonitor component to have triggers immitate the Octree behavior 145 | or visa-versa.** The difference between the two methods without configuring the WorldMonitor to immitate behaviors is shown below. 146 |
147 | 148 |
-------------------------------------------------------------------------------- /THIRD_PARTY_NOTICES.md: -------------------------------------------------------------------------------- 1 | OTI (Overtime Interactive) Dynamic Object Tracking uses third-party libraries or other resources that may 2 | be distributed under licenses different than the OTI software. 3 | The original copyright notice and the license at the time of incorporation of 4 | such third party material are set forth below. 5 | 6 | In the event that we accidentally failed to list a required notice, please 7 | bring it to our attention through opening a new issue on the GitHub repo here: 8 | 9 | https://github.com/phatboysh/DynamicObjectTracking/issues 10 | 11 | ------------------------------------------------------------------------------- 12 | 13 | UnityOctree 14 | https://github.com/Nition/UnityOctree 15 | 16 | This work is included in DynamicObjectTracking/Assets/UnityOctree 17 | 18 | and accessed from OTI files: 19 | DynamicObjectTracking/Assets/Octree/Octree.cs 20 | 21 | --- 22 | Copyright (c) 2014, Nition 23 | 24 | All rights reserved. 25 | 26 | 27 | 28 | Redistribution and use in source and binary forms, with or without 29 | modification, 30 | are permitted provided that the following conditions are met: 31 | 32 | 33 | 34 | * Redistributions of source code must retain the above copyright notice, this 35 | list of conditions and the following disclaimer. 36 | 37 | 38 | 39 | * Redistributions in binary form must reproduce the above copyright notice, 40 | this list of conditions and the following disclaimer 41 | in the documentation 42 | and/or other materials provided with the distribution. 43 | 44 | 45 | 46 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 47 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, 48 | BUT NOT LIMITED TO, THE 49 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 50 | DISCLAIMED. IN NO EVENT 51 | SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 52 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 53 | 54 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 55 | SERVICES; LOSS OF USE, DATA, OR PROFITS; 56 | OR BUSINESS INTERRUPTION) HOWEVER 57 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 58 | 59 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 60 | OF THIS SOFTWARE, EVEN IF ADVISED OF 61 | THE POSSIBILITY OF SUCH DAMAGE. 62 | 63 | ------------------------------------------------------------------------------- 64 | --------------------------------------------------------------------------------