├── Countdown.meta
├── Countdown
├── Countdown.cs
├── Countdown.cs.meta
├── CountdownProperty.cs
├── CountdownProperty.cs.meta
├── CountdownPropertyLoop.cs
├── CountdownPropertyLoop.cs.meta
├── CountdownPropertyOnce.cs
├── CountdownPropertyOnce.cs.meta
├── Editor.meta
├── Editor
│ ├── CountdownLoopPropertyDrawer.cs
│ ├── CountdownLoopPropertyDrawer.cs.meta
│ ├── CountdownOncePropertyDrawer.cs
│ ├── CountdownOncePropertyDrawer.cs.meta
│ ├── CountdownPropertyDrawerBase.cs
│ └── CountdownPropertyDrawerBase.cs.meta
├── README.md
└── README.md.meta
├── Doxyfile.dox
├── Doxyfile.dox.meta
├── EditorHelper.meta
├── EditorHelper
├── Editor.meta
├── Editor
│ ├── EditorHelper.cs
│ └── EditorHelper.cs.meta
├── README.md
└── README.md.meta
├── Examples.meta
├── Examples
├── CountdownExample.cs
├── CountdownExample.cs.meta
├── CountdownPropertyExample.cs
├── CountdownPropertyExample.cs.meta
├── LINQExtensionsExamples.cs
├── LINQExtensionsExamples.cs.meta
├── MathHelperExamples.cs
├── MathHelperExamples.cs.meta
├── MeshCreatorExample.cs
├── MeshCreatorExample.cs.meta
├── NoiseOutputValueExample.cs
├── NoiseOutputValueExample.cs.meta
├── RandomBagExample.cs
├── RandomBagExample.cs.meta
├── RangeExample.cs
├── RangeExample.cs.meta
├── RollingArrayExample.cs
├── RollingArrayExample.cs.meta
├── SingletonEntityManager.cs
├── SingletonEntityManager.cs.meta
├── SingletonMusicManager.cs
├── SingletonMusicManager.cs.meta
├── UnityHelperExamples.cs
├── UnityHelperExamples.cs.meta
├── XmlHelperExample.cs
└── XmlHelperExample.cs.meta
├── LICENSE
├── LICENSE.meta
├── LINQExtensions.meta
├── LINQExtensions
├── LINQExtensions.cs
├── LINQExtensions.cs.meta
├── README.md
└── README.md.meta
├── MathHelper.meta
├── MathHelper
├── MathHelper.cs
├── MathHelper.cs.meta
├── README.md
└── README.md.meta
├── MeshCreator.meta
├── MeshCreator
├── MeshCreator.cs
├── MeshCreator.cs.meta
├── MeshTriangle.cs
├── MeshTriangle.cs.meta
├── MeshVertex.cs
├── MeshVertex.cs.meta
├── README.md
└── README.md.meta
├── NoiseOutputValue.meta
├── NoiseOutputValue
├── NoiseOutputValue.cs
├── NoiseOutputValue.cs.meta
├── README.md
└── README.md.meta
├── README.md
├── README.md.meta
├── RandomBag.meta
├── RandomBag
├── README.md
├── README.md.meta
├── RandomBag.cs
└── RandomBag.cs.meta
├── Range.meta
├── Range
├── Editor.meta
├── Editor
│ ├── RangeFloatPropertyDrawer.cs
│ ├── RangeFloatPropertyDrawer.cs.meta
│ ├── RangeIntPropertyDrawer.cs
│ ├── RangeIntPropertyDrawer.cs.meta
│ ├── RangePropertyDrawerBase.cs
│ └── RangePropertyDrawerBase.cs.meta
├── README.md
├── README.md.meta
├── RangeFloat.cs
├── RangeFloat.cs.meta
├── RangeInt.cs
└── RangeInt.cs.meta
├── RollingArray.meta
├── RollingArray
├── README.md
├── README.md.meta
├── RollingArray.cs
└── RollingArray.cs.meta
├── Singleton.meta
├── Singleton
├── PersistentSingletonMonoBehaviour.cs
├── PersistentSingletonMonoBehaviour.cs.meta
├── README.md
├── README.md.meta
├── SelfCreatingSingletonMonoBehaviour.cs
├── SelfCreatingSingletonMonoBehaviour.cs.meta
├── SingletonMonoBehaviour.cs
└── SingletonMonoBehaviour.cs.meta
├── UnityHelper.meta
├── UnityHelper
├── README.md
├── README.md.meta
├── UnityHelper.cs
└── UnityHelper.cs.meta
├── XmlHelper.meta
├── XmlHelper
├── README.md
├── README.md.meta
├── XmlHelper.cs
└── XmlHelper.cs.meta
├── _Images.meta
└── _Images
├── CountdownPropertyExample.png
├── CountdownPropertyExample.png.meta
├── EasedLerpFactorExample.gif
├── EasedLerpFactorExample.gif.meta
├── NoiseOutputValueExample.gif
├── NoiseOutputValueExample.gif.meta
├── RangeExample.png
└── RangeExample.png.meta
/Countdown.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1f118e99765cc44489971355083bddb8
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Countdown/Countdown.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// A handy countdown class providing a lot of convenience methods.
8 | ///
9 | public class Countdown
10 | {
11 | ///
12 | /// The time left at the current countdown.
13 | ///
14 | public float TimeLeft { get; set; }
15 |
16 | ///
17 | /// The initial duration set.
18 | ///
19 | public float Duration { get; private set; }
20 |
21 | ///
22 | /// A delegate for automatically providing a new duration
23 | /// when the time left runs out.
24 | ///
25 | public Func CalculateDurationDelegate { get; set; }
26 |
27 | ///
28 | /// Should the countdown automatically loop when it reaches zero?
29 | ///
30 | public bool Loop { get; set; }
31 |
32 | ///
33 | /// Creates a new countdown with no TotalTime duration set yet.
34 | /// Should the countdown loop automatically?
35 | ///
36 | public Countdown(bool loop) : this(loop, 0f)
37 | {
38 | }
39 |
40 | ///
41 | /// Creates a new countdown, starting at .
42 | ///
43 | /// Should the countdown loop automatically?
44 | /// The starting time to count down from.
45 | public Countdown(bool loop, float startDuration)
46 | {
47 | Loop = loop;
48 | TimeLeft = startDuration;
49 | Duration = TimeLeft;
50 | CalculateDurationDelegate = null;
51 | }
52 |
53 | ///
54 | /// Creates a new countdown with a delegate specifying how long it should take.
55 | ///
56 | /// Should the countdown loop automatically?
57 | /// A delegate providing the value to count down from.
58 | /// Optional: A one-time starting duration. Afterwards the is used.
59 | public Countdown(bool loop, Func calculateDurationDelegate, float? startDuration = null)
60 | {
61 | Loop = loop;
62 |
63 | // If there is no starting value, ask the delegate for one.
64 | if (startDuration == null)
65 | startDuration = calculateDurationDelegate();
66 |
67 | TimeLeft = startDuration.Value;
68 | Duration = startDuration.Value;
69 | CalculateDurationDelegate = calculateDurationDelegate;
70 | }
71 |
72 | ///
73 | /// Progresses the countdown by (or Time.deltaTime). Returns true if the countdown
74 | /// it reached zero this frame. If the countdown is already at zero when this is called and
75 | /// is true, it is restarted automatically.
76 | ///
77 | /// Optional: A deltaTime to use instead of Time.deltaTime.
78 | /// True if the countdown reached zero this frame. False if it is still going or was already zero and isn't looping.
79 | public bool Progress(float? deltaTime = null)
80 | {
81 | // If no deltaTime is supplied, use Time.deltaTime
82 | if (deltaTime == null)
83 | deltaTime = Time.deltaTime;
84 |
85 | // If the countdown is already over, loop
86 | if (ReachedZero)
87 | {
88 | // ...unless we don't want to loop
89 | if (!Loop)
90 | return false;
91 |
92 | // Refill the time. This might change the duration if we use a CalculateDurationDelegate.
93 | Refill();
94 |
95 | // If the duration is zero or less, this is stopped. (A CalculateDurationDelegate in
96 | // Refill() might have changed that, which is why we check it here and not earlier.)
97 | if (Duration <= 0)
98 | return false;
99 | }
100 |
101 | // Progress the countdown
102 | TimeLeft -= deltaTime.Value;
103 |
104 | // Returns if the countdown reached zero
105 | return ReachedZero;
106 | }
107 |
108 | ///
109 | /// Resets the countdown to TotalTime. If a is supplied,
110 | /// a new TotalTime is picked first.
111 | ///
112 | public void Reset()
113 | {
114 | if (CalculateDurationDelegate != null)
115 | {
116 | Duration = CalculateDurationDelegate();
117 | }
118 |
119 | TimeLeft = Duration;
120 | }
121 |
122 | ///
123 | /// Sets the and the .
124 | ///
125 | /// The time to set TotalTime and TimeLeft to.
126 | public void Reset(float timeLeft)
127 | {
128 | TimeLeft = timeLeft;
129 | Duration = timeLeft;
130 | }
131 |
132 | ///
133 | /// Loops the countdown by adding TotalTime to TimeLeft. This should only be called when is already zero
134 | /// or less. If a is supplied, a new TotalTime is picked first.
135 | ///
136 | /// The difference between Reset() and Loop() is that Loop() factors in when is already less than zero
137 | /// and subtracts it from the TotalTime.
138 | ///
139 | public void Refill()
140 | {
141 | if (CalculateDurationDelegate != null)
142 | {
143 | Refill(CalculateDurationDelegate());
144 | }
145 | else
146 | {
147 | Refill(Duration);
148 | }
149 | }
150 |
151 | ///
152 | /// Loops the countdown by settings TotalTime to and then adds it to .
153 | ///
154 | /// The difference between Reset() and Loop() is that Loop() factors in when is already less than zero
155 | /// and subtracts it from the TotalTime.
156 | ///
157 | /// The time to set TotalTime to and to add to TimeLeft.
158 | public void Refill(float newTotalTimeLeft)
159 | {
160 | TimeLeft += newTotalTimeLeft;
161 | Duration = newTotalTimeLeft;
162 | }
163 |
164 | ///
165 | /// Returns true when the countdown reached zero (or less).
166 | ///
167 | public bool ReachedZero
168 | {
169 | get { return TimeLeft <= 0; }
170 | }
171 |
172 | ///
173 | /// Returns true if the countdown is currently over zero.
174 | ///
175 | public bool IsRunning
176 | {
177 | get { return TimeLeft > 0; }
178 | }
179 |
180 | ///
181 | /// Returns the time passed for this countdown: (TotalTime-TimeLeft).
182 | ///
183 | public float TimePassed
184 | {
185 | get { return Duration - TimeLeft; }
186 | }
187 |
188 | ///
189 | /// Returns 0 when the countdown is just starting and 1 when it is elapsed.
190 | /// If TotalTime is 0, this returns 1.
191 | ///
192 | public float PercentElapsed
193 | {
194 | get { return 1 - PercentLeft; }
195 | }
196 |
197 | ///
198 | /// Returns 1 when the countdown is just starting and 0 when it is elapsed.
199 | /// If TotalTime is 0, this returns 0.
200 | ///
201 | public float PercentLeft
202 | {
203 | get
204 | {
205 | if (Duration == 0)
206 | return 0f;
207 |
208 | return Mathf.Clamp01(TimeLeft / Duration);
209 | }
210 | }
211 | }
212 | }
--------------------------------------------------------------------------------
/Countdown/Countdown.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2ab57da72e2f287418bdf88873d67111
3 | timeCreated: 1462732529
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/CountdownProperty.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// A base version for properties based on .
8 | ///
9 | [Serializable]
10 | public class CountdownProperty : Countdown, ISerializationCallbackReceiver
11 | {
12 | ///
13 | /// The total time to be set. Refreshed at each loop to allow for live editing.
14 | ///
15 | [SerializeField] float time;
16 |
17 | bool initialized;
18 |
19 | ///
20 | /// Empty constructor for the editor.
21 | ///
22 | public CountdownProperty(bool loop) : base(loop)
23 | {
24 | CalculateDurationDelegate = GetTimeProperty;
25 | }
26 |
27 | ///
28 | /// The method used to set the total time each loop.
29 | ///
30 | /// The value of the field.
31 | float GetTimeProperty()
32 | {
33 | return time;
34 | }
35 |
36 | ///
37 | /// Called before the serialization (reading the editor value) of the "time" property happens.
38 | /// It's empty and just here because needs it.
39 | ///
40 | public void OnBeforeSerialize()
41 | {
42 | }
43 |
44 | ///
45 | /// Called after the serialization (reading the editor value) of the "time" property happens.
46 | /// If the timer is not initialized yet, it will be here.
47 | ///
48 | public void OnAfterDeserialize()
49 | {
50 | if (initialized)
51 | return;
52 |
53 | initialized = true;
54 | Reset();
55 | }
56 | }
57 | }
--------------------------------------------------------------------------------
/Countdown/CountdownProperty.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 52154614c7e358d4abe708a4fe27908a
3 | timeCreated: 1462737279
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/CountdownPropertyLoop.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// A version of that can be set in the Editor.
7 | /// Refreshes the total time on each loop to allow for live editing. Loops.
8 | ///
9 | [Serializable]
10 | public class CountdownPropertyLoop : CountdownProperty
11 | {
12 | ///
13 | /// Empty constructor for the editor.
14 | ///
15 | public CountdownPropertyLoop() : base(true)
16 | {
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Countdown/CountdownPropertyLoop.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6b8459496fb6a2a4b9763696e3f271e9
3 | timeCreated: 1462735192
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/CountdownPropertyOnce.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// A version of that can be set in the Editor.
7 | /// Just called once, but refreshes the total time on each call to .
8 | ///
9 | [Serializable]
10 | public class CountdownPropertyOnce : CountdownProperty
11 | {
12 | ///
13 | /// Empty constructor for the editor.
14 | ///
15 | public CountdownPropertyOnce() : base(false)
16 | {
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/Countdown/CountdownPropertyOnce.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 74dbb9fefcad3174199e29b4dabd37d0
3 | timeCreated: 1462735192
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 52f73aee8c49930469dedb0acdd35685
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownLoopPropertyDrawer.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 |
3 | namespace UnityUtilities
4 | {
5 | [CustomPropertyDrawer(typeof (CountdownPropertyLoop))]
6 | public class CountdownLoopPropertyDrawer : CountdownPropertyDrawerBase
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownLoopPropertyDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: da409ad08412e904f9f429e4810083c3
3 | timeCreated: 1462735312
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownOncePropertyDrawer.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 |
3 | namespace UnityUtilities
4 | {
5 | [CustomPropertyDrawer(typeof (CountdownPropertyOnce))]
6 | public class CountdownOncePropertyDrawer : CountdownPropertyDrawerBase
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownOncePropertyDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c2dc4b255e32c4c4dac9cc7ebe0cc5d8
3 | timeCreated: 1462737346
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownPropertyDrawerBase.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | public class CountdownPropertyDrawerBase : PropertyDrawer
7 | {
8 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
9 | {
10 | // Using BeginProperty / EndProperty on the parent property means that
11 | // prefab override logic works on the entire property.
12 | EditorGUI.BeginProperty(position, label, property);
13 |
14 | // Set tooltip, if any
15 | label.tooltip = EditorHelper.GetTooltip(fieldInfo);
16 |
17 | // Draw label
18 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
19 |
20 | // Don't make child field be indented
21 | var indent = EditorGUI.indentLevel;
22 | EditorGUI.indentLevel = 0;
23 |
24 | // Draw the time field - passs GUIContent.none to each so they are drawn without labels
25 | EditorGUI.PropertyField(position, property.FindPropertyRelative("time"), GUIContent.none);
26 |
27 | // Set indent back to what it was
28 | EditorGUI.indentLevel = indent;
29 |
30 | EditorGUI.EndProperty();
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/Countdown/Editor/CountdownPropertyDrawerBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1e89fc7efa522a44e85f2029e6f5f9c8
3 | timeCreated: 1462735312
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Countdown/README.md:
--------------------------------------------------------------------------------
1 | # Countdown
2 |
3 | This class is useful for things like cooldowns or spawn delays. It is also helpful for tweening things by using the `PercentElapsed` property.
4 |
5 | (If you want to tween a lot of stuff, you might want to check out [DOTween](http://dotween.demigiant.com). Actually, check it out either way, DOTween is fabulous!)
6 |
7 | ## Examples
8 |
9 | ### CountdownExample
10 |
11 | ```C#
12 | public class CountdownExample : MonoBehaviour
13 | {
14 | Countdown countdownLoop;
15 | Countdown countdownRandom;
16 | Countdown countdownOnce;
17 | Countdown countdownDelay;
18 |
19 | void Awake()
20 | {
21 | // Looping countdown, every 2 seconds
22 | countdownLoop = new Countdown(true, 2f);
23 |
24 | // Looping countdown, delegate is called every loop to determine duration (1 to 5 seconds)
25 | countdownRandom = new Countdown(true, () => UnityEngine.Random.Range(1f, 5f));
26 |
27 | // Non-looping countdown, 5 seconds duration. Can be reset by calling Reset().
28 | countdownOnce = new Countdown(false, 5f);
29 |
30 | // Non-looping countdown that isn't started yet. Can be started by calling e.g. Reset(5f).
31 | countdownDelay = new Countdown(false);
32 | }
33 |
34 | void Update()
35 | {
36 | // Looping automatically
37 | if (countdownLoop.Progress())
38 | Debug.Log("This is logged every 2 seconds.");
39 |
40 | // Looping automatically. Duration is chosen between 1 and 5 every loop.
41 | if (countdownRandom.Progress())
42 | Debug.Log("This is logged every 1 to 5 seconds.");
43 |
44 | // Not looping
45 | if (countdownOnce.Progress())
46 | Debug.Log("This is shown once after 5 seconds.");
47 |
48 | // Start countdownDelay (again) - if it's already running, it is reset
49 | if (Input.GetKeyDown(KeyCode.Alpha1))
50 | countdownDelay.Reset(1f); // 1 second
51 |
52 | if (Input.GetKeyDown(KeyCode.Alpha2))
53 | countdownDelay.Reset(2f); // 2 seconds
54 |
55 | // Show this once 1/2 seconds after 1/2 was last pressed
56 | if (countdownDelay.Progress())
57 | Debug.Log("This is shown after " + countdownDelay.Duration + " seconds.");
58 |
59 | // Output data about the countdown when space is pressed
60 | if (Input.GetKeyDown(KeyCode.Space))
61 | {
62 | if (countdownDelay.IsRunning)
63 | Debug.Log("countdownDelay is " + (countdownDelay.PercentElapsed * 100) + "% complete.");
64 | else
65 | Debug.Log("countdownDelay is stopped.");
66 | }
67 | }
68 | ```
69 |
70 | ### CountdownPropertyExample
71 |
72 | You can also use `CountdownPropertyOnce` and `CountdownPropertyLoop` to get the values directly from the
73 | editor. Live-editing works - if you change the value in the editor, it will be used in the next loop.
74 |
75 | 
76 |
77 | ```C#
78 | public class CountdownPropertyExample : MonoBehaviour
79 | {
80 | [SerializeField] CountdownPropertyOnce countdownOnce;
81 | [SerializeField] CountdownPropertyLoop countdownLoop;
82 |
83 | void Update()
84 | {
85 | // Looping automatically
86 | if (countdownLoop.Progress())
87 | Debug.Log("This is logged every " + countdownLoop.Duration + " seconds.");
88 |
89 | // Not looping
90 | if (countdownOnce.Progress())
91 | Debug.Log("This is shown once after " + countdownOnce.Duration + " seconds.");
92 |
93 | // Start countdownOnce again - if it's already running, it is reset
94 | if (Input.GetKeyDown(KeyCode.Space))
95 | countdownOnce.Reset();
96 | }
97 | }
98 | ```
99 |
100 | ## Dependencies
101 |
102 | None.
--------------------------------------------------------------------------------
/Countdown/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a6049e8646652634d99337ce6717016e
3 | timeCreated: 1462733353
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Doxyfile.dox.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 09d4a4db002008149aa44ec7c00ac54a
3 | timeCreated: 1462828878
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/EditorHelper.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 30705395a9275334a8a69a8b7eae8a19
3 | folderAsset: yes
4 | timeCreated: 1465150348
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/EditorHelper/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d072766fbad5a6747a8ced474a2a0210
3 | folderAsset: yes
4 | timeCreated: 1465151252
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/EditorHelper/Editor/EditorHelper.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// Provides static helper methods for editor classes.
8 | ///
9 | public static class EditorHelper
10 | {
11 | ///
12 | /// Gets the tooltip of a field.
13 | ///
14 | /// The field to get the tooltip from.
15 | /// The tooltip if set, else an empty string.
16 | public static string GetTooltip(FieldInfo field)
17 | {
18 | var attributes = (TooltipAttribute[]) field.GetCustomAttributes(typeof (TooltipAttribute), true);
19 | return (attributes.Length > 0)
20 | ? attributes[0].tooltip
21 | : "";
22 | }
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/EditorHelper/Editor/EditorHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c229a6b2549c99445b3022e1232242b8
3 | timeCreated: 1465150348
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/EditorHelper/README.md:
--------------------------------------------------------------------------------
1 | # EditorHelper
2 |
3 | Contains a method for getting the `[Tooltip]` attribute content of fields for editor classes. I might add more helper methods in the future.
4 |
5 | ## Example
6 |
7 | ```C#
8 | public class RangePropertyDrawerBase : PropertyDrawer
9 | {
10 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
11 | {
12 | // Using BeginProperty / EndProperty on the parent property means that
13 | // prefab override logic works on the entire property.
14 | EditorGUI.BeginProperty(position, label, property);
15 |
16 | // Set tooltip, if any
17 | label.tooltip = EditorHelper.GetTooltip(fieldInfo);
18 |
19 | // Draw label
20 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
21 |
22 | // Draw the GUI
23 | // [...]
24 |
25 | EditorGUI.EndProperty();
26 | }
27 | }
28 | ```
29 |
30 | ## Dependencies
31 |
32 | None.
--------------------------------------------------------------------------------
/EditorHelper/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5ffee59e65410ae48a58fb0973a32369
3 | timeCreated: 1465151238
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Examples.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 6ba4d0c59e672b8488efffd8c25d7aba
3 | folderAsset: yes
4 | timeCreated: 1462735836
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Examples/CountdownExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | public class CountdownExample : MonoBehaviour
6 | {
7 | Countdown countdownLoop;
8 | Countdown countdownRandom;
9 | Countdown countdownOnce;
10 | Countdown countdownDelay;
11 |
12 | void Awake()
13 | {
14 | // Looping countdown, every 2 seconds
15 | countdownLoop = new Countdown(true, 2f);
16 |
17 | // Looping countdown, delegate is called every loop to determine duration (1 to 5 seconds)
18 | countdownRandom = new Countdown(true, () => UnityEngine.Random.Range(1f, 5f));
19 |
20 | // Non-looping countdown, 5 seconds duration. Can be reset by calling Reset().
21 | countdownOnce = new Countdown(false, 5f);
22 |
23 | // Non-looping countdown that isn't started yet. Can be started by calling e.g. Reset(5f).
24 | countdownDelay = new Countdown(false);
25 | }
26 |
27 | void Update()
28 | {
29 | // Looping automatically
30 | if (countdownLoop.Progress())
31 | Debug.Log("This is logged every 2 seconds.");
32 |
33 | // Looping automatically. Duration is chosen between 1 and 5 every loop.
34 | if (countdownRandom.Progress())
35 | Debug.Log("This is logged every 1 to 5 seconds.");
36 |
37 | // Not looping
38 | if (countdownOnce.Progress())
39 | Debug.Log("This is shown once after 5 seconds.");
40 |
41 | // Start countdownDelay (again) - if it's already running, it is reset
42 | if (Input.GetKeyDown(KeyCode.Alpha1))
43 | countdownDelay.Reset(1f); // 1 second
44 |
45 | if (Input.GetKeyDown(KeyCode.Alpha2))
46 | countdownDelay.Reset(2f); // 2 seconds
47 |
48 | // Show this once 1/2 seconds after 1/2 was last pressed
49 | if (countdownDelay.Progress())
50 | Debug.Log("This is shown after " + countdownDelay.Duration + " seconds.");
51 |
52 | // Output data about the countdown when space is pressed
53 | if (Input.GetKeyDown(KeyCode.Space))
54 | {
55 | if (countdownDelay.IsRunning)
56 | Debug.Log("countdownDelay is " + Mathf.FloorToInt(countdownDelay.PercentElapsed * 100) + "% complete.");
57 | else
58 | Debug.Log("countdownDelay is stopped.");
59 | }
60 | }
61 | }
62 | }
--------------------------------------------------------------------------------
/Examples/CountdownExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 2e65fcbdbbfca7a41aa8f9a6b28333ec
3 | timeCreated: 1462734965
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/CountdownPropertyExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | public class CountdownPropertyExample : MonoBehaviour
6 | {
7 | [Tooltip("Test")]
8 | [SerializeField] CountdownPropertyOnce countdownOnce;
9 | [SerializeField] CountdownPropertyLoop countdownLoop;
10 |
11 | void Update()
12 | {
13 | // Looping automatically
14 | if (countdownLoop.Progress())
15 | Debug.Log("This is logged every " + countdownLoop.Duration + " seconds.");
16 |
17 | // Not looping
18 | if (countdownOnce.Progress())
19 | Debug.Log("This is shown once after " + countdownOnce.Duration + " seconds.");
20 |
21 | // Start countdownOnce again - if it's already running, it is reset
22 | if (Input.GetKeyDown(KeyCode.Space))
23 | countdownOnce.Reset();
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/Examples/CountdownPropertyExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 40c876e76324fd8438c7107873f75e35
3 | timeCreated: 1466344927
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/LINQExtensionsExamples.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using UnityEngine;
5 |
6 | namespace UnityUtilities.Examples
7 | {
8 | public class LINQExtensionsExamples : MonoBehaviour
9 | {
10 | [SerializeField] Transform[] elements;
11 |
12 | void Awake()
13 | {
14 | int[] items = new int[] {1, 2, 3, 4, 5};
15 |
16 | // Gets a random item
17 | Debug.Log(items.RandomElement());
18 |
19 | // Shuffles the array in place
20 | items.Shuffle();
21 |
22 | // Outputs the array on one line. Great for debugging.
23 | // Example output:
24 | // "3", "5", "2", "1", "4"
25 | Debug.Log(items.ToOneLineString());
26 | }
27 |
28 | void Update()
29 | {
30 | if (Input.GetMouseButtonDown(0))
31 | {
32 | // Get the x/y position of the click (for an orthographic camera)
33 | var mousePositionWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
34 |
35 | // Gets the element closest to the mouse click
36 | var nearestElement = elements.Nearest(mousePositionWorld);
37 |
38 | Debug.Log("Nearest element " + nearestElement.name + " at position " + nearestElement.position);
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Examples/LINQExtensionsExamples.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 808c85cf6542d124b8c9635c0a6e7008
3 | timeCreated: 1463270294
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/MathHelperExamples.cs:
--------------------------------------------------------------------------------
1 |
2 | using UnityEngine;
3 |
4 | #pragma warning disable 219 // We don't care about: warning CS0219: The variable `[...]' is assigned but its value is never used
5 | namespace UnityUtilities.Examples
6 | {
7 | public class MathHelperExamples : MonoBehaviour
8 | {
9 | [SerializeField] private Transform runner;
10 | [SerializeField] private Transform follower;
11 |
12 | void Awake()
13 | {
14 | MappingExamples();
15 | AnglesExamples();
16 |
17 | // Checks what calling the same EasedLerp from 0 to 1 and a factor of 75%
18 | // with 1, 10, 100, 1000 or 10000 FPS would return after one second.
19 | CheckEasedLerp(1); // => 0.75
20 | CheckEasedLerp(10); // => 0.7499999
21 | CheckEasedLerp(100); // => 0.7499999
22 | CheckEasedLerp(1000); // => 0.7499995
23 | CheckEasedLerp(10000); // => 0.7500508
24 | }
25 |
26 | void Update()
27 | {
28 | EasedLerpFactorExample();
29 | }
30 |
31 | private void MappingExamples()
32 | {
33 | // Maps 10 from [-250..250] to [0..10]
34 | Debug.Log(MathHelper.MapClamped(10f, -250f, 250f, 0f, 10f)); // => 5.2
35 |
36 | // Applies a deadzone to a joystick input (positive and negative) to make sure that
37 | // little imperfections in the stick resting position don't make the character move
38 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.1f, 0.2f)); // => 0
39 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.2f, 0.2f)); // => 0
40 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.21f, 0.2f)); // => 0.21
41 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.3f, 0.2f)); // => 0.3
42 | Debug.Log(MathHelper.ApplyJoystickDeadzone(1f, 0.2f)); // => 1
43 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.1f, 0.2f)); // => 0
44 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.2f, 0.2f)); // => 0
45 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.21f, 0.2f)); // => -0.21
46 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.3f, 0.2f)); // => -0.3
47 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-1f, 0.2f)); // => -1
48 | }
49 |
50 | private void AnglesExamples()
51 | {
52 | // Gets the center angle between two angles
53 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, 160f)); // => 90
54 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, 220f)); // => -60
55 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, -140f)); // => -60
56 |
57 | // Normalizes an angle between 0 (inclusive) and 360 (exclusive).
58 | Debug.Log(MathHelper.NormalizeAngleDeg360(-180f)); // => 180
59 | Debug.Log(MathHelper.NormalizeAngleDeg360(180f)); // => 180
60 | Debug.Log(MathHelper.NormalizeAngleDeg360(0f)); // => 0
61 | Debug.Log(MathHelper.NormalizeAngleDeg360(360f)); // => 0
62 | Debug.Log(MathHelper.NormalizeAngleDeg360(340f)); // => 340
63 |
64 | // Normalizes an angle between -180 (inclusive) and 180 (exclusive).
65 | Debug.Log(MathHelper.NormalizeAngleDeg180(-180f)); // => -180
66 | Debug.Log(MathHelper.NormalizeAngleDeg180(180f)); // => -180
67 | Debug.Log(MathHelper.NormalizeAngleDeg180(0f)); // => 0
68 | Debug.Log(MathHelper.NormalizeAngleDeg180(360f)); // => 0
69 | Debug.Log(MathHelper.NormalizeAngleDeg180(340f)); // => -20
70 | }
71 |
72 | private void EasedLerpFactorExample()
73 | {
74 | // Get the world position of the mouse pointer
75 | Vector3 mousePositionWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
76 | mousePositionWorld.z = 0f;
77 |
78 | // Set the runner position to the mouse pointer
79 | runner.position = mousePositionWorld;
80 |
81 | // Move the follower 75% of the remaining distance to the runner per second
82 | follower.position = UnityHelper.EasedLerpVector3(follower.position, runner.position, 0.75f);
83 |
84 | // ...which is the same as:
85 |
86 | //float t = MathHelper.EasedLerpFactor(0.75f);
87 | //follower.position = Vector3.Lerp(follower.position, mousePositionWorld, t);
88 | }
89 |
90 | void CheckEasedLerp(int steps)
91 | {
92 | var dt = 1f / steps;
93 |
94 | var currentValue = 0f;
95 | for (var i = 0; i < steps; i++)
96 | currentValue = MathHelper.EasedLerp(currentValue, 1f, 0.75f, dt);
97 |
98 | Debug.LogFormat("CheckEasedLerp({0}): {1}", steps, currentValue);
99 | }
100 | }
101 | }
102 | #pragma warning restore 168
103 |
104 |
--------------------------------------------------------------------------------
/Examples/MathHelperExamples.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: dadacaa2be8390043a3822f31a737948
3 | timeCreated: 1477153028
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/MeshCreatorExample.cs:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasWehrum/unity-utilities/c78da2928b1f7b73046a697185271e7effeddd1f/Examples/MeshCreatorExample.cs
--------------------------------------------------------------------------------
/Examples/MeshCreatorExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3e0b2799eda53e34fa4e3e64a348fa02
3 | timeCreated: 1467505582
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/NoiseOutputValueExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | public class NoiseOutputValueExample : MonoBehaviour
6 | {
7 | [SerializeField] NoiseOutputValue positionNoise;
8 | [SerializeField] Transform sphere;
9 |
10 | void Update()
11 | {
12 | // Updates the value with Time.deltaTime*speed
13 | positionNoise.Progress();
14 |
15 | // Sets the y position at the current output value
16 | sphere.transform.position = new Vector3(0, positionNoise.OutputValue, 0f);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/Examples/NoiseOutputValueExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c51a9de8de585c54bb1f08bc4aada97c
3 | timeCreated: 1462744871
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/RandomBagExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Text;
3 | using UnityEngine;
4 |
5 | namespace UnityUtilities.Examples
6 | {
7 | public class RandomBagExample : MonoBehaviour
8 | {
9 | enum TetrisPiece
10 | {
11 | Line, Square, T, J, L, S, Z
12 | }
13 |
14 | RandomBag pieceBag;
15 |
16 | void Awake()
17 | {
18 | // Get an array with each value of TetrisPiece
19 | TetrisPiece[] tetrisPieceArray = (TetrisPiece[]) Enum.GetValues(typeof (TetrisPiece));
20 |
21 | // Create the bag containing two instances of every value of TetrisPiece
22 | pieceBag = new RandomBag(tetrisPieceArray, 2);
23 |
24 | // Gets 50 items from the bag. The bag will be filled with 14 TetrisPieces and
25 | // automatically refilled with 14 more when needed. No two pieces will ever be
26 | // more than 14 calls apart - and even that will only happen if that piece was
27 | // the first and last item in the current 14 piece bag filling.
28 | StringBuilder str = new StringBuilder();
29 | for (var i = 0; i < 50; i++)
30 | {
31 | str.Append(pieceBag.PopRandomItem());
32 | str.Append(", ");
33 | }
34 |
35 | Debug.Log(str);
36 |
37 | // Example output:
38 | // T, Z, J, Square, Z, S, L, L, S, Line, J, Line, Square, T, Square, Z,
39 | // S, T, Line, Square, Z, T, J, Line, S, L, J, L, S, Z, Line, J, Line,
40 | // J, L, L, S, T, T, Z, Square, Square, Z, T, S, Z, J, J, L, Line,
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Examples/RandomBagExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 94efbeb7353e5ce4c947c5e49e1656ea
3 | timeCreated: 1463259046
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/RangeExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | public class RangeExample : MonoBehaviour
6 | {
7 | [SerializeField] RangeInt amountRange;
8 | [SerializeField] RangeFloat numberRange;
9 |
10 | void Awake()
11 | {
12 | // Get a random number in amountRange
13 | int amount = amountRange.RandomInclusive;
14 |
15 | // Output [amount] numbers
16 | for (int i = 0; i < amount; i++)
17 | {
18 | // Transform [i..(amount-1)] to [0..1]
19 | var t = ((float)i / (amount - 1));
20 |
21 | // Mathf.Lerp(numberRange.From, numberRange.To, t)
22 | Debug.Log(numberRange.Lerp(t));
23 | }
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/Examples/RangeExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 79d9570a75721024e80e0cd578b370e1
3 | timeCreated: 1462746256
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/RollingArrayExample.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | public class RollingArrayExample : MonoBehaviour
6 | {
7 | [SerializeField] Transform indicatorObject;
8 |
9 | RollingArray mousePositions;
10 | Camera mainCamera;
11 |
12 | void Awake()
13 | {
14 | // Save the last 50 elements
15 | mousePositions = new RollingArray(50);
16 |
17 | // Cache a reference to the main camera
18 | mainCamera = Camera.main;
19 | }
20 |
21 | void FixedUpdate()
22 | {
23 | // Get the mouse position in a fixed interval
24 | // If we get to 50 positions, the oldest position will be replaced
25 | mousePositions.Append(mainCamera.ScreenToWorldPoint(Input.mousePosition));
26 | }
27 |
28 | void Update()
29 | {
30 | // Only continue if we have at least one mouse position
31 | if (mousePositions.IsEmpty)
32 | return;
33 |
34 | // Go through all the saved mouse positions from oldest to newest to get the average
35 | Vector2 averagePosition = new Vector2();
36 | for (var i = 0; i < mousePositions.Count; i++)
37 | {
38 | averagePosition += mousePositions[i];
39 | }
40 | averagePosition /= mousePositions.Count;
41 |
42 | // Set the indicator object to the average position
43 | indicatorObject.position = averagePosition;
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Examples/RollingArrayExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: fed215a0a85333744a0f6903548366cf
3 | timeCreated: 1465133468
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/SingletonEntityManager.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities.Examples
5 | {
6 | /* If the following component is added on a game object in the scene, it could be accessed from anywhere
7 | * via SingletonEntityManager.Instance, e.g.: SingletonEntityManager.Instance.AddEntity(newEntity);
8 | *
9 | * This is available even before SingletonEntityManager.Awake() is called.
10 | *
11 | * If you want to use OnDestroy(), you have to override it like shown in the example below. All other MonoBehaviour
12 | * callbacks can be used as usual.
13 | */
14 |
15 | public class SingletonEntityManager : SingletonMonoBehaviour
16 | {
17 | List entities;
18 |
19 | public IEnumerable Entities
20 | {
21 | get { return entities; }
22 | }
23 |
24 | void Awake()
25 | {
26 | entities = new List();
27 | }
28 |
29 | // If you want to use OnDestroy(), you have to override it like this
30 | protected override void OnDestroy()
31 | {
32 | base.OnDestroy();
33 | Debug.Log("Destroyed");
34 | }
35 |
36 | public void AddEntity(GameObject entity)
37 | {
38 | entities.Add(entity);
39 | }
40 |
41 | public void RemoveEntity(GameObject entity)
42 | {
43 | entities.Remove(entity);
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Examples/SingletonEntityManager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e9eef450bee08ed46979cccbf8a00b24
3 | timeCreated: 1462747651
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/SingletonMusicManager.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities.Examples
4 | {
5 | /* The SingletonMusicManager in the following example can be accessed in the same way, but it is not destroyed when the scenes switches.
6 |
7 | You could make this SingletonMusicManager a prefab and drop it in multiple scenes that you work on. If at any time there are two `SingletonMusicManager`,
8 | the one from the previous scene survives and the new one is destroyed. (For that reason, you should never create an Awake() method in a
9 | PersistentSingletonMonoBehaviour. Instead, use `OnPersistentSingletonAwake()` because it is only called on "surviving" instances. Similarily, you shouldn't
10 | have an OnDestroy() method which would be called if this is ever destroyed via Destroy(); instead, use OnPersistentSingletonDestroyed().)
11 |
12 | Note that SingletonMusicManager.Instance is only available after SingletonMusicManager.Awake() was called, so if you need it in another Awake()
13 | call, you should put the SingletonMusicManager higher in the Script Execution Order: http://docs.unity3d.com/Manual/class-ScriptExecution.html.
14 | */
15 |
16 | public class SingletonMusicManager : PersistentSingletonMonoBehaviour
17 | {
18 | protected override void OnPersistentSingletonAwake()
19 | {
20 | base.OnPersistentSingletonAwake();
21 |
22 | // Start playing the music the first time Awake() is called
23 | PlayMusic();
24 | }
25 |
26 | protected override void OnSceneSwitched()
27 | {
28 | base.OnSceneSwitched();
29 |
30 | // Fade to random song once a new scene is loaded
31 | FadeToRandomSong();
32 | }
33 |
34 | protected override void OnPersistentSingletonDestroyed()
35 | {
36 | base.OnPersistentSingletonDestroyed();
37 |
38 | // Stop the music when Destroy() was called on the active instance.
39 | StopMusic();
40 | }
41 |
42 | public void PlayMusic()
43 | {
44 | Debug.Log("Play music");
45 | }
46 |
47 | public void StopMusic()
48 | {
49 | Debug.Log("Stop music");
50 | }
51 |
52 | public void FadeToRandomSong()
53 | {
54 | Debug.Log("Fade to a random song");
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Examples/SingletonMusicManager.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 19d5da28c8805a24bb4571bd23ad2003
3 | timeCreated: 1462747648
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/UnityHelperExamples.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | #pragma warning disable 219 // We don't care about: warning CS0219: The variable `[...]' is assigned but its value is never used
4 | namespace UnityUtilities.Examples
5 | {
6 | public class UnityHelperExamples : MonoBehaviour
7 | {
8 | [SerializeField] Transform someEnemyTransform;
9 | [SerializeField] Transform enemyIndicator;
10 | [SerializeField] GameObject prefab;
11 | [SerializeField] LayerMask someLayerMask;
12 | [SerializeField] CharacterController playerCharacterController;
13 |
14 | void Awake()
15 | {
16 | TransformVectorColorExamples();
17 | CentroidExample();
18 | Vector2RotationExamples();
19 | GameObjectExamples();
20 | RectExamples();
21 | PlayerPrefsExample();
22 | CapsuleCastExample();
23 | RandomExamples();
24 | OtherExamples();
25 |
26 | // You can find an example for eased lerping in MathHelperExamples.EasedLerpFactorExample()
27 | }
28 |
29 | void TransformVectorColorExamples()
30 | {
31 | /* Set the transform.position.x to 5 and z to 3. Keeps y.
32 | * Equivalent to:
33 | * var position = transform.position;
34 | * position.x = 5;
35 | * position.z = 3;
36 | * transform.position = position;
37 | */
38 | transform.SetPosition(x: 5, z: 3);
39 |
40 | // Same as above; only sets transform.localEulerAngles.y.
41 | // There are extension methods for all position/rotation/scales.
42 | transform.SetLocalEulerAngles(y: 180);
43 |
44 | // Similar methods are available for Vector2/3/4 and Color:
45 | // Gets the transform.position, but with y set to 0.
46 | Vector3 floorPosition = transform.position.Change3(y: 0);
47 |
48 | // Gets the material color, but sets the color.a value to 0.5.
49 | Color halfTransparentColor = GetComponent().sharedMaterial.color.ChangeAlpha(0.5f);
50 |
51 | // Sets the position/rotation of enemyIndicator to someEnemyTransform.position/rotation
52 | enemyIndicator.CopyPositionAndRotatationFrom(someEnemyTransform);
53 | }
54 |
55 | private void CentroidExample()
56 | {
57 | Vector3[] list = {
58 | new Vector3(-5, 10, 12),
59 | new Vector3(55, 32, 10),
60 | new Vector3(85, -40, 80)
61 | };
62 |
63 | // Calculates the geometric center (the average) of the input list
64 | Debug.Log("Centroid: " + list.CalculateCentroid()); // => Centroid: (45.0, 0.7, 34.0)
65 | }
66 |
67 | void Vector2RotationExamples()
68 | {
69 | // Create a length 1 Vector2 pointing 40 degrees away from (1.0, 0.0)
70 | var vector = UnityHelper.CreateVector2AngleDeg(20f);
71 | Debug.Log(vector); // => (0.9, 0.3)
72 |
73 | // Rotate the vector 70 degrees
74 | vector = vector.RotateDeg(70f);
75 | Debug.Log(vector); // => (0.0, 1.0)
76 |
77 | // Output the current vector rotation
78 | Debug.Log(vector.GetAngleDeg()); // => 90
79 | }
80 |
81 | void GameObjectExamples()
82 | {
83 | // Assigns layer 4 to this GameObject and all its children recursively
84 | gameObject.AssignLayerToHierarchy(4);
85 |
86 | // Create an instance of a prefab. When the prefab is named "Original", the instance will
87 | // be named "Original(Copy)"
88 | GameObject copiedGameObject = Instantiate(prefab);
89 |
90 | // Return the name without "(Copy)"
91 | Debug.Log(copiedGameObject.GetNameWithoutClone()); // => Original
92 |
93 | // Change the name back to "Original"
94 | copiedGameObject.StripCloneFromName();
95 | }
96 |
97 | void RectExamples()
98 | {
99 | // Make a rect from (10|20) to (60|120)
100 | Rect rect = new Rect(10, 20, 50, 100);
101 |
102 | // Gets a random position for an enemy in the rect, leaving a 5 unit border
103 | Vector2 enemySpawnPosition = rect.RandomPosition(-5);
104 |
105 | // Gets a random sub rect of size 10|10 in which we could spawn multiple enemies
106 | Rect enemySpawnSubrect = rect.RandomSubRect(10, 10);
107 |
108 | Vector2 enemyPosition = new Vector2(0, 500);
109 |
110 | // Clamp an enemy position to the rect
111 | enemyPosition = rect.Clamp2(enemyPosition);
112 | Debug.Log(enemyPosition); // Output: (10.0, 120.0)
113 |
114 | // Create a rect that is 10 units bigger to each side
115 | Rect biggerRect = rect.Extend(10);
116 |
117 | // Get the corner points
118 | Vector2[] cornerPoints = rect.GetCornerPoints();
119 | }
120 |
121 | void PlayerPrefsExample()
122 | {
123 | // Gets a PlayerPrefs key "FirstStart" or return true if not set
124 | bool isFirstStart = UnityHelper.PlayerPrefsGetBool("FirstStart", true);
125 |
126 | // Set the key FirstStart to false
127 | UnityHelper.PlayerPrefsSetBool("FirstStart", false);
128 | }
129 |
130 | void CapsuleCastExample()
131 | {
132 | Vector3 point1;
133 | Vector3 point2;
134 | float radius;
135 | Vector3 origin = playerCharacterController.transform.position;
136 |
137 | // Get the data for the capsule cast from the current player position
138 | UnityHelper.GetCapsuleCastData(playerCharacterController, origin, out point1, out point2, out radius);
139 |
140 | // Cast 2 units forwards
141 | bool hitSomething = Physics.CapsuleCast(point1, point2, radius, Vector3.forward, 2f);
142 | }
143 |
144 | void RandomExamples()
145 | {
146 | // Points in a random 2D direction
147 | var randomDirection2D = UnityHelper.RandomOnUnitCircle;
148 |
149 | // Either goes left or right
150 | var deltaX = 20 * UnityHelper.RandomSign;
151 |
152 | // Gets set to either choice
153 | var choice = UnityHelper.RandomBool ? "Choice A" : "Choice B";
154 | }
155 |
156 | void OtherExamples()
157 | {
158 | // Does the layer mask contain layer 4?
159 | bool containsLayer4 = someLayerMask.ContainsLayer(4);
160 |
161 | // Get the bounds of all colliders in the level to clamp the camera later on
162 | Collider[] allColliders = FindObjectsOfType();
163 | Bounds levelBounds = UnityHelper.CombineColliderBounds(allColliders);
164 |
165 | // Find out how much the perspective camera can see at 10 unit away
166 | Vector2 viewportSizeAtDistance = Camera.main.CalculateViewportWorldSizeAtDistance(10);
167 | }
168 | }
169 | }
170 | #pragma warning restore 168
--------------------------------------------------------------------------------
/Examples/UnityHelperExamples.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 262d17ba29d2c21409dd7bac960113f0
3 | timeCreated: 1465301267
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Examples/XmlHelperExample.cs:
--------------------------------------------------------------------------------
1 | using System.Xml;
2 | using System.Xml.Serialization;
3 | using UnityEngine;
4 |
5 | #pragma warning disable 414, 219
6 | namespace UnityUtilities.Examples
7 | {
8 | public class XmlHelperExample : MonoBehaviour
9 | {
10 | public class TestData
11 | {
12 | // A public field - will be serialized
13 | public int field;
14 |
15 | // A private field with public property - will be serialized
16 | float property;
17 | public float Property
18 | {
19 | get { return property; }
20 | set { property = value;}
21 | }
22 |
23 | // An auto property - will be serialized
24 | public bool AutoProperty { get; set; }
25 |
26 | // A private field - will *not* be serialized
27 | string privateField = "Test";
28 |
29 | // A public field marked "XmlIgnore" - will *not* be serialized
30 | [XmlIgnore]
31 | public double publicNonSerialized = 5.5;
32 |
33 | // The public default constructor is needed for the XmlSerializer.
34 | public TestData()
35 | {
36 | }
37 |
38 | public TestData(int field, float property, bool autoProperty)
39 | {
40 | this.field = field;
41 | this.property = property;
42 | AutoProperty = autoProperty;
43 | }
44 | }
45 |
46 | void Awake()
47 | {
48 | SerializationExamples();
49 | XmlExamples();
50 | }
51 |
52 | void SerializationExamples()
53 | {
54 | // Create a new TestData object
55 | TestData data = new TestData(1, 2.3f, true);
56 |
57 | // Serialize the TestData object into a string
58 | string xmlString = data.SerializeToXmlString();
59 |
60 | /* Output:
61 |
62 |
63 |
64 | 1
65 | 2.3
66 | true
67 |
68 | */
69 | Debug.Log(xmlString);
70 |
71 | // Get the data back from the string
72 | TestData deserializedData = xmlString.DeserializeFromXmlString();
73 | }
74 |
75 | void XmlExamples()
76 | {
77 | // Create an XmlDocument with test data
78 | XmlDocument xmlDocument = new XmlDocument();
79 | xmlDocument.LoadXml("" +
80 | " " +
81 | " Grunt" +
82 | " " +
83 | " " +
84 | " " +
85 | " Tank" +
86 | " " +
87 | " true" +
88 | " " +
89 | "");
90 |
91 | // Read each enemyData element in the enemyList
92 | foreach (XmlNode enemyData in xmlDocument["enemyList"].ChildNodes)
93 | {
94 | // Get the name element content, if it exists, else set "???"
95 | string name = enemyData.GetElementString("name", "???");
96 |
97 | // Get the position element and then its attributes
98 | XmlNode position = enemyData["position"];
99 | int x = position.GetAttributeInt("x");
100 | int y = position.GetAttributeInt("y");
101 |
102 | // Get the ranged element content, if it exists, else set "false"
103 | bool ranged = enemyData.GetElementBool("ranged", false);
104 |
105 | // Output the result
106 | Debug.Log(string.Format("{0} at {1}|{2} is {3}",
107 | name,
108 | x,
109 | y,
110 | ranged ? "ranged" : "not ranged"));
111 | }
112 |
113 | /* Grunt at 5|3 is not ranged
114 | Tank at 7|1 is ranged
115 | */
116 | }
117 | }
118 | }
119 | #pragma warning restore 414, 219
--------------------------------------------------------------------------------
/Examples/XmlHelperExample.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 30bf2162031183f46970f7b4a1c358af
3 | timeCreated: 1466344872
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016 Tobias Wehrum
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
--------------------------------------------------------------------------------
/LICENSE.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d07847ece7dacc24591ca0b7266b4180
3 | timeCreated: 1462727730
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/LINQExtensions.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 68eeefa7b7ec5cd40a04e24c328fbf43
3 | folderAsset: yes
4 | timeCreated: 1463231729
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/LINQExtensions/LINQExtensions.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 | using UnityEngine;
5 |
6 | namespace UnityUtilities
7 | {
8 | ///
9 | /// A collection of extension methods for , and arrays.
10 | ///
11 | public static class LINQExtensions
12 | {
13 | ///
14 | /// Takes a collection, generates values from the items and and returns the item with the lowest generated value.
15 | /// Useful for example to find the closest item. Reverse the generated values to find the item with the highest generated value.
16 | ///
17 | /// This returns the same as list.Where(element => predicateValue(valueConverter(element))).OrderBy(valueConverter).First(), but it
18 | /// a) doesn't order the whole list and
19 | /// b) doesn't call valueConverted more than once per element.
20 | ///
21 | /// The collection element type.
22 | /// The generated value type.
23 | /// The list of elements.
24 | /// The method to convert an element to a generated value used for ordering.
25 | /// A predicate testing whether the generated value is permitted. If true, the element is used; if false, the element is skipped.
26 | /// The first element by the generated value in order that succeeded the predicateValue test.
27 | public static TElement FirstByGeneratedValue(this IEnumerable list, Func valueConverter, Predicate predicateValue = null)
28 | where TValue : IComparable
29 | {
30 | var isFirstElement = true;
31 | TElement bestElement = default(TElement);
32 | TValue bestValue = default(TValue);
33 |
34 | // For each element...
35 | foreach (var element in list)
36 | {
37 | // Generate its value
38 | var value = valueConverter(element);
39 |
40 | // Check whether its value is permitted
41 | if ((predicateValue != null) && (!predicateValue(value)))
42 | continue;
43 |
44 | // If it's the first permitted element or better than the previous best element...
45 | if (isFirstElement || (value.CompareTo(bestValue) < 0))
46 | {
47 | // ...set it as the best element
48 | isFirstElement = false;
49 | bestElement = element;
50 | bestValue = value;
51 | }
52 | }
53 |
54 | return bestElement;
55 | }
56 |
57 | ///
58 | /// Returns the component nearest to the referencePoint and in minimum/maximum range.
59 | ///
60 | /// The collection element type. Needs to be a subclass of .
61 | /// The list of components.
62 | /// A reference point to get the distance from.
63 | /// Optional: The minimum distance.
64 | /// Optional: The maximum distance.
65 | /// The element nearest to the referencePoint and in minimum/maximum range.
66 | public static TElement Nearest(this IEnumerable list, Vector3 referencePoint, float minDistance = 0, float maxDistance = float.PositiveInfinity)
67 | where TElement : Component
68 | {
69 | // Create the predicate value from the min/max distance.
70 | Predicate predicateValue = null;
71 | if ((minDistance != 0) || !float.IsPositiveInfinity(maxDistance))
72 | {
73 | var minDistanceSq = minDistance * minDistance;
74 | var maxDistanceSq = maxDistance * maxDistance;
75 | predicateValue = (distanceSq => (distanceSq >= minDistanceSq) && (distanceSq <= maxDistanceSq));
76 | }
77 |
78 | // Return the nearest element to the reference point in the given range.
79 | return list.FirstByGeneratedValue(component => (component.transform.position - referencePoint).sqrMagnitude, predicateValue);
80 | }
81 |
82 | ///
83 | /// Shuffles an array in place.
84 | ///
85 | /// The array element type.
86 | /// The array to shuffle.
87 | public static void Shuffle(this T[] list)
88 | {
89 | var count = list.Length;
90 | for (int i1 = 0; i1 < count; i1++)
91 | {
92 | var i2 = UnityEngine.Random.Range(0, count);
93 | var element = list[i1];
94 | list[i1] = list[i2];
95 | list[i2] = element;
96 | }
97 | }
98 |
99 | ///
100 | /// Shuffles a list in place.
101 | ///
102 | /// The list element type.
103 | /// The list to shuffle.
104 | public static void Shuffle(this List list)
105 | {
106 | var count = list.Count;
107 | for (int i1 = 0; i1 < count; i1++)
108 | {
109 | var i2 = UnityEngine.Random.Range(0, count);
110 | var element = list[i1];
111 | list[i1] = list[i2];
112 | list[i2] = element;
113 | }
114 | }
115 |
116 | ///
117 | /// Returns a random element from the array.
118 | ///
119 | /// The array element type.
120 | /// The array to return an element from.
121 | /// A random element from the array.
122 | public static T RandomElement(this T[] array)
123 | {
124 | var index = UnityEngine.Random.Range(0, array.Length);
125 | return array[index];
126 | }
127 |
128 | ///
129 | /// Returns a random element from the list.
130 | ///
131 | /// The list element type.
132 | /// The list to return an element from.
133 | /// A random element from the list.
134 | public static T RandomElement(this List list)
135 | {
136 | var index = UnityEngine.Random.Range(0, list.Count);
137 | return list[index];
138 | }
139 |
140 | ///
141 | /// Calls ToString() on every element of the list, puts [encapsulate] directly before and after the result
142 | /// and then concatenates the results with [seperator] between them.
143 | ///
144 | /// The collection element type.
145 | /// The collection to concatenate.
146 | /// The seperator between entries.
147 | /// The string to put directly before and after every item.
148 | /// A string containing the ToString() results of all items.
149 | public static string ToOneLineString(this IEnumerable list, string separator = ", ", string encapsulate = "\"")
150 | {
151 | var useEncapsulate = encapsulate.Length > 0;
152 |
153 | var result = new StringBuilder();
154 | foreach (var element in list)
155 | {
156 | if (result.Length > 0)
157 | result.Append(separator);
158 |
159 | if (useEncapsulate)
160 | result.Append(encapsulate);
161 |
162 | result.Append(element);
163 |
164 | if (useEncapsulate)
165 | result.Append(encapsulate);
166 | }
167 |
168 | return result.ToString();
169 | }
170 | }
171 | }
--------------------------------------------------------------------------------
/LINQExtensions/LINQExtensions.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3c3902b08d7a97840a4f53d71841fd89
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 |
--------------------------------------------------------------------------------
/LINQExtensions/README.md:
--------------------------------------------------------------------------------
1 | # LINQExtensions
2 |
3 | A collection of extension methods for `IEnumerable`, `List` and arrays.
4 |
5 | ## Examples
6 |
7 | # RandomElement/Shuffle/ToOneLineString
8 |
9 | ```C#
10 | int[] items = new int[] {1, 2, 3, 4, 5};
11 |
12 | // Gets a random item
13 | Debug.Log(items.RandomElement());
14 |
15 | // Shuffles the array in place
16 | items.Shuffle();
17 |
18 | // Outputs the array on one line. Great for debugging.
19 | // Example output:
20 | // "3", "5", "2", "1", "4"
21 | Debug.Log(items.ToOneLineString());
22 | ```
23 |
24 | # Nearest
25 |
26 | ```C#
27 | public class LINQExtensionsExamples : MonoBehaviour
28 | {
29 | [SerializeField] Transform[] elements;
30 |
31 | void Update()
32 | {
33 | if (Input.GetMouseButtonDown(0))
34 | {
35 | // Get the x/y position of the click (for an orthographic camera)
36 | var mousePositionWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
37 |
38 | // Gets the element closest to the mouse click
39 | var nearestElement = elements.Nearest(mousePositionWorld);
40 |
41 | Debug.Log("Nearest element " + nearestElement.name + " at position " + nearestElement.position);
42 | }
43 | }
44 | }
45 | ```
46 |
47 | ## Dependencies
48 |
49 | None.
--------------------------------------------------------------------------------
/LINQExtensions/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e787f75ca3f464843a5c94d80d660b97
3 | timeCreated: 1463270294
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/MathHelper.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 08400f198e74a804e8df43d5dd377179
3 | folderAsset: yes
4 | timeCreated: 1477146251
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/MathHelper/MathHelper.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 | using Random = UnityEngine.Random;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// The MathHelper contains methods to help with mapping and angles and a really nifty method for framerate-independent eased lerping.
8 | ///
9 | public static class MathHelper
10 | {
11 | #region Mapping
12 |
13 | ///
14 | /// Maps a value from [sourceFrom..sourceTo] to [targetFrom..targetTo] with clamping.
15 | ///
16 | /// This is basically Mathf.Lerp(targetFrom, targetTo, Mathf.InverseLerp(sourceFrom, sourceTo, sourceValue)).
17 | ///
18 | /// The value in the range of [sourceFrom..sourceTo]. Will be clamped if not in that range.
19 | /// The lower end of the source range.
20 | /// The higher end of the source range.
21 | /// The lower end of the target range.
22 | /// The higher end of the target range.
23 | /// The mapped value.
24 | public static float MapClamped(float sourceValue, float sourceFrom, float sourceTo, float targetFrom, float targetTo)
25 | {
26 | var sourceRange = sourceTo - sourceFrom;
27 | var targetRange = targetTo - targetFrom;
28 | var percent = Mathf.Clamp01((sourceValue - sourceFrom) / sourceRange);
29 | return targetFrom + targetRange * percent;
30 | }
31 |
32 | ///
33 | /// Applies a deadzone [-deadzone..deadzone] in which the value will be set to 0.
34 | ///
35 | /// The joystick value.
36 | /// A value between for which all results [-deadzone..deadzone] will be set to 0.
37 | /// If this is true, the values between [-1..-deadzone] and [deadzone..1] will be mapped to [-1..0] and [0..1] respectively.
38 | /// The result value between [-1..1].
39 | public static float ApplyJoystickDeadzone(float value, float deadzone, bool fullRangeBetweenDeadzoneAndOne = false)
40 | {
41 | if (Mathf.Abs(value) <= deadzone)
42 | return 0;
43 |
44 | if (fullRangeBetweenDeadzoneAndOne && (deadzone > 0f))
45 | {
46 | if (value < 0)
47 | {
48 | return MapClamped(value, -1f, -deadzone, -1f, 0f);
49 | }
50 | else
51 | {
52 | return MapClamped(value, deadzone, 1f, 0f, 1f);
53 | }
54 | }
55 |
56 | return value;
57 | }
58 |
59 | ///
60 | /// Maps a joystick input from [sourceFrom..sourceTo] to [-1..1] with clamping.
61 | /// Applies a deadzone [-deadzone..deadzone] in which the value will be set to 0.
62 | ///
63 | /// The value in the range of [sourceFrom..sourceTo]. Will be clamped if not in that range.
64 | /// The lower end of the source range.
65 | /// The higher end of the source range.
66 | /// A value between 0 and 1 for which all results [-deadzone..deadzone] will be set to 0.
67 | /// If this is true, the values between [-1..-deadzone] and [deadzone..1] will be mapped to [-1..0] and [0..1] respectively.
68 | /// The result value between [-1..1].
69 | public static float MapClampedJoystick(float sourceValue, float sourceFrom, float sourceTo, float deadzone = 0f, bool fullRangeBetweenDeadzoneAndOne = false)
70 | {
71 | var percent = MapClamped(sourceValue, sourceFrom, sourceTo, -1, 1);
72 |
73 | if (deadzone > 0)
74 | percent = ApplyJoystickDeadzone(percent, deadzone, fullRangeBetweenDeadzoneAndOne);
75 |
76 | return percent;
77 | }
78 |
79 | #endregion
80 |
81 | #region Angles
82 |
83 | ///
84 | /// Returns the closer center between two angles.
85 | ///
86 | /// The first angle.
87 | /// The second angle.
88 | /// The closer center.
89 | public static float GetCenterAngleDeg(float angle1, float angle2)
90 | {
91 | return angle1 + Mathf.DeltaAngle(angle1, angle2) / 2f;
92 | }
93 |
94 | ///
95 | /// Normalizes an angle between 0 (inclusive) and 360 (exclusive).
96 | ///
97 | /// The input angle.
98 | /// The result angle.
99 | public static float NormalizeAngleDeg360(float angle)
100 | {
101 | while (angle < 0)
102 | angle += 360;
103 |
104 | if (angle >= 360)
105 | angle %= 360;
106 |
107 | return angle;
108 | }
109 |
110 | ///
111 | /// Normalizes an angle between -180 (inclusive) and 180 (exclusive).
112 | ///
113 | /// The input angle.
114 | /// The result angle.
115 | public static float NormalizeAngleDeg180(float angle)
116 | {
117 | while (angle < -180)
118 | angle += 360;
119 |
120 | while (angle >= 180)
121 | angle -= 360;
122 |
123 | return angle;
124 | }
125 |
126 | #endregion
127 |
128 | #region Framerate-Independent Lerping
129 |
130 | ///
131 | /// Provides a framerate-independent t for lerping towards a target.
132 | ///
133 | /// Example:
134 | ///
135 | /// currentValue = Mathf.Lerp(currentValue, 1f, MathHelper.EasedLerpFactor(0.75f);
136 | ///
137 | /// will cover 75% of the remaining distance between currentValue and 1 each second.
138 | ///
139 | /// There are essentially two ways of lerping a value over time: linear (constant speed) or
140 | /// eased (e.g. getting slower the closer you are to the target, see http://easings.net.)
141 | ///
142 | /// For linear lerping (and most of the easing functions), you need to track the start and end
143 | /// positions and the time that elapsed.
144 | ///
145 | /// Calling something like
146 | ///
147 | /// currentValue = Mathf.Lerp(currentValue, 1f, 0.95f);
148 | ///
149 | /// every frame provides an easy way of eased lerping without tracking elapsed time or the
150 | /// starting value, but since it's called every frame, the actual traversed distance per
151 | /// second changes the higher the framerate is.
152 | ///
153 | /// This function replaces the lerp T to make it framerate-independent and easier to estimate.
154 | ///
155 | /// For more info, see https://www.scirra.com/blog/ashley/17/using-lerp-with-delta-time.
156 | ///
157 | /// How much % the lerp should cover per second.
158 | /// How much time passed since the last call.
159 | /// The framerate-independent lerp t.
160 | public static float EasedLerpFactor(float factor, float deltaTime = 0f)
161 | {
162 | if (deltaTime == 0f)
163 | deltaTime = Time.deltaTime;
164 |
165 | return 1 - Mathf.Pow(1 - factor, deltaTime);
166 | }
167 |
168 | ///
169 | /// Framerate-independent eased lerping to a target value, slowing down the closer it is.
170 | ///
171 | /// If you call
172 | ///
173 | /// currentValue = MathHelper.EasedLerp(currentValue, 1f, 0.75f);
174 | ///
175 | /// each frame (e.g. in Update()), starting with a currentValue of 0, then after 1 second
176 | /// it will be approximately 0.75 - which is 75% of the way between 0 and 1.
177 | ///
178 | /// Adjusting the target or the percentPerSecond between calls is also possible.
179 | ///
180 | /// The current value.
181 | /// The target value.
182 | /// How much of the distance between current and target should be covered per second?
183 | /// How much time passed since the last call.
184 | /// The interpolated value from current to target.
185 | public static float EasedLerp(float current, float target, float percentPerSecond, float deltaTime = 0f)
186 | {
187 | var t = EasedLerpFactor(percentPerSecond, deltaTime);
188 | return Mathf.Lerp(current, target, t);
189 | }
190 |
191 | #endregion
192 | }
193 | }
--------------------------------------------------------------------------------
/MathHelper/MathHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 479e0b35c08d2124a92e7b31e5685665
3 | timeCreated: 1465253549
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/MathHelper/README.md:
--------------------------------------------------------------------------------
1 | # MathHelper
2 |
3 | The MathHelper contains methods to help with mapping and angles and a really nifty method for framerate-independent eased lerping.
4 |
5 | ## Examples
6 |
7 | ### Framerate-Independent Eased Lerping
8 |
9 | There are essentially two ways of lerping a value over time: linear (constant speed) or eased (e.g. getting slower the closer you are to the target, see http://easings.net.)
10 |
11 | For linear lerping (and most of the easing functions), you need to track the start and end positions and the time that elapsed.
12 |
13 | Calling something like `currentValue = Mathf.Lerp(currentValue, 1f, 0.95f);` every frame provides an easy way of eased lerping without tracking elapsed time or the starting value, but since it's called every frame, the actual traversed distance per second changes the higher the framerate is.
14 |
15 | EasedLerpFactor replaces the lerp parameter t to make it framerate-independent and easier to estimate.
16 |
17 | You can find more information about the formula used [here](https://www.scirra.com/blog/ashley/17/using-lerp-with-delta-time).
18 |
19 | You can use `MathHelper.EasedLerpFactor` to get the t used for a lerp or call `MathHelper.EasedLerp`, `UnityHelper.EasedLerpVector2`, `UnityHelper.EasedLerpVector3`, `UnityHelper.EasedLerpVector4` or `UnityHelper.EasedLerpColor` directly.
20 |
21 | 
22 |
23 | ```C#
24 | void Update()
25 | {
26 | // Get the world position of the mouse pointer
27 | Vector3 mousePositionWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
28 | mousePositionWorld.z = 0f;
29 |
30 | // Set the runner position to the mouse pointer
31 | runner.position = mousePositionWorld;
32 |
33 | // Move the follower 75% of the remaining distance to the runner per second
34 | follower.position = UnityHelper.EasedLerpVector3(follower.position, runner.position, 0.75f);
35 |
36 | // ...which is the same as:
37 |
38 | //float t = MathHelper.EasedLerpFactor(0.75f);
39 | //follower.position = Vector3.Lerp(follower.position, mousePositionWorld, t);
40 | }
41 | ```
42 |
43 | ### Mapping
44 |
45 | ```C#
46 | // Maps 10 from [-250..250] to [0..10]
47 | Debug.Log(MathHelper.MapClamped(10f, -250f, 250f, 0f, 10f)); // => 5.2
48 |
49 | // Applies a deadzone to a joystick input (positive and negative) to make sure that
50 | // little imperfections in the stick resting position don't make the character move
51 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.1f, 0.2f)); // => 0
52 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.2f, 0.2f)); // => 0
53 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.21f, 0.2f)); // => 0.21
54 | Debug.Log(MathHelper.ApplyJoystickDeadzone(0.3f, 0.2f)); // => 0.3
55 | Debug.Log(MathHelper.ApplyJoystickDeadzone(1f, 0.2f)); // => 1
56 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.1f, 0.2f)); // => 0
57 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.2f, 0.2f)); // => 0
58 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.21f, 0.2f)); // => -0.21
59 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-0.3f, 0.2f)); // => -0.3
60 | Debug.Log(MathHelper.ApplyJoystickDeadzone(-1f, 0.2f)); // => -1
61 | ```
62 |
63 | ### Angles
64 |
65 | ```C#
66 | // Gets the center angle between two angles
67 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, 160f)); // => 90
68 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, 220f)); // => -60
69 | Debug.Log(MathHelper.GetCenterAngleDeg(20f, -140f)); // => -60
70 |
71 | // Normalizes an angle between 0 (inclusive) and 360 (exclusive).
72 | Debug.Log(MathHelper.NormalizeAngleDeg360(-180f)); // => 180
73 | Debug.Log(MathHelper.NormalizeAngleDeg360(180f)); // => 180
74 | Debug.Log(MathHelper.NormalizeAngleDeg360(0f)); // => 0
75 | Debug.Log(MathHelper.NormalizeAngleDeg360(360f)); // => 0
76 | Debug.Log(MathHelper.NormalizeAngleDeg360(340f)); // => 340
77 |
78 | // Normalizes an angle between -180 (inclusive) and 180 (exclusive).
79 | Debug.Log(MathHelper.NormalizeAngleDeg180(-180f)); // => -180
80 | Debug.Log(MathHelper.NormalizeAngleDeg180(180f)); // => -180
81 | Debug.Log(MathHelper.NormalizeAngleDeg180(0f)); // => 0
82 | Debug.Log(MathHelper.NormalizeAngleDeg180(360f)); // => 0
83 | Debug.Log(MathHelper.NormalizeAngleDeg180(340f)); // => -20
84 | ```
85 |
86 | ## Dependencies
87 |
88 | None.
--------------------------------------------------------------------------------
/MathHelper/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 080955fafb9c14244a8daa5a727aefe5
3 | timeCreated: 1477157197
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/MeshCreator.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 458e81fc1d8b9314aad15e31165ca9d0
3 | folderAsset: yes
4 | timeCreated: 1467495335
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/MeshCreator/MeshCreator.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// Stores the vertex/triangle data of a mesh in easily modifiable form - which can
8 | /// then be used to actually create or update a mesh.
9 | ///
10 | public class MeshCreator
11 | {
12 | ///
13 | /// The triangles of the mesh.
14 | ///
15 | List meshTriangles;
16 |
17 | ///
18 | /// The vertices of a mesh.
19 | ///
20 | List meshVertices;
21 |
22 | ///
23 | /// A temporary array of the vertex positions for filling the mesh.
24 | ///
25 | Vector3[] tempVertices;
26 |
27 | ///
28 | /// A temporary array of the vertex normals for filling the mesh.
29 | ///
30 | Vector3[] tempNormals;
31 |
32 | ///
33 | /// A temporary array of the vertex UV coordinates for filling the mesh.
34 | ///
35 | Vector2[] tempUV;
36 |
37 | ///
38 | /// A temporary array of the vertex colors for filling the mesh.
39 | ///
40 | Color[] tempColors;
41 |
42 | ///
43 | /// A temporary array of the triangle vertex indizes for filling the mesh.
44 | ///
45 | int[] tempTriangles;
46 |
47 | ///
48 | /// The amount of registered vertices.
49 | ///
50 | public int MeshVerticesCount
51 | {
52 | get { return meshVertices.Count; }
53 | }
54 |
55 | ///
56 | /// The registered vertices. Use to add a vertex.
57 | /// Content of existing vertices can be freely updated.
58 | ///
59 | public List MeshVertices
60 | {
61 | get { return meshVertices; }
62 | }
63 |
64 | ///
65 | /// The registered triangles. Use or
66 | /// to add triangles.
67 | ///
68 | public List MeshTriangles
69 | {
70 | get { return meshTriangles; }
71 | }
72 |
73 | ///
74 | /// Creates a new MeshCreator.
75 | ///
76 | /// Used to create the initial size of the MeshTriangles list.
77 | /// Used to set the initial size of the MeshVertices list.
78 | public MeshCreator(int estimatedTriangleCount, int estimatedVertexCount)
79 | {
80 | meshTriangles = new List(estimatedTriangleCount);
81 | meshVertices = new List(estimatedVertexCount);
82 | }
83 |
84 | ///
85 | /// Clear the triangles and vertices.
86 | ///
87 | public void Clear()
88 | {
89 | meshTriangles.Clear();
90 |
91 | for (var i = 0; i < meshVertices.Count; i++)
92 | meshVertices[i].VertexIndex = -1;
93 |
94 | meshVertices.Clear();
95 | }
96 |
97 | ///
98 | /// Adds a vertex to the MeshCreator and assigns it a VertexIndex.
99 | /// If it already has a VertexIndex, this method does nothing.
100 | ///
101 | /// The vertex to be added.
102 | public MeshVertex AddVertex(MeshVertex vertex)
103 | {
104 | if (vertex.VertexIndex != -1)
105 | return vertex;
106 |
107 | vertex.VertexIndex = meshVertices.Count;
108 | meshVertices.Add(vertex);
109 | return vertex;
110 | }
111 |
112 | ///
113 | /// Adds a triangle to the MeshCreator. Adds the vertices to the MeshCreator
114 | /// if they aren't already added.
115 | ///
116 | /// The first vertex in clockwise order.
117 | /// The second vertex in clockwise order.
118 | /// The third vertex in clockwise order.
119 | /// The created triangle.
120 | public MeshTriangle AddTriangle(MeshVertex a, MeshVertex b, MeshVertex c)
121 | {
122 | AddVertex(a);
123 | AddVertex(b);
124 | AddVertex(c);
125 |
126 | var triangle = new MeshTriangle(a, b, c);
127 | meshTriangles.Add(triangle);
128 | return triangle;
129 | }
130 |
131 | ///
132 | /// Adds two triangles forming a quad to the MeshCreator. Adds the vertices
133 | /// to the MeshCreator if they aren't already added.
134 | ///
135 | /// The first vertex in clockwise order.
136 | /// The second vertex in clockwise order.
137 | /// The third vertex in clockwise order.
138 | /// The fourth vertex in clockwise order.
139 | public void AddQuad(MeshVertex a, MeshVertex b, MeshVertex c, MeshVertex d)
140 | {
141 | AddTriangle(a, b, c);
142 | AddTriangle(a, c, d);
143 | }
144 |
145 | ///
146 | /// Creates a new mesh and fills it via .
147 | ///
148 | /// The filled mesh.
149 | public Mesh CreateMesh()
150 | {
151 | var mesh = new Mesh();
152 | mesh.MarkDynamic();
153 | return UpdateMesh(mesh);
154 | }
155 |
156 | ///
157 | /// Takes an existing mesh previously created with or
158 | /// and fills it with the data from this MeshCreator.
159 | ///
160 | /// The mesh to be updated.
161 | /// Should the vertex positions be updated?
162 | /// Should the vertex normals be updated?
163 | /// Should the vertex colors be updated?
164 | /// Should the UVs be updated?
165 | ///
166 | /// Should the triangle composition be updated? This only needs to be called when
167 | /// you assigned new vertices to triangles, not when vertices changed their data
168 | /// internally. Calling this also triggers updating every other property.
169 | ///
170 | /// The filled mesh.
171 | public Mesh UpdateMesh(Mesh mesh, bool updatePositions = true, bool updateNormals = true, bool updateColors = true, bool updateUVs = true, bool updateTriangles = true)
172 | {
173 | if (updateTriangles)
174 | {
175 | mesh.Clear();
176 | updatePositions = true;
177 | updateNormals = true;
178 | updateColors = true;
179 | updateUVs = true;
180 | }
181 |
182 | var verticesCount = meshVertices.Count;
183 | if ((tempVertices == null) || (tempVertices.Length != verticesCount))
184 | {
185 | tempVertices = new Vector3[verticesCount];
186 | tempNormals = new Vector3[verticesCount];
187 | tempUV = new Vector2[verticesCount];
188 | tempColors = new Color[verticesCount];
189 | }
190 |
191 | for (var i = 0; i < verticesCount; i++)
192 | {
193 | var meshVertex = meshVertices[i];
194 |
195 | if (updatePositions)
196 | tempVertices[i] = meshVertex.Position;
197 |
198 | if (updateNormals)
199 | tempNormals[i] = meshVertex.Normal;
200 |
201 | if (updateColors)
202 | tempColors[i] = meshVertex.Color;
203 |
204 | if (updateUVs)
205 | tempUV[i] = meshVertex.UV;
206 | }
207 |
208 | if (updatePositions)
209 | mesh.vertices = tempVertices;
210 |
211 | if (updateColors)
212 | mesh.colors = tempColors;
213 |
214 | if (updateNormals)
215 | mesh.normals = tempNormals;
216 |
217 | if (updateUVs)
218 | mesh.uv = tempUV;
219 |
220 | if (updateTriangles)
221 | {
222 | var trianglesCount = meshTriangles.Count;
223 | var triangleArrayLength = trianglesCount * 3;
224 |
225 | if ((tempTriangles == null) || (tempTriangles.Length != triangleArrayLength))
226 | tempTriangles = new int[triangleArrayLength];
227 |
228 | for (var i = 0; i < trianglesCount; i++)
229 | {
230 | var meshTriangleVertices = meshTriangles[i].MeshVertices;
231 | for (var j = 0; j < 3; j++)
232 | {
233 | tempTriangles[i * 3 + j] = meshTriangleVertices[j].VertexIndex;
234 | }
235 | }
236 |
237 | mesh.triangles = tempTriangles;
238 | }
239 |
240 | if (updatePositions)
241 | mesh.RecalculateBounds();
242 |
243 | return mesh;
244 | }
245 | }
246 | }
--------------------------------------------------------------------------------
/MeshCreator/MeshCreator.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3246b9e96565833498f07158c6df11be
3 | timeCreated: 1467495335
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/MeshCreator/MeshTriangle.cs:
--------------------------------------------------------------------------------
1 | namespace UnityUtilities
2 | {
3 | ///
4 | /// A triangle, consisting of three .
5 | /// Used in a . Cannot be part of more than one MeshCreator.
6 | ///
7 | public class MeshTriangle
8 | {
9 | ///
10 | /// The three vertices that make up this triangle in clockwise order.
11 | ///
12 | public MeshVertex[] MeshVertices { get; private set; }
13 |
14 | ///
15 | /// Creates a new triangle.
16 | ///
17 | /// The first vertex in clockwise order.
18 | /// The second vertex in clockwise order.
19 | /// The third vertex in clockwise order.
20 | public MeshTriangle(MeshVertex a, MeshVertex b, MeshVertex c)
21 | {
22 | MeshVertices = new[] {a, b, c};
23 | }
24 |
25 | ///
26 | /// Convenience method to update all three vertices at once.
27 | ///
28 | /// The first vertex in clockwise order.
29 | /// The second vertex in clockwise order.
30 | /// The third vertex in clockwise order.
31 | public void Update(MeshVertex a, MeshVertex b, MeshVertex c)
32 | {
33 | MeshVertices[0] = a;
34 | MeshVertices[1] = b;
35 | MeshVertices[2] = c;
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/MeshCreator/MeshTriangle.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 87e3e75024f9b5f449c84e56724c6b4b
3 | timeCreated: 1467495335
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/MeshCreator/MeshVertex.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// A vertex in a . Can -and should!- be shared by multiple triangles.
7 | /// Used in a . Cannot be part of more than one MeshCreator.
8 | ///
9 | public class MeshVertex
10 | {
11 | ///
12 | /// The local position of the vertex inside the mesh.
13 | ///
14 | public Vector3 Position { get; set; }
15 |
16 | ///
17 | /// The normal of the vertex.
18 | ///
19 | public Vector3 Normal { get; set; }
20 |
21 | ///
22 | /// The color of the vertex.
23 | ///
24 | public Color Color { get; set; }
25 |
26 | ///
27 | /// The first UV coordinates of the vertex.
28 | ///
29 | public Vector2 UV { get; set; }
30 |
31 | ///
32 | /// The index of this vertex inside the MeshCreator.MeshVertices list. Automatically assigned
33 | /// by MeshCreator.AddVertex(), MeshCreator.AddTriangle() and MeshCreator.AddQuad().
34 | /// Used to identify the vertex for actually creating the Mesh in MeshCreator.UpdateMesh().
35 | ///
36 | public int VertexIndex { get; internal set; }
37 |
38 | ///
39 | /// Creates a new MeshVertex.
40 | ///
41 | /// The local position of the vertex inside the mesh.
42 | /// The normal of the vertex.
43 | /// The color of the vertex.
44 | /// The first UV coordinates of the vertex.
45 | public MeshVertex(Vector3 position, Vector3 normal = default(Vector3), Color color = new Color(), Vector2 uv = new Vector2())
46 | {
47 | Position = position;
48 | Normal = normal;
49 | Color = color;
50 | UV = uv;
51 | VertexIndex = -1;
52 | }
53 | }
54 | }
--------------------------------------------------------------------------------
/MeshCreator/MeshVertex.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7017d87be61c0fe4ba4f573f38980a23
3 | timeCreated: 1467495335
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/MeshCreator/README.md:
--------------------------------------------------------------------------------
1 | # MeshCreator
2 |
3 | Stores the vertex/triangle data of a mesh in easily modifiable form - which can then be used to actually create or update a mesh.
4 |
5 | ## Example
6 |
7 | ```C#
8 | [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))]
9 | public class MeshCreatorExample : MonoBehaviour
10 | {
11 | MeshCreator meshCreator;
12 | MeshFilter meshFilter;
13 |
14 | void Awake()
15 | {
16 | // We will create a cube, so we set 12 triangles (6 sides á 2 triangles) and 8 vertices.
17 | // To do a cube with proper shading, we should actually create 4 vertices per side and have
18 | // normals pointing outwards, but for this example let's keep it simple.
19 | meshCreator = new MeshCreator(12, 8);
20 |
21 | // Create the vertices
22 | var behindUpperLeft = new MeshVertex(new Vector3(-1, 1, 1), Vector3.zero, Color.white);
23 | var behindUpperRight = new MeshVertex(new Vector3(1, 1, 1), Vector3.zero, Color.white);
24 | var behindLowerLeft = new MeshVertex(new Vector3(-1, -1, 1), Vector3.zero, Color.white);
25 | var behindLowerRight = new MeshVertex(new Vector3(1, -1, 1), Vector3.zero, Color.white);
26 | var frontUpperLeft = new MeshVertex(new Vector3(-1, 1, -1), Vector3.zero, Color.white);
27 | var frontUpperRight = new MeshVertex(new Vector3(1, 1, -1), Vector3.zero, Color.white);
28 | var frontLowerLeft = new MeshVertex(new Vector3(-1, -1, -1), Vector3.zero, Color.white);
29 | var frontLowerRight = new MeshVertex(new Vector3(1, -1, -1), Vector3.zero, Color.white);
30 |
31 | // Create the quads
32 | meshCreator.AddQuad(frontUpperLeft, frontUpperRight, frontLowerRight, frontLowerLeft);
33 | meshCreator.AddQuad(behindUpperRight, behindUpperLeft, behindLowerLeft, behindLowerRight);
34 | meshCreator.AddQuad(frontUpperRight, behindUpperRight, behindLowerRight, frontLowerRight);
35 | meshCreator.AddQuad(frontUpperLeft, frontLowerLeft, behindLowerLeft, behindUpperLeft);
36 | meshCreator.AddQuad(frontUpperLeft, behindUpperLeft, behindUpperRight, frontUpperRight);
37 | meshCreator.AddQuad(frontLowerLeft, frontLowerRight, behindLowerRight, behindLowerLeft);
38 |
39 | // Create a new mesh and set it in the mesh filter
40 | meshFilter = GetComponent();
41 | meshFilter.sharedMesh = meshCreator.CreateMesh();
42 | meshFilter.sharedMesh.RecalculateNormals();
43 | }
44 |
45 | void Update()
46 | {
47 | // Make the vertices wobble independently
48 | for (int i = 0; i < meshCreator.MeshVerticesCount; i++)
49 | {
50 | MeshVertex meshVertex = meshCreator.MeshVertices[i];
51 | float scale = Mathf.Lerp(2f, 4f, Mathf.Abs(Mathf.Cos(Time.time + i / 4f)));
52 | meshVertex.Position = meshVertex.Position.normalized * scale;
53 | }
54 |
55 | // Update the mesh
56 | meshCreator.UpdateMesh(meshFilter.sharedMesh);
57 | }
58 | }
59 | ```
60 |
61 | ## Dependencies
62 |
63 | None.
--------------------------------------------------------------------------------
/MeshCreator/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7615b80d7d59f42438b505c1da0b9986
3 | timeCreated: 1467505581
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/NoiseOutputValue.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a5375a70fdbb70d47a640acffd4367b5
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/NoiseOutputValue/NoiseOutputValue.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 | using Random = UnityEngine.Random;
4 |
5 | namespace UnityUtilities
6 | {
7 | ///
8 | /// Provides a fluidly changing output value using .
9 | ///
10 | [Serializable]
11 | public class NoiseOutputValue
12 | {
13 | ///
14 | /// The range of the output value.
15 | ///
16 | [Tooltip("The range of the output value.")]
17 | [SerializeField] RangeFloat range = new RangeFloat(0f, 1f);
18 |
19 | ///
20 | /// How fast to scroll over the perlin noise.
21 | ///
22 | [Tooltip("How fast to scroll over the perlin noise.")]
23 | [SerializeField] float speed = 0.1f;
24 |
25 | ///
26 | /// Has the random seed already been initialized?
27 | ///
28 | bool initialized;
29 |
30 | ///
31 | /// The scrolling time used as x for the 2d perlin function.
32 | ///
33 | float perlinTime;
34 |
35 | ///
36 | /// The seed used as y for the 2d perlin function. This scrolls too, but very slowly, to avoid early looping.
37 | ///
38 | float perlinSeed;
39 |
40 | ///
41 | /// The current output value between range.from and range.to.
42 | ///
43 | public float OutputValue { get; private set; }
44 |
45 | ///
46 | /// The range of the output value.
47 | ///
48 | public RangeFloat Range { get { return range; } }
49 |
50 | ///
51 | /// The range of the output speed.
52 | ///
53 | public float Speed { get { return speed; } }
54 |
55 | ///
56 | /// Updates the . Should be called once per frame before using for the first time.
57 | ///
58 | /// Optional: Provide the deltaTime for the scrolling if it isn't Time.deltaTime.
59 | public void Progress(float? deltaTime = null)
60 | {
61 | if (!initialized)
62 | {
63 | initialized = true;
64 |
65 | // Gets a random seed to use as y for the 2d perlin function.
66 | perlinSeed = Random.value * 10f;
67 | }
68 |
69 | if (deltaTime == null)
70 | deltaTime = Time.deltaTime;
71 |
72 | var delta = deltaTime.Value * speed;
73 |
74 | // Scroll forward in time.
75 | perlinTime += delta;
76 |
77 | // Scroll very slowing through the seed to avoid looping at PerlinTime values of 10 and higher.
78 | // It will still loop, but only after
79 | perlinSeed += delta / 100f;
80 |
81 | // Update the output value.
82 | OutputValue = range.Lerp(Mathf.PerlinNoise(perlinTime, perlinSeed));
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/NoiseOutputValue/NoiseOutputValue.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 13a0a570d62aefd4bb1bdd3645b36f78
3 | timeCreated: 1462647054
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/NoiseOutputValue/README.md:
--------------------------------------------------------------------------------
1 | # NoiseOutputValue
2 |
3 | Enter a range and a speed in the editor and you will get an output value in that ranges that fluctuates fluently over time using [Perlin Noise](http://docs.unity3d.com/ScriptReference/Mathf.PerlinNoise.html).
4 |
5 | ## Example
6 |
7 | 
8 |
9 | ```C#
10 | public class NoiseOutputValueExample : MonoBehaviour
11 | {
12 | [SerializeField] NoiseOutputValue positionNoise;
13 | [SerializeField] Transform sphere;
14 |
15 | private void Update()
16 | {
17 | // Updates the value with Time.deltaTime*speed
18 | positionNoise.Update();
19 |
20 | // Sets the y position at the current output value
21 | sphere.transform.position = new Vector3(0, positionNoise.OutputValue, 0f);
22 | }
23 | }
24 | ```
25 |
26 | ## Dependencies
27 |
28 | * [Range](https://github.com/TobiasWehrum/unity-utilities/tree/master/Range)
--------------------------------------------------------------------------------
/NoiseOutputValue/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 7280d3c5926236545ad43635ad87a21f
3 | timeCreated: 1462746256
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Tobi's Unity Utilities
2 |
3 | Over the years, I've worked on a lot of [projects](http://dragonlab.de/portfolio) and [game jam prototypes](http://blog.dragonlab.de/tag/unity) with Unity3D and there are some pieces of code that I've needed time and time again. I'm sharing them here in the hopes that they are useful for you too!
4 |
5 | Everything is released under the [MIT License](https://opensource.org/licenses/MIT).
6 |
7 | If you find any bugs or have suggestions, please add an [Issue](https://github.com/TobiasWehrum/unity-utilities/issues) here or send me a mail at Tobias.Wehrum@dragonlab.de.
8 |
9 | ## Overview
10 | * [Countdown](https://github.com/TobiasWehrum/unity-utilities/tree/master/Countdown): Useful for things like cooldowns or spawn delays. It is also helpful for tweening things by using the `PercentElapsed` property.
11 | * [EditorHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/EditorHelper): Gets the `[Tooltip]` attribute content of fields for editor classes. Might get more helper methods in the future.
12 | * [LINQExtensions](https://github.com/TobiasWehrum/unity-utilities/tree/master/LINQExtensions): A collection of extension methods for `IEnumerable`, `List` and arrays.
13 | * [MathHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/MathHelper): Helper methods for framerate-independent eased lerping, mapping and angles.
14 | * [MeshCreator](https://github.com/TobiasWehrum/unity-utilities/tree/master/MeshCreator): Makes it more convenient to create meshes via code.
15 | * [NoiseOutputValue](https://github.com/TobiasWehrum/unity-utilities/tree/master/NoiseOutputValue): Enter a range and a speed in the editor, get an output value that fluctuates over time using [Perlin Noise](http://docs.unity3d.com/ScriptReference/Mathf.PerlinNoise.html).
16 | * [RandomBag](https://github.com/TobiasWehrum/unity-utilities/tree/master/RandomBag): A `RandomBag` gives you random items from a group while ensuring that in a certain interval every item was given back the same number of times.
17 | * [Range](https://github.com/TobiasWehrum/unity-utilities/tree/master/Range): Editable data types that take an `int`/`float` range. Used for things like "Spawn 2 to 4 enemies."
18 | * [RollingArray](https://github.com/TobiasWehrum/unity-utilities/tree/master/RollingArray): Collection that keeps the last x elements that are added to it.
19 | * [Singleton](https://github.com/TobiasWehrum/unity-utilities/tree/master/Singleton): Allows easy and convenient creation of a Singleton. Optionally makes a Singleton persist between scenes while ensuring that only one exists.
20 | * [UnityHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/UnityHelper): Contains a plethora of useful extensions and helpers for Transform, GameObject, Vector2/3/4, Rect and more.
21 | * [XmlHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/XmlHelper): Serializes data to XML strings and makes accessing optional element content and attributes in general XMLs easier.
22 |
23 | ## Usage
24 |
25 | To use the scripts, just drop them into the Assets folder of your projects. Or better yet, make an "Assets/Extensions/TobisUnityUtitilites" folder and drop them there. Hurray for proper organisation.
26 |
27 | You can also just use selected scripts, but you should check the "Dependencies" section in the respective folder to make sure you copy everything you need.
28 |
29 | ## Documentation
30 |
31 | The class documentation is available [here](http://tobiaswehrum.github.io/UnityUtilities/html/annotated.html).
32 |
33 | ## Changelog
34 | * 2016-10-23: Fixed bugs/improved [Singleton](https://github.com/TobiasWehrum/unity-utilities/tree/master/Singleton). Added EasedLerp methods for float in [MathHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/MathHelper) and Vector2, Vector3 and Color in [UnityHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/UnityHelper). Added CalculateCentroid in [UnityHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/UnityHelper) for arrays/lists of Vector2/3/4.
35 | * 2016-10-22: Added [MathHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/MathHelper). Added randomization helper methods to [UnityHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/UnityHelper).
36 | * 2016-07-03: Added [MeshCreator](https://github.com/TobiasWehrum/unity-utilities/tree/master/MeshCreator).
37 | * 2016-06-19: Added [XmlHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/XmlHelper).
38 | * 2016-06-08: Added [UnityHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/UnityHelper).
39 | * 2016-06-05: Added [EditorHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/EditorHelper) and [RollingArray](https://github.com/TobiasWehrum/unity-utilities/tree/master/RollingArray). Added `[Tooltip]` for `NoiseOutputValue` and edited the existing `PropertyDrawer` to use tooltips.
40 | * 2016-05-15: Added [LINQExtensions](https://github.com/TobiasWehrum/unity-utilities/tree/master/LINQExtensions) and [RandomBag](https://github.com/TobiasWehrum/unity-utilities/tree/master/RandomBag).
41 | * 2016-05-09: Added the [class documentation website](http://tobiaswehrum.github.io/UnityUtilities/html/annotated.html).
42 | * 2016-05-08: Added [Countdown](https://github.com/TobiasWehrum/unity-utilities/tree/master/Countdown), [NoiseOutputValue](https://github.com/TobiasWehrum/unity-utilities/tree/master/NoiseOutputValue), [Range](https://github.com/TobiasWehrum/unity-utilities/tree/master/Range) and [Singleton](https://github.com/TobiasWehrum/unity-utilities/tree/master/Singleton).
43 | * 2017-09-26: Removed .gitignore. Update note: This will break any scene you use example scripts in and might cause one-time .meta conflicts if you track your projects with git and didn't remove the .gitignore yourself. I'm sorry.
--------------------------------------------------------------------------------
/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: eff04722ac3129d42bfdb29011dc918d
3 | timeCreated: 1462727730
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/RandomBag.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 07f4be29056efd74a915c53e4b50707d
3 | folderAsset: yes
4 | timeCreated: 1463231729
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/RandomBag/README.md:
--------------------------------------------------------------------------------
1 | # RandomBag
2 |
3 | A RandomBag ensures that per interval [fillings * itemCount], every different item in it will be given back [fillings] times. Once the bag is empty, it is automatically refilled, either from a fixed array or by calling a delegate.
4 |
5 | An example for that is used in [some implementations of Tetris](http://tetris.wikia.com/wiki/Random_Generator). The bag is filled with one instance (fillings=1) of each of the seven different pieces. Every time the next piece is needed, a random one is taken out of the bag until the bag is empty. That way, any two pieces are never longer than 14 pulls apart - and even that is only the case if the first and the last piece in the bag are the same one.
6 |
7 | ## Example
8 |
9 | ```C#
10 | public class RandomBagExample : MonoBehaviour
11 | {
12 | private enum TetrisPiece
13 | {
14 | Line, Square, T, J, L, S, Z
15 | }
16 |
17 | RandomBag pieceBag;
18 |
19 | void Awake()
20 | {
21 | // Get an array with each value of TetrisPiece
22 | TetrisPiece[] tetrisPieceArray = (TetrisPiece[]) Enum.GetValues(typeof (TetrisPiece));
23 |
24 | // Create the bag containing two instances of every value of TetrisPiece
25 | pieceBag = new RandomBag(tetrisPieceArray, 2);
26 |
27 | // Gets 50 items from the bag. The bag will be filled with 14 TetrisPieces and
28 | // automatically refilled with 14 more when needed. No two pieces will ever be
29 | // more than 14 calls apart - and even that will only happen if that piece was
30 | // the first and last item in the current 14 piece bag filling.
31 | StringBuilder str = new StringBuilder();
32 | for (var i = 0; i < 50; i++)
33 | {
34 | str.Append(pieceBag.PopRandomItem());
35 | str.Append(", ");
36 | }
37 |
38 | Debug.Log(str);
39 |
40 | // Example output:
41 | // T, Z, J, Square, Z, S, L, L, S, Line, J, Line, Square, T, Square, Z,
42 | // S, T, Line, Square, Z, T, J, Line, S, L, J, L, S, Z, Line, J, Line,
43 | // J, L, L, S, T, T, Z, Square, Square, Z, T, S, Z, J, J, L, Line,
44 | }
45 | }
46 | ```
47 |
48 | ## Dependencies
49 |
50 | * [LINQExtensions](https://github.com/TobiasWehrum/unity-utilities/tree/master/LINQExtensions)
--------------------------------------------------------------------------------
/RandomBag/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: c42cfaa3e607e084c88ab39259f6fc0c
3 | timeCreated: 1463270294
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/RandomBag/RandomBag.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// A RandomBag ensures that per interval [fillings * itemCount], every different item in it
8 | /// will be given back [fillings] times. Once the bag is empty, it is automatically refilled,
9 | /// either from a fixed array or by calling a delegate.
10 | ///
11 | /// An example for that is used in some implementations of Tetris. The bag is filled with one
12 | /// instance (fillings=1) of each of the seven different pieces. Every time the next piece is
13 | /// needed, a random one is taken out of the bag until the bag is empty. That way, any two pieces
14 | /// are never longer than 7 pulls apart - and even that is only the case if the first and the last
15 | /// piece in the bag are the same one.
16 | ///
17 | /// The type to be put in the bag.
18 | public class RandomBag
19 | {
20 | ///
21 | /// A temporary array used internally for shuffling.
22 | ///
23 | List tempList;
24 |
25 | ///
26 | /// The bag itself.
27 | ///
28 | Stack bag;
29 |
30 | ///
31 | /// One of the two methods of filling the bag. When empty, this array is added to the bag [fillings] times.
32 | ///
33 | T[] refillItems;
34 |
35 | ///
36 | /// One of the two methods of filling the bag. When empty, this delegate is called [fillings] times to fill the bag.
37 | ///
38 | Action> refillDelegate;
39 |
40 | ///
41 | /// How often / is used to fill the bag when the bag is empty.
42 | ///
43 | public int Fillings { get; private set; }
44 |
45 | ///
46 | /// Initializes the bag with a array of items to refill it and the number of times the array is added to the bag.
47 | /// Once the bag is empty, the array will automatically be added to the bag [fillings] times again.
48 | ///
49 | /// The array to fill the bag [fillings] times with.
50 | /// The number of times the array is added to the bag.
51 | public RandomBag(T[] refillItems, int fillings)
52 | {
53 | bag = new Stack();
54 | tempList = new List();
55 |
56 | SetRefillItems(refillItems);
57 | Fillings = fillings;
58 |
59 | Reset();
60 | }
61 |
62 | ///
63 | /// Initializes the bag by calling the refillDelegate multiple times.
64 | /// Once the bag is empty, the delegate will automatically be called [fillings] times again.
65 | ///
66 | /// The delegate that will be called [fillings] times to fill the bag.
67 | /// The number of times refillDelegate is called.
68 | public RandomBag(Action> refillDelegate, int fillings)
69 | {
70 | bag = new Stack();
71 | tempList = new List();
72 |
73 | SetRefillDelegate(refillDelegate);
74 | Fillings = fillings;
75 |
76 | Reset();
77 | }
78 |
79 | ///
80 | /// Sets the refill method to "When empty, this delegate is called [fillings] times to fill the bag."
81 | ///
82 | /// The delegate that will be called [fillings] times to fill the bag once it's empty.
83 | public void SetRefillDelegate(Action> refillDelegate)
84 | {
85 | this.refillDelegate = refillDelegate;
86 | refillItems = null;
87 | }
88 |
89 | ///
90 | /// Sets the refill method to "When empty, this array is added to the bag [fillings] times."
91 | ///
92 | /// The array to fill the bag [fillings] times with once it's empty.
93 | public void SetRefillItems(T[] refillItems)
94 | {
95 | if (refillItems.Length == 0)
96 | throw new ArgumentOutOfRangeException("refillItems", "RefillItems needs to contain at least one item.");
97 |
98 | this.refillItems = refillItems;
99 | refillDelegate = null;
100 | }
101 |
102 | ///
103 | /// Clears the bag and refills it.
104 | ///
105 | public void Reset()
106 | {
107 | // Empty the bag
108 | bag.Clear();
109 |
110 | // Call the delegate/add the array [Fillings] times
111 | for (var i = 0; i < Fillings; i++)
112 | {
113 | if (refillDelegate != null)
114 | {
115 | refillDelegate(tempList);
116 |
117 | if (tempList.Count == 0)
118 | throw new Exception("RandomBag.refillDelegate didn't add any items to the bag.");
119 | }
120 | else
121 | {
122 | tempList.AddRange(refillItems);
123 | }
124 | }
125 |
126 | // Shuffle the temporary list
127 | tempList.Shuffle();
128 |
129 | // Fill the temporary list into the bag
130 | for (var i = 0; i < tempList.Count; i++)
131 | {
132 | bag.Push(tempList[i]);
133 | }
134 |
135 | // Clear the temporary list
136 | tempList.Clear();
137 | }
138 |
139 | ///
140 | /// Gets a random item from the bag. If there is no item in the bag, it is automatically refilled first.
141 | ///
142 | /// A random item from the bag.
143 | public T PopRandomItem()
144 | {
145 | // If the bag is empty, refill it
146 | if (bag.Count == 0)
147 | Reset();
148 |
149 | // Return an item
150 | return bag.Pop();
151 | }
152 |
153 | ///
154 | /// Gets multiple random items from the bag. If there aren't enough item in the bag, it is automatically refilled.
155 | ///
156 | /// How many items to pull from the bag.
157 | /// A number of random items from the bag.
158 | public T[] PopRandomItems(int count)
159 | {
160 | var randomItems = new T[count];
161 |
162 | // Add [count] items to the bag
163 | for (var i = 0; i < count; i++)
164 | {
165 | // If the bag is empty, refill it
166 | if (bag.Count == 0)
167 | Reset();
168 |
169 | // Add a random item to the result array
170 | randomItems[i] = bag.Pop();
171 | }
172 |
173 | return randomItems;
174 | }
175 |
176 | ///
177 | /// Gets an enumerator returning an endless number of items, automatically refilling the bag when empty.
178 | ///
179 | /// An enumerator returning an endless number of items from the bag.
180 | public IEnumerator GetEndlessEnumerator()
181 | {
182 | while (true)
183 | yield return PopRandomItem();
184 | }
185 |
186 | ///
187 | /// Gets an enumerator returning the items remaining in the bag.
188 | ///
189 | /// An enumerator returning the items currently remaining in the bag.
190 | public IEnumerator GetRemainderEnumerator()
191 | {
192 | while (bag.Count > 0)
193 | yield return bag.Pop();
194 | }
195 |
196 | ///
197 | /// The items currently remaining in the bag.
198 | ///
199 | public int RemainderCount
200 | {
201 | get { return bag.Count; }
202 | }
203 | }
204 | }
205 |
--------------------------------------------------------------------------------
/RandomBag/RandomBag.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0e9e6b1d3fe40544ca29829e80233895
3 | timeCreated: 1463231729
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Range.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 99780946aee1802469d2804ec9d050be
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Range/Editor.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 326c0927f62b6ae4a8175ede59eb3f8a
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Range/Editor/RangeFloatPropertyDrawer.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 |
3 | namespace UnityUtilities
4 | {
5 | [CustomPropertyDrawer(typeof (RangeFloat))]
6 | public class RangeFloatPropertyDrawer : RangePropertyDrawerBase
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/Range/Editor/RangeFloatPropertyDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 114c3186bf56f39459f8a6cf4e44e5bf
3 | timeCreated: 1462732529
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Range/Editor/RangeIntPropertyDrawer.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 |
3 | namespace UnityUtilities
4 | {
5 | [CustomPropertyDrawer(typeof (RangeInt))]
6 | public class RangeIntPropertyDrawer : RangePropertyDrawerBase
7 | {
8 | }
9 | }
--------------------------------------------------------------------------------
/Range/Editor/RangeIntPropertyDrawer.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b0fd8cdb8b637574284efbe5ae471625
3 | timeCreated: 1462732529
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Range/Editor/RangePropertyDrawerBase.cs:
--------------------------------------------------------------------------------
1 | using UnityEditor;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | public class RangePropertyDrawerBase : PropertyDrawer
7 | {
8 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
9 | {
10 | // Using BeginProperty / EndProperty on the parent property means that
11 | // prefab override logic works on the entire property.
12 | EditorGUI.BeginProperty(position, label, property);
13 |
14 | // Set tooltip, if any
15 | label.tooltip = EditorHelper.GetTooltip(fieldInfo);
16 |
17 | // Draw label
18 | position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
19 |
20 | // Don't make child fields be indented
21 | var indent = EditorGUI.indentLevel;
22 | EditorGUI.indentLevel = 0;
23 |
24 | // Calculate rects
25 | var fromLabelWidth = 40;
26 | var toLabelWidth = 20;
27 | var afterValueFieldOffset = 5;
28 | var valuesWidth = (position.width - fromLabelWidth - toLabelWidth - afterValueFieldOffset) / 2f;
29 | var fromLabelRect = new Rect(position.x, position.y, fromLabelWidth, position.height);
30 | var fromRect = new Rect(fromLabelRect.xMax, position.y, valuesWidth, position.height);
31 | var toLabelRect = new Rect(fromRect.xMax + afterValueFieldOffset, position.y, toLabelWidth, position.height);
32 | var toRect = new Rect(toLabelRect.xMax, position.y, valuesWidth, position.height);
33 |
34 | // Draw fields - passs GUIContent.none to each so they are drawn without labels
35 | EditorGUI.LabelField(fromLabelRect, "From");
36 | EditorGUI.PropertyField(fromRect, property.FindPropertyRelative("from"), GUIContent.none);
37 | EditorGUI.LabelField(toLabelRect, "to");
38 | EditorGUI.PropertyField(toRect, property.FindPropertyRelative("to"), GUIContent.none);
39 |
40 | // Set indent back to what it was
41 | EditorGUI.indentLevel = indent;
42 |
43 | EditorGUI.EndProperty();
44 | }
45 | }
46 | }
--------------------------------------------------------------------------------
/Range/Editor/RangePropertyDrawerBase.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e5ea3b62097d6bc45bce230ae024eb93
3 | timeCreated: 1462732534
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Range/README.md:
--------------------------------------------------------------------------------
1 | # RangeInt/Float
2 |
3 | `RangeInt`/`RangeFloat` are editable data types that take an int/float range. Used for things like "Spawn 2 to 4 enemies."
4 |
5 | ## Example
6 | 
7 |
8 | ```C#
9 | public class RangeExample : MonoBehaviour
10 | {
11 | [SerializeField] RangeInt amountRange;
12 | [SerializeField] RangeFloat numberRange;
13 |
14 | private void Awake()
15 | {
16 | // Get a random number in amountRange
17 | int amount = amountRange.RandomInclusive;
18 |
19 | // Output [amount] numbers
20 | for (int i = 0; i < amount; i++)
21 | {
22 | // Transform [i..(amount-1)] to [0..1]
23 | var t = ((float)i / (amount - 1));
24 |
25 | // Mathf.Lerp(numberRange.From, numberRange.To, t)
26 | Debug.Log(numberRange.Lerp(t));
27 | }
28 | }
29 | }
30 | }
31 | ```
32 |
33 | ## Dependencies
34 |
35 | None.
--------------------------------------------------------------------------------
/Range/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1f519e37ca0101f479accde1398c5e06
3 | timeCreated: 1462746256
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Range/RangeFloat.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// Provides input for a float value range in the editor and various convencience functions to work with that range.
8 | ///
9 | [Serializable]
10 | public class RangeFloat
11 | {
12 | ///
13 | /// The range start.
14 | ///
15 | [SerializeField] float from;
16 |
17 | ///
18 | /// The range end.
19 | ///
20 | [SerializeField] float to;
21 |
22 | ///
23 | /// The range start.
24 | ///
25 | public float From { get { return from; } }
26 |
27 | ///
28 | /// The range end.
29 | ///
30 | public float To { get { return to; } }
31 |
32 | ///
33 | /// Returns how wide the range between from and to is.
34 | ///
35 | public float Range { get { return to - from; } }
36 |
37 | ///
38 | /// Returns a random number between from [inclusive] and to [inclusive].
39 | ///
40 | public float RandomInclusive { get { return UnityEngine.Random.Range(from, to); } }
41 |
42 | ///
43 | /// Create a RangeFloat with 0-0 as the range. Needed for the editor.
44 | ///
45 | public RangeFloat()
46 | {
47 | }
48 |
49 | ///
50 | /// Create a RangeFloat with a certain range.
51 | ///
52 | /// Lower range bound.
53 | /// Upper range bound.
54 | public RangeFloat(float @from, float to)
55 | {
56 | this.@from = @from;
57 | this.to = to;
58 | }
59 |
60 | ///
61 | /// Linearly interpolates between to and from by t.
62 | ///
63 | /// How much to interpolate. Clamped between 0 and 1. 0 is [to] and 1 is [from].
64 | ///
65 | public float Lerp(float t)
66 | {
67 | return Mathf.Lerp(from, to, t);
68 | }
69 |
70 | ///
71 | /// Linearly interpolates between to and from by t.
72 | ///
73 | /// How much to interpolate. 0 is [to] and 1 is [from].
74 | ///
75 | public float LerpUnclamped(float t)
76 | {
77 | return Mathf.LerpUnclamped(from, to, t);
78 | }
79 |
80 | ///
81 | /// Calculates the linear parameter t that produces the interpolant value within the range [from, to].
82 | ///
83 | ///
84 | ///
85 | public float InverseLerp(float value)
86 | {
87 | return Mathf.InverseLerp(from, to, value);
88 | }
89 | }
90 | }
--------------------------------------------------------------------------------
/Range/RangeFloat.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 94ef56b85cf1a22498b4299d49dcedeb
3 | timeCreated: 1462732529
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Range/RangeInt.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using UnityEngine;
3 |
4 | namespace UnityUtilities
5 | {
6 | ///
7 | /// Provides input for a value range in the editor and various convencience functions to work with that range.
8 | ///
9 | [Serializable]
10 | public class RangeInt
11 | {
12 | ///
13 | /// The range start.
14 | ///
15 | [SerializeField] int from;
16 |
17 | ///
18 | /// The range end.
19 | ///
20 | [SerializeField] int to;
21 |
22 | ///
23 | /// The range start.
24 | ///
25 | public int From { get { return from; } }
26 |
27 | ///
28 | /// The range end.
29 | ///
30 | public int To { get { return to; } }
31 |
32 | ///
33 | /// Returns how wide the range between from and to is.
34 | ///
35 | public int Range { get { return to - from; } }
36 |
37 | ///
38 | /// Returns a random number between from [inclusive] and to [inclusive].
39 | ///
40 | public int RandomInclusive { get { return UnityEngine.Random.Range(from, to + 1); } }
41 |
42 | ///
43 | /// Returns a random number between from [inclusive] and to [exclusive].
44 | ///
45 | public int RandomExclusive { get { return UnityEngine.Random.Range(from, to); } }
46 |
47 | ///
48 | /// Create a RangeFloat with 0-0 as the range. Needed for the editor.
49 | ///
50 | public RangeInt()
51 | {
52 | }
53 |
54 | ///
55 | /// Create a RangeFloat with a certain range.
56 | ///
57 | /// Lower range bound.
58 | /// Upper range bound.
59 | public RangeInt(int from, int to)
60 | {
61 | this.from = from;
62 | this.to = to;
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/Range/RangeInt.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 0a7ceba396b3b4b42ab9086be9ec2528
3 | timeCreated: 1462732529
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/RollingArray.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 786224cc203cfd347a3b735a5fcceef9
3 | folderAsset: yes
4 | timeCreated: 1465072662
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/RollingArray/README.md:
--------------------------------------------------------------------------------
1 | # RollingArray
2 |
3 | `RollingArray` is a container that always stores the last arraySize elements added. New elements are added via `Append()`, which automatically rolls over once the maximum number of elements is reached, overwriting the oldest element. `array[i]` always returns the oldest element that still exists + i. That way, this container always stores the last arraySize elements added.
4 |
5 | Adding is O(1), retrieving is O(1) and (with the exception of `GetEnumerator()`) no new memory is allocated after the initial creation.
6 |
7 | You can read more about the `GetEnumerator()` memory problem (and Unity's dreadful memory allocation troubles) here under "Should you avoid foreach loops?": http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php
8 |
9 | ## Example
10 |
11 | ```C#
12 | public class RollingArrayExample : MonoBehaviour
13 | {
14 | [SerializeField] Transform indicatorObject;
15 |
16 | RollingArray mousePositions;
17 | Camera mainCamera;
18 |
19 | void Awake()
20 | {
21 | // Save the last 50 elements
22 | mousePositions = new RollingArray(50);
23 |
24 | // Cache a reference to the main camera
25 | mainCamera = Camera.main;
26 | }
27 |
28 | void FixedUpdate()
29 | {
30 | // Get the mouse position in a fixed interval
31 | // If we get to 50 positions, the oldest position will be replaced
32 | mousePositions.Append(mainCamera.ScreenToWorldPoint(Input.mousePosition));
33 | }
34 |
35 | void Update()
36 | {
37 | // Only continue if we have at least one mouse position
38 | if (mousePositions.IsEmpty)
39 | return;
40 |
41 | // Go through all the saved mouse positions from oldest to newest to get the average
42 | Vector2 averagePosition = new Vector2();
43 | for (var i = 0; i < mousePositions.Count; i++)
44 | {
45 | averagePosition += mousePositions[i];
46 | }
47 | averagePosition /= mousePositions.Count;
48 |
49 | // Set the indicator object to the average position
50 | indicatorObject.position = averagePosition;
51 | }
52 | }
53 | ```
54 |
55 | ## Dependencies
56 |
57 | None.
--------------------------------------------------------------------------------
/RollingArray/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 567fa8418a92e63488ee3716c54d54ef
3 | timeCreated: 1465141999
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/RollingArray/RollingArray.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections;
3 | using System.Collections.Generic;
4 | using UnityEngine;
5 |
6 | namespace UnityUtilities
7 | {
8 | ///
9 | /// A container that always stores the last arraySize elements added. New elements are added
10 | /// via Append(), which automatically rolls over once the maximum number of elements is reached,
11 | /// overwriting the oldest element. array[i] always returns the oldest element that still
12 | /// exists + i. That way, this container always stores the last arraySize elements added.
13 | ///
14 | /// Adding is O(1), retrieving is O(1) and (with the exception of GetEnumerator()) no new memory
15 | /// is allocated after the initial creation.
16 | ///
17 | /// The collection element type.
18 | public class RollingArray : IEnumerable
19 | {
20 | ///
21 | /// The internal storage array.
22 | ///
23 | T[] array;
24 |
25 | ///
26 | /// The index of the next element to be added.
27 | ///
28 | int nextElementIndex;
29 |
30 | ///
31 | /// The current count of filled elements.
32 | ///
33 | public int Count { get; private set; }
34 |
35 | ///
36 | /// Creates a new rolling array with the defined arraySize.
37 | ///
38 | ///
39 | public RollingArray(int arraySize)
40 | {
41 | array = new T[arraySize];
42 | }
43 |
44 | ///
45 | /// Appends an element to the RollingArray. Automatically rolls over once the maximum number
46 | /// of elements is reached, overwriting the oldest element
47 | ///
48 | /// The element to be added.
49 | public void Append(T element)
50 | {
51 | array[nextElementIndex] = element;
52 | nextElementIndex = (nextElementIndex + 1) % array.Length;
53 |
54 | if (Count < array.Length)
55 | Count++;
56 | }
57 |
58 | ///
59 | /// Is the array empty?
60 | ///
61 | public bool IsEmpty
62 | {
63 | get { return Count == 0; }
64 | }
65 |
66 | ///
67 | /// Gets the oldest element.
68 | ///
69 | /// Thrown when the array is empty.
70 | public T OldestElement
71 | {
72 | get
73 | {
74 | if (IsEmpty)
75 | throw new IndexOutOfRangeException("The array is current empty.");
76 |
77 | return this[0];
78 | }
79 | }
80 |
81 | ///
82 | /// Gets the latest added element.
83 | ///
84 | /// Thrown when the array is empty.
85 | public T LatestElement
86 | {
87 | get
88 | {
89 | if (IsEmpty)
90 | throw new IndexOutOfRangeException("The array is current empty.");
91 |
92 | return this[Count - 1];
93 | }
94 | }
95 |
96 | ///
97 | /// Gets/sets an element from/in the array. 0 is always the oldest element that is still in the array,
98 | /// [Count-1] is always the latest added element.
99 | ///
100 | /// This method should NOT be used to add elements - used Append() for that. Only read and write elements
101 | /// that are already in the array.
102 | ///
103 | /// The index. 0 is the oldest, [Count-1] the newest element.
104 | /// The accessed elements.
105 | /// Thrown when accessing an element outside of [0..Count-1].
106 | public T this[int i]
107 | {
108 | get
109 | {
110 | if ((i < 0) || (i >= Count))
111 | throw new IndexOutOfRangeException("Index " + i + " (current count: " + Count + ") is out of range.");
112 |
113 | i = (i + nextElementIndex - Count + array.Length) % array.Length;
114 | return array[i];
115 | }
116 |
117 | set
118 | {
119 | if ((i < 0) || (i >= Count))
120 | throw new IndexOutOfRangeException("Index " + i + " (current count: " + Count + ") is out of range.");
121 |
122 | i = (i + nextElementIndex - Count + array.Length) % array.Length;
123 | array[i] = value;
124 | }
125 | }
126 |
127 | ///
128 | /// Clears the RollingArray.
129 | ///
130 | public void Clear()
131 | {
132 | nextElementIndex = 0;
133 | Count = 0;
134 | }
135 |
136 | ///
137 | /// Returns an enumerator that iterates through the collection from oldest to newest element.
138 | ///
139 | /// Caveat: Due to the outdated Mono version used in Unity3D, this allocates a small amount of
140 | /// memory, leading to memory fragmentation if called often. You might want to use array[i] instead.
141 | ///
142 | /// Read more about this under "Should you avoid foreach loops?" at:
143 | /// http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php
144 | ///
145 | /// An enumerator that iterates through the collection from oldest to newest element.
146 | public IEnumerator GetEnumerator()
147 | {
148 | if (IsEmpty)
149 | yield break;
150 |
151 | var index = nextElementIndex - Count;
152 | if (index < 0)
153 | index += array.Length;
154 |
155 | for (int counter = 0; counter < Count; counter++)
156 | {
157 | yield return array[index];
158 |
159 | index++;
160 | if (index >= array.Length)
161 | index -= array.Length;
162 | }
163 | }
164 |
165 | ///
166 | /// Returns an enumerator that iterates through the collection from oldest to newest element.
167 | ///
168 | /// Caveat: Due to the outdated Mono version used in Unity3D, this allocates a small amount of
169 | /// memory, leading to memory fragmentation if called often. You might want to use array[i] instead.
170 | ///
171 | /// Read more about this under "Should you avoid foreach loops?" at:
172 | /// http://www.gamasutra.com/blogs/WendelinReich/20131109/203841/C_Memory_Management_for_Unity_Developers_part_1_of_3.php
173 | ///
174 | /// An enumerator that iterates through the collection from oldest to newest element.
175 | IEnumerator IEnumerable.GetEnumerator()
176 | {
177 | return GetEnumerator();
178 | }
179 | }
180 | }
--------------------------------------------------------------------------------
/RollingArray/RollingArray.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a0a426c557878204e9bd54dae0a02fc1
3 | timeCreated: 1465072797
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Singleton.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 25de148f6c9456445ada831981d8d467
3 | folderAsset: yes
4 | timeCreated: 1462732529
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/Singleton/PersistentSingletonMonoBehaviour.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// Any class that extends from this one will persist through scenes (via ) and can be handily accessed
7 | /// via the static property.
8 | /// If a new scene is loaded with a new instance of this class while another persistent instance already exists, the new instance in the scene is destroyed.
9 | /// This allows you to make this a prefab and have it in all scenes that you are working on.
10 | ///
11 | /// The subclass that extends from this class.
12 | public class PersistentSingletonMonoBehaviour : MonoBehaviour where TSubclass : PersistentSingletonMonoBehaviour
13 | {
14 | static TSubclass instance;
15 |
16 | ///
17 | /// Returns the singleton instance.
18 | ///
19 | public static TSubclass Instance
20 | {
21 | get { return instance; }
22 | }
23 |
24 | ///
25 | /// Returns true if a singleton instance is registered.
26 | ///
27 | protected bool InstanceExists
28 | {
29 | get { return instance != null; }
30 | }
31 |
32 | ///
33 | /// Used to skip the first "OnLevelWasLoaded".
34 | ///
35 | bool skipOnLevelWasLoaded;
36 |
37 | ///
38 | /// If this is the first instance of this type:
39 | /// 1. Register it as the instance.
40 | /// 2. Mark it as .
41 | /// 3. Call .
42 | /// 4. Call .
43 | ///
44 | /// If an instance of this already exists, destroy this instance.
45 | ///
46 | void Awake()
47 | {
48 | // If an instance already exists, destroy this instance.
49 | if (InstanceExists)
50 | {
51 | Destroy(gameObject);
52 | return;
53 | }
54 |
55 | // Register, make persistent and call event methods
56 | instance = (TSubclass) this;
57 | DontDestroyOnLoad(gameObject);
58 | OnPersistentSingletonAwake();
59 | OnAwakeOrSwitch();
60 |
61 | // Make sure to skip "OnLevelWasLoaded" for this first Awake -
62 | // we only want to go there when the scene changes.
63 | skipOnLevelWasLoaded = true;
64 | }
65 |
66 | ///
67 | /// If this is the persistent instance and it was destroyed (manually),
68 | /// remove the instance registration.
69 | ///
70 | /// Note: This also means that you need to use
71 | ///
72 | /// protected override void OnDestroy()
73 | /// {
74 | /// base.OnDestroy();
75 | /// // [Your code]
76 | /// }
77 | ///
78 | /// in subclasses.
79 | ///
80 | protected virtual void OnDestroy()
81 | {
82 | if (instance == this)
83 | {
84 | instance = null;
85 | OnPersistentSingletonDestroyed();
86 | }
87 | }
88 |
89 | ///
90 | /// Called when the scene is first loaded or was switched.
91 | ///
92 | void OnLevelWasLoaded()
93 | {
94 | // First time? Skip it - it's not a scene switch.
95 | if (skipOnLevelWasLoaded)
96 | return;
97 |
98 | if (Instance == this)
99 | {
100 | // Call the event methods.
101 | OnSceneSwitched();
102 | OnAwakeOrSwitch();
103 | }
104 | }
105 |
106 | ///
107 | /// Disable .
108 | ///
109 | protected virtual void Start()
110 | {
111 | // The first "OnLevelWasLoaded" was called already; disable the skipping.
112 | skipOnLevelWasLoaded = false;
113 | }
114 |
115 | ///
116 | /// This method is called when the Awake() method of the first instance of the persistent
117 | /// singleton is done. This is not called if this is a second instance (which is destroyed
118 | /// automatically immediately).
119 | ///
120 | protected virtual void OnPersistentSingletonAwake()
121 | {
122 | }
123 |
124 | ///
125 | /// This method is called when the registered instance of the persistent singleton is either
126 | /// destroyed manually by calling Destroy() or the application is closed. This is not called
127 | /// if this is a second instance (which is destroyed automatically immediately).
128 | ///
129 | protected virtual void OnPersistentSingletonDestroyed()
130 | {
131 | }
132 |
133 | ///
134 | /// This method is called after switching to a new scene.
135 | ///
136 | protected virtual void OnSceneSwitched()
137 | {
138 | }
139 |
140 | ///
141 | /// This method is called immediately after
142 | /// or .
143 | ///
144 | protected virtual void OnAwakeOrSwitch()
145 | {
146 | }
147 | }
148 | }
--------------------------------------------------------------------------------
/Singleton/PersistentSingletonMonoBehaviour.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 1327f4476a85f614e8d3c49a1412bcb2
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 |
--------------------------------------------------------------------------------
/Singleton/README.md:
--------------------------------------------------------------------------------
1 | # SingletonMonoBehaviour and PersistentSingletonMonoBehaviour
2 |
3 | SingletonMonoBehaviour can be used to provide static access to single instances like an EntityManager easily from anywhere in the code.
4 |
5 | PersistentSingletonMonoBehaviour also provides static instance, but additionally marks the object with [`DontDestroyOnLoad`](http://docs.unity3d.com/ScriptReference/Object.DontDestroyOnLoad.html). That is useful for objects like a MusicManager that should continue playing even when switching levels, or a PlayerData singleton that carries the name and statistics of a player between scenes.
6 |
7 | ## A word of caution
8 |
9 | Note that the Singleton pattern has quite a few shortcomings. For example, the instance binding is hardwired in the code, which makes providing an alternative implementation for testing impossible. Unless you are using this for a prototype like a jam game, you might considering using a framework like [Zenject](https://github.com/modesttree/Zenject) or [StrangeIoC](http://strangeioc.github.io/strangeioc) instead.
10 |
11 | ## Examples
12 |
13 | ### SingletonEntityManager
14 |
15 | If the following component is added on a game object in the scene, it could be accessed from anywhere via `SingletonEntityManager.Instance`, e.g.: `SingletonEntityManager.Instance.AddEntity(newEntity);`. This is available even before `SingletonEntityManager.Awake()` is called.
16 |
17 | If you want to use OnDestroy(), you have to override it like shown in the example below. All other MonoBehaviour callbacks can be used as usual.
18 |
19 | ```C#
20 | public class SingletonEntityManager : SingletonMonoBehaviour
21 | {
22 | List entities;
23 |
24 | public IEnumerable Entities
25 | {
26 | get { return entities; }
27 | }
28 |
29 | void Awake()
30 | {
31 | entities = new List();
32 | }
33 |
34 | // If you want to use OnDestroy(), you have to override it like this
35 | protected override void OnDestroy()
36 | {
37 | base.OnDestroy();
38 | Debug.Log("Destroyed");
39 | }
40 |
41 | public void AddEntity(GameObject entity)
42 | {
43 | entities.Add(entity);
44 | }
45 |
46 | public void RemoveEntity(GameObject entity)
47 | {
48 | entities.Remove(entity);
49 | }
50 | }
51 | ```
52 |
53 | ### SingletonMusicManager
54 |
55 | The `SingletonMusicManager` in the following example can be accessed in the same way, but it is not destroyed when the scenes switches.
56 |
57 | You could make this SingletonMusicManager a prefab and drop it in multiple scenes that you work on. If at any time there are two `SingletonMusicManager`,
58 | the one from the previous scene survives and the new one is destroyed. (For that reason, you should never create an `Awake()` method in a
59 | PersistentSingletonMonoBehaviour. Instead, use `OnPersistentSingletonAwake()` because it is only called on "surviving" instances. Similarily, you shouldn't
60 | have an `OnDestroy()` method which would be called if this is ever destroyed via `Destroy()`; instead, use `OnPersistentSingletonDestroyed()`.)
61 |
62 | Note that `SingletonMusicManager.Instance` is only available after `SingletonMusicManager.Awake()` was called, so if you need it in another `Awake()`
63 | call, you should put the `SingletonMusicManager` higher in the [Script Execution Order](http://docs.unity3d.com/Manual/class-ScriptExecution.html).
64 |
65 | ```C#
66 | public class SingletonMusicManager : PersistentSingletonMonoBehaviour
67 | {
68 | protected override void OnPersistentSingletonAwake()
69 | {
70 | base.OnPersistentSingletonAwake();
71 |
72 | // Start playing the music the first time Awake() is called
73 | PlayMusic();
74 | }
75 |
76 | protected override void OnSceneSwitched()
77 | {
78 | base.OnSceneSwitched();
79 |
80 | // Fade to random song once a new scene is loaded
81 | FadeToRandomSong();
82 | }
83 |
84 | protected override void OnPersistentSingletonDestroyed()
85 | {
86 | base.OnPersistentSingletonDestroyed();
87 |
88 | // Stop the music when Destroy() was called on the active instance.
89 | StopMusic();
90 | }
91 |
92 | public void PlayMusic()
93 | {
94 | Debug.Log("Play music");
95 | }
96 |
97 | public void StopMusic()
98 | {
99 | Debug.Log("Stop music");
100 | }
101 |
102 | public void FadeToRandomSong()
103 | {
104 | Debug.Log("Fade to a random song");
105 | }
106 | }
107 | ```
108 |
109 | ## Dependencies
110 |
111 | None.
--------------------------------------------------------------------------------
/Singleton/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 17aff1e8f544d534197e512a71211a76
3 | timeCreated: 1462746256
4 | licenseType: Free
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/Singleton/SelfCreatingSingletonMonoBehaviour.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// A that should only exist once and provides easy access to its instance. If none exists in
7 | /// the secene at the time it is requested, it will be automatically created.
8 | ///
9 | /// The subclass that extends from this class.
10 | public class SelfCreatingSingletonMonoBehaviour : MonoBehaviour where TSubclass : SelfCreatingSingletonMonoBehaviour
11 | {
12 | static TSubclass instance;
13 |
14 | ///
15 | /// Returns the sole instance of this class in the current scene.
16 | /// If the instance is not yet found cached, it searches for it and then caches it.
17 | /// If no instance is found, it creates one.
18 | ///
19 | public static TSubclass Instance
20 | {
21 | get
22 | {
23 | if (instance == null)
24 | {
25 | UpdateInstance();
26 | }
27 |
28 | return instance;
29 | }
30 | }
31 |
32 |
33 | ///
34 | /// Searches for the instance and fills with it. Creates an instance if there is none and
35 | /// outputs an error message if there are too many instances.
36 | ///
37 | static void UpdateInstance()
38 | {
39 | var instances = FindObjectsOfType();
40 | if (instances.Length == 1)
41 | {
42 | instance = instances[0];
43 | }
44 | else if (instances.Length == 0)
45 | {
46 | instance = new GameObject(typeof(TSubclass).Name).AddComponent();
47 | }
48 | else
49 | {
50 | Debug.LogError("Requested singleton of type " + typeof (TSubclass).Name + " has " + instances.Length + "instances.");
51 | }
52 | }
53 |
54 | ///
55 | /// If this is the instance and it was destroyed,
56 | /// remove the instance registration.
57 | ///
58 | /// Note: This also means that you need to use
59 | ///
60 | /// protected override void OnDestroy()
61 | /// {
62 | /// base.OnDestroy();
63 | /// // [Your code]
64 | /// }
65 | ///
66 | /// in subclasses.
67 | ///
68 | protected virtual void OnDestroy()
69 | {
70 | if (instance == this)
71 | {
72 | instance = null;
73 | }
74 | }
75 | }
76 | }
--------------------------------------------------------------------------------
/Singleton/SelfCreatingSingletonMonoBehaviour.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 349795bb315cf0b46ac82409025e062f
3 | timeCreated: 1477779343
4 | licenseType: Free
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/Singleton/SingletonMonoBehaviour.cs:
--------------------------------------------------------------------------------
1 | using UnityEngine;
2 |
3 | namespace UnityUtilities
4 | {
5 | ///
6 | /// A that should only exist once and provides easy access to its instance. However, it isn't automatically
7 | /// created and still needs to be attached to a GameObject in the scene.
8 | ///
9 | /// The subclass that extends from this class.
10 | public class SingletonMonoBehaviour : MonoBehaviour where TSubclass : SingletonMonoBehaviour
11 | {
12 | static TSubclass instance;
13 |
14 | ///
15 | /// Returns the sole instance of this class in the current scene.
16 | /// If the instance is not yet found cached, it searches for it and then caches it.
17 | ///
18 | public static TSubclass Instance
19 | {
20 | get
21 | {
22 | if (instance == null)
23 | {
24 | UpdateInstance(false);
25 | }
26 |
27 | return instance;
28 | }
29 | }
30 |
31 | ///
32 | /// Returns the sole instance of this class in the current scene.
33 | /// If the instance is not already cached, it searches for it and then caches it.
34 | /// Note that if the instance is not found at all, InstanceOptional will try to
35 | /// find it on every call. For that reason, it is better to only call this once
36 | /// per script in Awake() or Start() and cache the result.
37 | ///
38 | public static TSubclass InstanceOptional
39 | {
40 | get
41 | {
42 | if (instance == null)
43 | {
44 | // If the instance is not in the current scene, UpdateInstance will be called on every call.
45 | // I could fix this by introducting a static "instanceUpdated" boolean, but then I would
46 | // need to set instanceUpdated to false in OnDestroy() (for scene changes) and I don't want
47 | // to introduce the complexity of virtual MonoBehaviour event methods to this class.
48 | UpdateInstance(true);
49 | }
50 |
51 | return instance;
52 | }
53 | }
54 |
55 | ///
56 | /// Searches for the instance and fills with it. Outputs an error message if there is no
57 | /// instance (unless the parameter is set) or if there are too many instances.
58 | ///
59 | /// If this is set to false, and error message will be shown if there is no instance found.
60 | static void UpdateInstance(bool optional)
61 | {
62 | var instances = FindObjectsOfType();
63 | if (instances.Length == 1)
64 | {
65 | instance = instances[0];
66 | }
67 | else if (instances.Length == 0)
68 | {
69 | if (!optional)
70 | {
71 | Debug.LogError("Requested singleton of type " + typeof (TSubclass).Name + " not found.");
72 | }
73 | }
74 | else
75 | {
76 | Debug.LogError("Requested singleton of type " + typeof (TSubclass).Name + " has " + instances.Length + "instances.");
77 | }
78 | }
79 |
80 | ///
81 | /// If this is the instance and it was destroyed,
82 | /// remove the instance registration.
83 | ///
84 | /// Note: This also means that you need to use
85 | ///
86 | /// protected override void OnDestroy()
87 | /// {
88 | /// base.OnDestroy();
89 | /// // [Your code]
90 | /// }
91 | ///
92 | /// in subclasses.
93 | ///
94 | protected virtual void OnDestroy()
95 | {
96 | if (instance == this)
97 | {
98 | instance = null;
99 | }
100 | }
101 | }
102 | }
--------------------------------------------------------------------------------
/Singleton/SingletonMonoBehaviour.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 4c4b96e5289472c41b1d65d001649e67
3 | MonoImporter:
4 | serializedVersion: 2
5 | defaultReferences: []
6 | executionOrder: 0
7 | icon: {instanceID: 0}
8 | userData:
9 |
--------------------------------------------------------------------------------
/UnityHelper.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: e5cf8213f892df34a890c84ce548c280
3 | folderAsset: yes
4 | timeCreated: 1465253549
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/UnityHelper/README.md:
--------------------------------------------------------------------------------
1 | # UnityHelper
2 |
3 | The UnityHelper contains a plethora of useful extensions and helpers for Transform, GameObject, Vector2/3/4, Rect and more.
4 |
5 | ## Examples
6 |
7 | ### Transform/Vector/Color
8 |
9 | ```C#
10 | /* Set the transform.position.x to 5 and z to 3. Keeps y.
11 | * Equivalent to:
12 | * var position = transform.position;
13 | * position.x = 5;
14 | * position.z = 3;
15 | * transform.position = position;
16 | */
17 | transform.SetPosition(x: 5, z: 3);
18 |
19 | // Same as above; only sets transform.localEulerAngles.y.
20 | // There are extension methods for all position/rotation/scales.
21 | transform.SetLocalEulerAngles(y: 180);
22 |
23 | // Similar methods are available for Vector2/3/4 and Color:
24 | // Gets the transform.position, but with y set to 0.
25 | Vector3 floorPosition = transform.position.Change3(y: 0);
26 |
27 | // Gets the material color, but sets the color.a value to 0.5.
28 | Color halfTransparentColor = GetComponent().sharedMaterial.color.ChangeAlpha(0.5f);
29 |
30 | // Sets the position/rotation of enemyIndicator to someEnemyTransform.position/rotation
31 | enemyIndicator.CopyPositionAndRotatationFrom(someEnemyTransform);
32 | ```
33 |
34 | ### Framerate-Independent Eased Lerping
35 |
36 | There are essentially two ways of lerping a value over time: linear (constant speed) or eased (e.g. getting slower the closer you are to the target, see http://easings.net.)
37 |
38 | For linear lerping (and most of the easing functions), you need to track the start and end positions and the time that elapsed.
39 |
40 | Calling something like `currentValue = Mathf.Lerp(currentValue, 1f, 0.95f);` every frame provides an easy way of eased lerping without tracking elapsed time or the starting value, but since it's called every frame, the actual traversed distance per second changes the higher the framerate is.
41 |
42 | EasedLerpFactor replaces the lerp parameter t to make it framerate-independent and easier to estimate.
43 |
44 | You can find more information about the formula used [here](https://www.scirra.com/blog/ashley/17/using-lerp-with-delta-time).
45 |
46 | You can use `MathHelper.EasedLerpFactor` to get the t used for a lerp or call `MathHelper.EasedLerp`, `UnityHelper.EasedLerpVector2`, `UnityHelper.EasedLerpVector3`, `UnityHelper.EasedLerpVector4` or `UnityHelper.EasedLerpColor` directly.
47 |
48 | 
49 |
50 | ```C#
51 | void Update()
52 | {
53 | // Get the world position of the mouse pointer
54 | Vector3 mousePositionWorld = Camera.main.ScreenToWorldPoint(Input.mousePosition);
55 | mousePositionWorld.z = 0f;
56 |
57 | // Set the runner position to the mouse pointer
58 | runner.position = mousePositionWorld;
59 |
60 | // Move the follower 75% of the remaining distance to the runner per second
61 | follower.position = UnityHelper.EasedLerpVector3(follower.position, runner.position, 0.75f);
62 |
63 | // ...which is the same as:
64 |
65 | //float t = MathHelper.EasedLerpFactor(0.75f);
66 | //follower.position = Vector3.Lerp(follower.position, mousePositionWorld, t);
67 | }
68 | ```
69 |
70 | ### Get the centroid from an array/list of Vector2/3/4
71 |
72 | ```C#
73 | Vector3[] list = {
74 | new Vector3(-5, 10, 12),
75 | new Vector3(55, 32, 10),
76 | new Vector3(85, -40, 80)
77 | };
78 |
79 | // Calculates the geometric center (the average) of the input list
80 | Debug.Log("Centroid: " + list.CalculateCentroid()); // => Centroid: (45.0, 0.7, 34.0)
81 | ```
82 |
83 | ### Vector2 Rotation
84 |
85 | ```C#
86 | // Create a length 1 Vector2 pointing 40 degrees away from (1.0, 0.0)
87 | var vector = UnityHelper.CreateVector2AngleDeg(20f);
88 | Debug.Log(vector); // => (0.9, 0.3)
89 |
90 | // Rotate the vector 70 degrees
91 | vector = vector.RotateDeg(70f);
92 | Debug.Log(vector); // => (0.0, 1.0)
93 |
94 | // Output the current vector rotation
95 | Debug.Log(vector.GetAngleDeg()); // => 90
96 | ```
97 |
98 | ### GameObject
99 |
100 | ```C#
101 | // Assigns layer 4 to this GameObject and all its children recursively
102 | gameObject.AssignLayerToHierarchy(4);
103 |
104 | // Create an instance of a prefab. When the prefab is named "Original", the instance will
105 | // be named "Original(Copy)"
106 | GameObject copiedGameObject = Instantiate(prefab);
107 |
108 | // Return the name without "(Copy)"
109 | Debug.Log(copiedGameObject.GetNameWithoutClone()); // => Original
110 |
111 | // Change the name back to "Original"
112 | copiedGameObject.StripCloneFromName();
113 | ```
114 |
115 | ### Rect
116 |
117 | ```C#
118 | // Make a rect from (10|20) to (60|120)
119 | Rect rect = new Rect(10, 20, 50, 100);
120 |
121 | // Gets a random position for an enemy in the rect, leaving a 5 unit border
122 | Vector2 enemySpawnPosition = rect.RandomPosition(-5);
123 |
124 | // Gets a random sub rect of size 10|10 in which we could spawn multiple enemies
125 | Rect enemySpawnSubrect = rect.RandomSubRect(10, 10);
126 |
127 | Vector2 enemyPosition = new Vector2(0, 500);
128 |
129 | // Clamp an enemy position to the rect
130 | enemyPosition = rect.Clamp2(enemyPosition);
131 | Debug.Log(enemyPosition); // Output: (10.0, 120.0)
132 |
133 | // Create a rect that is 10 units bigger to each side
134 | Rect biggerRect = rect.Extend(10);
135 |
136 | // Get the corner points
137 | Vector2[] cornerPoints = rect.GetCornerPoints();
138 | ```
139 |
140 | ### Random
141 |
142 | ```C#
143 | // Points in a random 2D direction
144 | var randomDirection2D = UnityHelper.RandomOnUnitCircle;
145 |
146 | // Either goes left or right
147 | var deltaX = 20 * UnityHelper.RandomSign;
148 |
149 | // Gets set to either choice
150 | var choice = UnityHelper.RandomBool ? "Choice A" : "Choice B";
151 | ```
152 |
153 | ### PlayerPrefs: Bool
154 |
155 | ```C#
156 | // Gets a PlayerPrefs key "FirstStart" or return true if not set
157 | bool isFirstStart = UnityHelper.PlayerPrefsGetBool("FirstStart", true);
158 |
159 | // Set the key FirstStart to false
160 | UnityHelper.PlayerPrefsSetBool("FirstStart", false);
161 | ```
162 |
163 | ### Check if a layer is included in a LayerMask
164 |
165 | ```C#
166 | // Does the layer mask contain layer 4?
167 | bool containsLayer4 = someLayerMask.ContainsLayer(4);
168 | ```
169 |
170 | ### Find out how big the level bounds are
171 |
172 | ```C#
173 | // Get the bounds of all colliders in the level to clamp the camera later on
174 | Collider[] allColliders = FindObjectsOfType();
175 | Bounds levelBounds = UnityHelper.CombineColliderBounds(allColliders);
176 | ```
177 |
178 | ### Calculate Camera viewport world size at distance
179 |
180 | ```C#
181 | // Find out how much the perspective camera can see at 10 unit away
182 | Vector2 viewportSizeAtDistance = Camera.main.CalculateViewportWorldSizeAtDistance(10);
183 | ```
184 |
185 | ### CharacterController: CapsuleCast
186 |
187 | ```C#
188 | Vector3 point1;
189 | Vector3 point2;
190 | float radius;
191 | Vector3 origin = playerCharacterController.transform.position;
192 |
193 | // Get the data for the capsule cast from the current player position
194 | UnityHelper.GetCapsuleCastData(playerCharacterController, origin, out point1, out point2, out radius);
195 |
196 | // Cast 2 units forwards
197 | bool hitSomething = Physics.CapsuleCast(point1, point2, radius, Vector3.forward, 2f);
198 | ```
199 |
200 | ## Dependencies
201 |
202 | * [MathHelper](https://github.com/TobiasWehrum/unity-utilities/tree/master/MathHelper)
--------------------------------------------------------------------------------
/UnityHelper/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: b6e34e3dba2edc24bb08650aff4b9f20
3 | timeCreated: 1465339531
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/UnityHelper/UnityHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 5f9bb454e61aeef47baa33c3d1273e8e
3 | timeCreated: 1465253549
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/XmlHelper.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 10a1937e9ab43024e840c2beff334731
3 | folderAsset: yes
4 | timeCreated: 1466344872
5 | licenseType: Pro
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/XmlHelper/README.md:
--------------------------------------------------------------------------------
1 | # XmlHelper
2 |
3 | The XmlHelper serializes and deserializes to/from XML and allows convenient access to optional element content and attributes when reading general XMLs.
4 |
5 | With a few exceptions (e.g. arrays of ArrayList and arrays of List), all public attributes and fields of any public class should be serialized without any
6 | further need to tag the elements. The only thing needed is a public default constructor.
7 |
8 | For finer control, see the MSDN documentation on XmlSerializer: https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=vs.110).aspx
9 |
10 | ## Examples
11 |
12 | ### String serialization
13 |
14 | ```C#
15 | public class TestData
16 | {
17 | // A public field - will be serialized
18 | public int field;
19 |
20 | // A private field with public property - will be serialized
21 | float property;
22 | public float Property
23 | {
24 | get { return property; }
25 | set { property = value;}
26 | }
27 |
28 | // An auto property - will be serialized
29 | public bool AutoProperty { get; set; }
30 |
31 | // A private field - will *not* be serialized
32 | string privateField = "Test";
33 |
34 | // A public field marked "XmlIgnore" - will *not* be serialized
35 | [XmlIgnore]
36 | public double publicNonSerialized = 5.5;
37 |
38 | // The public default constructor is needed for the XmlSerializer.
39 | public TestData()
40 | {
41 | }
42 |
43 | public TestData(int field, float property, bool autoProperty)
44 | {
45 | this.field = field;
46 | this.property = property;
47 | AutoProperty = autoProperty;
48 | }
49 | }
50 | ```
51 |
52 | ```C#
53 | // Create a new TestData object
54 | TestData data = new TestData(1, 2.3f, true);
55 |
56 | // Serialize the TestData object into a string
57 | string xmlString = data.SerializeToXmlString();
58 |
59 | /* Output:
60 |
61 |
62 |
63 | 1
64 | 2.3
65 | true
66 |
67 | */
68 | Debug.Log(xmlString);
69 |
70 | // Get the data back from the string
71 | TestData deserializedData = xmlString.DeserializeFromXmlString();
72 | ```
73 |
74 | ### XmlNode content/attributes
75 |
76 | ```C#
77 | // Create an XmlDocument with test data
78 | XmlDocument xmlDocument = new XmlDocument();
79 | xmlDocument.LoadXml("" +
80 | " " +
81 | " Grunt" +
82 | " " +
83 | " " +
84 | " " +
85 | " Tank" +
86 | " " +
87 | " true" +
88 | " " +
89 | "");
90 |
91 | // Read each enemyData element in the enemyList
92 | foreach (XmlNode enemyData in xmlDocument["enemyList"].ChildNodes)
93 | {
94 | // Get the name element content, if it exists, else set "???"
95 | string name = enemyData.GetElementString("name", "???");
96 |
97 | // Get the position element and then its attributes
98 | XmlNode position = enemyData["position"];
99 | int x = position.GetAttributeInt("x");
100 | int y = position.GetAttributeInt("y");
101 |
102 | // Get the ranged element content, if it exists, else set "false"
103 | bool ranged = enemyData.GetElementBool("ranged", false);
104 |
105 | // Output the result
106 | Debug.Log(string.Format("{0} at {1}|{2} is {3}",
107 | name,
108 | x,
109 | y,
110 | ranged ? "ranged" : "not ranged"));
111 | }
112 |
113 | /* Grunt at 5|3 is not ranged
114 | Tank at 7|1 is ranged
115 | */
116 | ```
117 |
118 | ## Dependencies
119 |
120 | None.
--------------------------------------------------------------------------------
/XmlHelper/README.md.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 417d0b881713b7045a00a27b80b46b1b
3 | timeCreated: 1466352001
4 | licenseType: Pro
5 | DefaultImporter:
6 | userData:
7 | assetBundleName:
8 | assetBundleVariant:
9 |
--------------------------------------------------------------------------------
/XmlHelper/XmlHelper.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.IO;
4 | using System.Xml;
5 | using System.Xml.Serialization;
6 |
7 | namespace UnityUtilities
8 | {
9 | ///
10 | /// The XmlHelper serializes and deserializes to/from XML and allows convenient
11 | /// access to optional element content and attributes when reading general XMLs.
12 | ///
13 | public static class XmlHelper
14 | {
15 | ///
16 | /// A dictionary of XmlSerializer, accessible by type. Used by .
17 | ///
18 | static Dictionary serializersByType = new Dictionary();
19 |
20 | ///
21 | /// A thread lock object to make access to threadsafe.
22 | ///
23 | #pragma warning disable 414
24 | static Object serializersByTypeLock = new object();
25 | #pragma warning restore 414
26 |
27 | ///
28 | /// Gets a cached XmlSerializer for the specified type.
29 | ///
30 | /// The type to get the XmlSerializer for.
31 | /// An XmlSerializer for the specified type.
32 | public static XmlSerializer GetSerializer()
33 | {
34 | lock (serializersByType)
35 | {
36 | var t = typeof (T);
37 | XmlSerializer serializer;
38 | if (!serializersByType.TryGetValue(t, out serializer))
39 | {
40 | serializer = new XmlSerializer(t);
41 | serializersByType[t] = serializer;
42 | }
43 | return serializer;
44 | }
45 | }
46 |
47 | ///
48 | /// Uses the XmlSerializer to serialize data into a string that can later
49 | /// be deserialized again via .
50 | ///
51 | /// With a few exceptions (e.g. arrays of ArrayList and arrays of List<T>),
52 | /// all public attributes and fields of any public class should be serialized
53 | /// without any further need to tag the elements. The only thing needed is
54 | /// a public default constructor.
55 | ///
56 | /// For finer control, see the MSDN document on XmlSerializer:
57 | /// https://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlserializer(v=vs.110).aspx
58 | ///
59 | /// The data type to be serialized.
60 | /// The data to be serialized.
61 | /// The serialized data string.
62 | public static string SerializeToXmlString(this T data)
63 | {
64 | using (var stringWriter = new StringWriter())
65 | {
66 | GetSerializer().Serialize(stringWriter, data);
67 | return stringWriter.ToString();
68 | }
69 | }
70 |
71 | ///
72 | /// Deserializes an object serialized with .
73 | ///
74 | /// Thedata type that was serialized.
75 | /// The serialized data string.
76 | /// The deserialized data.
77 | ///
78 | /// An error occurred during deserialization. The original exception is available
79 | /// using the InnerException property.
80 | ///
81 | public static T DeserializeFromXmlString(this string str)
82 | {
83 | using (var stringReader = new StringReader(str))
84 | {
85 | return (T) GetSerializer().Deserialize(stringReader);
86 | }
87 | }
88 |
89 | ///
90 | /// Gets the content of first child element with the specified name. If no child
91 | /// with that name exists, the defaultValue is returned.
92 | ///
93 | /// The XMlNode to get the child from.
94 | /// The name of the child.
95 | /// The default value if no child with that name exists.
96 | /// The content of the child if it exists; else the default value.
97 | public static string GetElementString(this XmlNode xmlNode, string name, string defaultValue = "")
98 | {
99 | var element = xmlNode[name];
100 | if (element == null)
101 | return defaultValue;
102 |
103 | return element.InnerText;
104 | }
105 |
106 | ///
107 | /// Gets the content of first child element with the specified name. If no child
108 | /// with that name exists, the defaultValue is returned.
109 | ///
110 | /// The XMlNode to get the child from.
111 | /// The name of the child.
112 | /// The default value if no child with that name exists.
113 | /// The content of the child if it exists; else the default value.
114 | /// The content is is not in the correct format.
115 | /// The content represents a number less than MinValue or greater than MaxValue.
116 | public static int GetElementInt(this XmlNode xmlNode, string name, int defaultValue = 0)
117 | {
118 | var element = xmlNode[name];
119 | if (element == null)
120 | return defaultValue;
121 |
122 | return int.Parse(element.InnerText);
123 | }
124 |
125 | ///
126 | /// Gets the content of first child element with the specified name. If no child
127 | /// with that name exists, the defaultValue is returned.
128 | ///
129 | /// The XMlNode to get the child from.
130 | /// The name of the child.
131 | /// The default value if no child with that name exists.
132 | /// The content of the child if it exists; else the default value.
133 | /// The content is is not in the correct format.
134 | /// The content represents a number less than MinValue or greater than MaxValue.
135 | public static float GetElementFloat(this XmlNode xmlNode, string name, float defaultValue = 0)
136 | {
137 | var element = xmlNode[name];
138 | if (element == null)
139 | return defaultValue;
140 |
141 | return float.Parse(element.InnerText);
142 | }
143 |
144 | ///
145 | /// Gets the content of first child element with the specified name. If no child
146 | /// with that name exists, the defaultValue is returned.
147 | ///
148 | /// The XMlNode to get the child from.
149 | /// The name of the child.
150 | /// The default value if no child with that name exists.
151 | /// The content of the child if it exists; else the default value.
152 | /// The content is is not in the correct format.
153 | /// The content represents a number less than MinValue or greater than MaxValue.
154 | public static bool GetElementBool(this XmlNode xmlNode, string name, bool defaultValue = false)
155 | {
156 | var element = xmlNode[name];
157 | if (element == null)
158 | return defaultValue;
159 |
160 | return bool.Parse(element.InnerText);
161 | }
162 |
163 | ///
164 | /// Gets the content of first attribute with the specified name. If no attribute
165 | /// with that name exists, the defaultValue is returned.
166 | ///
167 | /// The XMlNode to get the attribute from.
168 | /// The name of the attribute.
169 | /// The default value if no attribute with that name exists.
170 | /// The content of the attribute if it exists; else the default value.
171 | public static string GetAttributeString(this XmlNode xmlNode, string name, string defaultValue = "")
172 | {
173 | var attribute = xmlNode.Attributes[name];
174 | if (attribute == null)
175 | return defaultValue;
176 |
177 | return attribute.Value;
178 | }
179 |
180 | ///
181 | /// Gets the content of first attribute with the specified name. If no attribute
182 | /// with that name exists, the defaultValue is returned.
183 | ///
184 | /// The XMlNode to get the attribute from.
185 | /// The name of the attribute.
186 | /// The default value if no attribute with that name exists.
187 | /// The content of the attribute if it exists; else the default value.
188 | /// The content is is not in the correct format.
189 | /// The content represents a number less than MinValue or greater than MaxValue.
190 | public static int GetAttributeInt(this XmlNode xmlNode, string name, int defaultValue = 0)
191 | {
192 | var attribute = xmlNode.Attributes[name];
193 | if (attribute == null)
194 | return defaultValue;
195 |
196 | return int.Parse(attribute.Value);
197 | }
198 |
199 | ///
200 | /// Gets the content of first attribute with the specified name. If no attribute
201 | /// with that name exists, the defaultValue is returned.
202 | ///
203 | /// The XMlNode to get the attribute from.
204 | /// The name of the attribute.
205 | /// The default value if no attribute with that name exists.
206 | /// The content of the attribute if it exists; else the default value.
207 | /// The content is is not in the correct format.
208 | /// The content represents a number less than MinValue or greater than MaxValue.
209 | public static int? GetAttributeIntNullable(this XmlNode xmlNode, string name, int? defaultValue = null)
210 | {
211 | var attribute = xmlNode.Attributes[name];
212 | if (attribute == null)
213 | return defaultValue;
214 |
215 | return int.Parse(attribute.Value);
216 | }
217 |
218 | ///
219 | /// Gets the content of first attribute with the specified name. If no attribute
220 | /// with that name exists, the defaultValue is returned.
221 | ///
222 | /// The XMlNode to get the attribute from.
223 | /// The name of the attribute.
224 | /// The default value if no attribute with that name exists.
225 | /// The content of the attribute if it exists; else the default value.
226 | /// The content is is not in the correct format.
227 | /// The content represents a number less than MinValue or greater than MaxValue.
228 | public static float GetAttributeFloat(this XmlNode xmlNode, string name, float defaultValue = 0)
229 | {
230 | var attribute = xmlNode.Attributes[name];
231 | if (attribute == null)
232 | return defaultValue;
233 |
234 | return float.Parse(attribute.Value);
235 | }
236 |
237 | ///
238 | /// Gets the content of first attribute with the specified name. If no attribute
239 | /// with that name exists, the defaultValue is returned.
240 | ///
241 | /// The XMlNode to get the attribute from.
242 | /// The name of the attribute.
243 | /// The default value if no attribute with that name exists.
244 | /// The content of the attribute if it exists; else the default value.
245 | /// The content is is not in the correct format.
246 | /// The content represents a number less than MinValue or greater than MaxValue.
247 | public static float? GetAttributeFloatNullable(this XmlNode xmlNode, string name, float? defaultValue = null)
248 | {
249 | var attribute = xmlNode.Attributes[name];
250 | if (attribute == null)
251 | return defaultValue;
252 |
253 | return float.Parse(attribute.Value);
254 | }
255 |
256 | ///
257 | /// Gets the content of first attribute with the specified name. If no attribute
258 | /// with that name exists, the defaultValue is returned.
259 | ///
260 | /// The XMlNode to get the attribute from.
261 | /// The name of the attribute.
262 | /// The default value if no attribute with that name exists.
263 | /// The content of the attribute if it exists; else the default value.
264 | /// The content is is not in the correct format.
265 | public static bool GetAttributeBool(this XmlNode xmlNode, string name, bool defaultValue = false)
266 | {
267 | var attribute = xmlNode.Attributes[name];
268 | if (attribute == null)
269 | return defaultValue;
270 |
271 | return bool.Parse(attribute.Value);
272 | }
273 | }
274 | }
--------------------------------------------------------------------------------
/XmlHelper/XmlHelper.cs.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 3b2acd0274494544581360d5a51273ae
3 | timeCreated: 1466344872
4 | licenseType: Pro
5 | MonoImporter:
6 | serializedVersion: 2
7 | defaultReferences: []
8 | executionOrder: 0
9 | icon: {instanceID: 0}
10 | userData:
11 | assetBundleName:
12 | assetBundleVariant:
13 |
--------------------------------------------------------------------------------
/_Images.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 913c49f316b8a5241b405c3300a5fb3c
3 | folderAsset: yes
4 | timeCreated: 1462736436
5 | licenseType: Free
6 | DefaultImporter:
7 | userData:
8 | assetBundleName:
9 | assetBundleVariant:
10 |
--------------------------------------------------------------------------------
/_Images/CountdownPropertyExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasWehrum/unity-utilities/c78da2928b1f7b73046a697185271e7effeddd1f/_Images/CountdownPropertyExample.png
--------------------------------------------------------------------------------
/_Images/CountdownPropertyExample.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 77d7b8d5d2aa0b54c9511431d8cab308
3 | timeCreated: 1462736440
4 | licenseType: Free
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: 0
37 | lightmap: 0
38 | rGBM: 0
39 | compressionQuality: 50
40 | allowsAlphaSplitting: 0
41 | spriteMode: 1
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: 1
49 | textureType: 8
50 | buildTargetSettings: []
51 | spriteSheet:
52 | sprites: []
53 | outline: []
54 | spritePackingTag:
55 | userData:
56 | assetBundleName:
57 | assetBundleVariant:
58 |
--------------------------------------------------------------------------------
/_Images/EasedLerpFactorExample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasWehrum/unity-utilities/c78da2928b1f7b73046a697185271e7effeddd1f/_Images/EasedLerpFactorExample.gif
--------------------------------------------------------------------------------
/_Images/EasedLerpFactorExample.gif.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: a88f79c593407344a879cfbf8c0d2e94
3 | timeCreated: 1477158275
4 | licenseType: Free
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: 0
37 | lightmap: 0
38 | rGBM: 0
39 | compressionQuality: 50
40 | allowsAlphaSplitting: 0
41 | spriteMode: 1
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: 1
49 | spriteTessellationDetail: -1
50 | textureType: 8
51 | buildTargetSettings: []
52 | spriteSheet:
53 | serializedVersion: 2
54 | sprites: []
55 | outline: []
56 | spritePackingTag:
57 | userData:
58 | assetBundleName:
59 | assetBundleVariant:
60 |
--------------------------------------------------------------------------------
/_Images/NoiseOutputValueExample.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasWehrum/unity-utilities/c78da2928b1f7b73046a697185271e7effeddd1f/_Images/NoiseOutputValueExample.gif
--------------------------------------------------------------------------------
/_Images/NoiseOutputValueExample.gif.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: 860c1464aa19c2848acd724336e8c20a
3 | timeCreated: 1462745341
4 | licenseType: Free
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: 16
34 | mipBias: -1
35 | wrapMode: 1
36 | nPOTScale: 0
37 | lightmap: 0
38 | rGBM: 0
39 | compressionQuality: 50
40 | allowsAlphaSplitting: 0
41 | spriteMode: 1
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: 1
49 | textureType: 8
50 | buildTargetSettings: []
51 | spriteSheet:
52 | sprites: []
53 | outline: []
54 | spritePackingTag:
55 | userData:
56 | assetBundleName:
57 | assetBundleVariant:
58 |
--------------------------------------------------------------------------------
/_Images/RangeExample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/TobiasWehrum/unity-utilities/c78da2928b1f7b73046a697185271e7effeddd1f/_Images/RangeExample.png
--------------------------------------------------------------------------------
/_Images/RangeExample.png.meta:
--------------------------------------------------------------------------------
1 | fileFormatVersion: 2
2 | guid: d0c53fde2b1abc648b22728cef0f39b3
3 | timeCreated: 1462746431
4 | licenseType: Free
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: 0
37 | lightmap: 0
38 | rGBM: 0
39 | compressionQuality: 50
40 | allowsAlphaSplitting: 0
41 | spriteMode: 1
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: 1
49 | textureType: 8
50 | buildTargetSettings: []
51 | spriteSheet:
52 | sprites: []
53 | outline: []
54 | spritePackingTag:
55 | userData:
56 | assetBundleName:
57 | assetBundleVariant:
58 |
--------------------------------------------------------------------------------