22// Purpose: Various static maths helper methods
33// Created by: DavidFDev
44
5+ using System . Diagnostics . Contracts ;
6+ using UnityEngine ;
7+
58namespace DavidFDev . Maths
69{
710 public static class MathsHelper
811 {
12+ /// <summary>
13+ /// Shift the start value towards the end value without exceeding.
14+ /// </summary>
15+ /// <param name="start"></param>
16+ /// <param name="end"></param>
17+ /// <param name="shift"></param>
18+ /// <returns></returns>
19+ [ Pure ]
20+ public static float Approach ( float start , float end , float shift )
21+ {
22+ if ( start < end )
23+ {
24+ return Mathf . Min ( start + shift , end ) ;
25+ }
26+
27+ return Mathf . Max ( start - shift , end ) ;
28+ }
29+
30+ /// <summary>
31+ /// Shift the start angle towards the end angle (degrees).
32+ /// </summary>
33+ /// <param name="start"></param>
34+ /// <param name="end"></param>
35+ /// <param name="shift"></param>
36+ /// <returns></returns>
37+ [ Pure ]
38+ public static float ApproachAngle ( float start , float end , float shift )
39+ {
40+ float deltaAngle = Mathf . DeltaAngle ( start , end ) ;
41+ if ( - shift < deltaAngle && deltaAngle < shift )
42+ {
43+ return end ;
44+ }
45+
46+ return Mathf . Repeat ( Approach ( start , start + deltaAngle , shift ) , 360f ) ;
47+ }
48+
49+ /// <summary>
50+ /// Shift the start value towards zero without exceeding.
51+ /// </summary>
52+ /// <param name="start"></param>
53+ /// <param name="shift"></param>
54+ /// <returns></returns>
55+ [ Pure ]
56+ public static float Reduce ( float start , float shift )
57+ {
58+ return Approach ( start , 0f , shift ) ;
59+ }
60+
61+ /// <summary>
62+ /// Shift the start angle towards zero (degrees).
63+ /// </summary>
64+ /// <param name="start"></param>
65+ /// <param name="shift"></param>
66+ /// <returns></returns>
67+ [ Pure ]
68+ public static float ReduceAngle ( float start , float shift )
69+ {
70+ return ApproachAngle ( start , 0f , shift ) ;
71+ }
72+
73+ /// <summary>
74+ /// Pulse between min and max using a sine wave.
75+ /// </summary>
76+ /// <param name="time">Increasing value (e.g. Time.time).</param>
77+ /// <param name="frequency">How many min..max..min per second (lower is slower).</param>
78+ /// <param name="min"></param>
79+ /// <param name="max"></param>
80+ /// <returns></returns>
81+ [ Pure ]
82+ public static float Pulse ( float time , float frequency , float min , float max )
83+ {
84+ float half = ( max - min ) * 0.5f ;
85+ return min + half + Mathf . Sin ( 2f * Mathf . PI * frequency * time ) * half ;
86+ }
87+
88+ /// <summary>
89+ /// Alternate between true and false using a sine wave.
90+ /// </summary>
91+ /// <param name="time">Increasing value (e.g. Time.time).</param>
92+ /// <param name="frequency">How many false..true..false per second (lower is slower).</param>
93+ /// <returns></returns>
94+ [ Pure ]
95+ public static bool FlipFlop ( float time , float frequency )
96+ {
97+ return Pulse ( time , frequency , 0f , 1f ) >= 0.5f ;
98+ }
99+
100+ /// <summary>
101+ /// Alternate between true and false using a sine wave, only returning true when it's at its peak.
102+ /// </summary>
103+ /// <param name="time">Increasing value (e.g. Time.time).</param>
104+ /// <param name="frequency">Blip speed (lower is slower).</param>
105+ /// <returns></returns>
106+ [ Pure ]
107+ public static bool Blip ( float time , float frequency )
108+ {
109+ return Pulse ( time , frequency , 0f , 1f ) == 1f ;
110+ }
111+
112+ /// <summary>
113+ /// Sign method that returns -1, 0 or +1 depending on the sign of a given value.
114+ /// </summary>
115+ /// <param name="value"></param>
116+ /// <returns></returns>
117+ [ Pure ]
118+ public static float Sign ( float value )
119+ {
120+ return value < 0f ? - 1f : ( value > 0f ? 1f : 0f ) ;
121+ }
122+
123+ /// <summary>
124+ /// Retrive the sign of a value if it's over the threshold, otherwise return zero.
125+ /// </summary>
126+ /// <param name="value"></param>
127+ /// <param name="threshold"></param>
128+ /// <returns></returns>
129+ [ Pure ]
130+ public static float SignThreshold ( float value , float threshold )
131+ {
132+ return Mathf . Abs ( value ) >= threshold ? Sign ( value ) : 0f ;
133+ }
134+
135+ /// <summary>
136+ /// Get a vector with its original components passed through Sign().
137+ /// </summary>
138+ /// <param name="value"></param>
139+ /// <returns></returns>
140+ [ Pure ]
141+ public static Vector2 Sign ( Vector2 value )
142+ {
143+ return new Vector2 ( Sign ( value . x ) , Sign ( value . y ) ) ;
144+ }
145+
146+ /// <summary>
147+ /// Get a vector with its original components passed through Sign().
148+ /// </summary>
149+ /// <param name="value"></param>
150+ /// <returns></returns>
151+ [ Pure ]
152+ public static Vector3 Sign ( Vector3 value )
153+ {
154+ return new Vector3 ( Sign ( value . x ) , Sign ( value . y ) , Sign ( value . z ) ) ;
155+ }
156+
157+ /// <summary>
158+ /// Check if a value is between min and max (inclusive).
159+ /// </summary>
160+ /// <param name="value"></param>
161+ /// <param name="min"></param>
162+ /// <param name="max"></param>
163+ /// <returns></returns>
164+ [ Pure ]
165+ public static bool Between ( float value , float min , float max )
166+ {
167+ return value >= min && value <= max ;
168+ }
169+
170+ /// <summary>
171+ /// Check if a value is between min and max (inclusive).
172+ /// </summary>
173+ /// <param name="value"></param>
174+ /// <param name="min"></param>
175+ /// <param name="max"></param>
176+ /// <returns></returns>
177+ [ Pure ]
178+ public static bool Between ( int value , int min , int max )
179+ {
180+ return value >= min && value <= max ;
181+ }
182+
183+ /// <summary>
184+ /// Check if a value is even.
185+ /// </summary>
186+ /// <param name="value"></param>
187+ /// <returns></returns>
188+ [ Pure ]
189+ public static bool IsEven ( int value )
190+ {
191+ return value % 2 == 0 ;
192+ }
193+
194+ /// <summary>
195+ /// Check if a value is odd.
196+ /// </summary>
197+ /// <param name="value"></param>
198+ /// <returns></returns>
199+ [ Pure ]
200+ public static bool IsOdd ( int value )
201+ {
202+ return ! IsEven ( value ) ;
203+ }
204+
205+ /// <summary>
206+ /// Map a value from some arbitrary range to the 0 to 1 range.
207+ /// </summary>
208+ /// <param name="value"></param>
209+ /// <param name="min"></param>
210+ /// <param name="max"></param>
211+ /// <returns></returns>
212+ [ Pure ]
213+ public static float Map01 ( float value , float min , float max )
214+ {
215+ return ( value - min ) * 1f / ( max - min ) ;
216+ }
217+
218+ /// <summary>
219+ /// Map a value from some arbitrary range to the 1 to 0 range.
220+ /// </summary>
221+ /// <param name="value"></param>
222+ /// <param name="min"></param>
223+ /// <param name="max"></param>
224+ /// <returns></returns>
225+ [ Pure ]
226+ public static float Map10 ( float value , float min , float max )
227+ {
228+ return 1f - Map01 ( value , min , max ) ;
229+ }
230+
231+ /// <summary>
232+ /// Map a value from one range to another range.
233+ /// </summary>
234+ /// <param name="value"></param>
235+ /// <param name="from1"></param>
236+ /// <param name="from2"></param>
237+ /// <param name="to1"></param>
238+ /// <param name="to2"></param>
239+ /// <returns></returns>
240+ [ Pure ]
241+ public static float Map ( float value , float from1 , float from2 , float to1 , float to2 )
242+ {
243+ return ( value - from1 ) / ( to1 - from1 ) * ( to2 - from2 ) + from2 ;
244+ }
245+
246+ /// <summary>
247+ /// Convert from an angle (degrees) to a 2d direction.
248+ /// </summary>
249+ /// <param name="degrees"></param>
250+ /// <returns></returns>
251+ [ Pure ]
252+ public static Vector2 GetDirection ( float degrees )
253+ {
254+ return new Vector2 ( Mathf . Cos ( degrees * Mathf . Deg2Rad ) , Mathf . Sin ( degrees * Mathf . Deg2Rad ) ) ;
255+ }
256+
257+ /// <summary>
258+ /// Convert from a 2d direction to an angle (degrees).
259+ /// </summary>
260+ /// <param name="direction"></param>
261+ /// <returns></returns>
262+ [ Pure ]
263+ public static float GetAngle ( Vector2 direction )
264+ {
265+ return Mathf . Atan2 ( direction . y , direction . x ) * Mathf . Rad2Deg ;
266+ }
267+
268+ /// <summary>
269+ /// Retrieve the angle (degrees) between two 2d directions.
270+ /// </summary>
271+ /// <param name="directionA"></param>
272+ /// <param name="directionB"></param>
273+ /// <returns></returns>
274+ [ Pure ]
275+ public static float GetAngleBetween ( Vector2 directionA , Vector2 directionB )
276+ {
277+ return GetAngle ( directionA - directionB ) ;
278+ }
279+
280+ /// <summary>
281+ /// Check if a target 2d position is within a cone projected from the source 2d position.
282+ /// </summary>
283+ /// <param name="source"></param>
284+ /// <param name="target"></param>
285+ /// <param name="coneDirection"></param>
286+ /// <param name="degrees"></param>
287+ /// <returns></returns>
288+ [ Pure ]
289+ public static bool WithinAngle ( Vector2 source , Vector2 target , Vector2 coneDirection , float degrees )
290+ {
291+ Vector2 direction = ( target - source ) . normalized ;
292+ float cosAngle = Vector2 . Dot ( direction , coneDirection ) ;
293+ float angle = Mathf . Acos ( cosAngle ) * Mathf . Rad2Deg ;
294+ return angle < degrees ;
295+ }
296+
297+ /// <summary>
298+ /// Rotate a vector by an angle (degrees).
299+ /// </summary>
300+ /// <param name="value"></param>
301+ /// <param name="degrees"></param>
302+ /// <returns></returns>
303+ [ Pure ]
304+ public static Vector2 RotateVector ( Vector2 value , float degrees )
305+ {
306+ return GetDirection ( GetAngle ( value ) + degrees ) ;
307+ }
308+
309+ /// <summary>
310+ /// Rotate a vector around a pivot point by an angle (degrees).
311+ /// </summary>
312+ /// <param name="value"></param>
313+ /// <param name="degrees"></param>
314+ /// <param name="pivot"></param>
315+ /// <returns></returns>
316+ [ Pure ]
317+ public static Vector2 RotateVector ( Vector2 value , float degrees , Vector2 pivot )
318+ {
319+ Vector2 direction = value - pivot ;
320+ direction = Quaternion . Euler ( 0f , 0f , degrees ) * direction ;
321+ return direction + pivot ;
322+ }
9323 }
10324}
0 commit comments