using System; using System.Collections.Generic; using System.Linq; using UnityEngine; using Random = UnityEngine.Random; namespace Assets.Scripts.Utils { public static class RandomUtil { /// <summary> /// Return random bool value. /// </summary> public static bool NextBool() { return Random.Range(0, 2) == 0; } /// <summary> /// Return random item from item1 and item2 set. /// </summary> public static T Next<T>(T item1, T item2) { return NextBool() ? item1 : item2; } /// <summary> /// Return random item from item1, item2 and item3 set. /// </summary> public static T Next<T>(T item1, T item2, T item3) { int n = Random.Range(0, 3); return n == 0 ? item1 : (n == 1 ? item2 : item3); } /// <summary> /// Return random item from array. /// </summary> public static T NextItem<T>(T[] array) { return array[Random.Range(0, array.Length)]; } /// <summary> /// Return random item from list. /// </summary> public static T NextItem<T>(List<T> list) { return list[Random.Range(0, list.Count)]; } /// <summary> /// Return random enum item. /// </summary> public static T NextEnum<T>() { var values = Enum.GetValues(typeof(T)); return (T)values.GetValue(Random.Range(0, values.Length)); } /// <summary> /// Return random index of passed array. Index random selection is based on array weights. /// </summary> public static int NextWeightedInd(int[] weights) { int randomPoint = Random.Range(0, weights.Sum()) + 1; int sum = 0; for (int i = 0; i < weights.Length; i++) { sum += weights[i]; if (randomPoint <= sum) return i; } throw new Exception("Logic error!"); } /// <summary> /// Return random index of passed array. Index random selection is based on array weights. /// </summary> public static int NextWeightedInd(float[] weights) { float randomPoint = Random.Range(0f, weights.Sum()); float sum = 0f; for (int i = 0; i < weights.Length; i++) { sum += weights[i]; if (randomPoint <= sum) return i; } throw new Exception("Logic error!"); } /// <summary> /// Return sub-list of random items from origin list without repeating. /// </summary> public static List<T> Take<T>(IList<T> list, int count) { List<T> items = new List<T>(); List<int> remainedIndexes = Enumerable.Range(0, list.Count).ToList(); for (int i = 0; i < count; i++) { int selectedIndex = NextItem(remainedIndexes); remainedIndexes.Remove(selectedIndex); items.Add(list[selectedIndex]); } return items; } /// <summary> /// Shuffle list of items. /// </summary> public static void Shuffle<T>(this List<T> list) { for (int i = 1; i < list.Count; i++) { int indRnd = Random.Range(0, i + 1); T temp = list[i]; list[i] = list[indRnd]; list[indRnd] = temp; } } /// <summary> /// Shuffle array of items. /// </summary> public static void Shuffle<T>(T[] array) { for (int i = 1; i < array.Length; i++) { int indRnd = Random.Range(0, i + 1); T temp = array[i]; array[i] = array[indRnd]; array[indRnd] = temp; } } /// <summary> /// Return random point on line. /// </summary> public static Vector2 NextPointOnLine(Vector2 point1, Vector2 point2) { float t = Random.Range(0f, 1f); return new Vector2(Mathf.Lerp(point1.x, point2.x, t), Mathf.Lerp(point1.y, point2.y, t)); } /// <summary> /// Return random point on line. /// </summary> public static Vector3 NextPointOnLine(Vector3 point1, Vector3 point2) { float t = Random.Range(0f, 1f); return new Vector3(Mathf.Lerp(point1.x, point2.x, t), Mathf.Lerp(point1.y, point2.y, t), Mathf.Lerp(point1.z, point2.z, t)); } /// <summary> /// Get a chance with given percentage. If percentage is 25 it will return true each 4th time on an average. /// </summary> public static bool GetChance(int percentage) { return Random.Range(0, 100) + 1 <= percentage; } /// <summary> /// Gets a chance with give probability. If probability is 0.25 it will return true each 4th time on an average. /// </summary> public static bool GetChance(float probability) { return Random.Range(0f, 1f) < probability; } /// <summary> /// Get random normalized 2D direction as Vector2. /// </summary> public static Vector2 NextDirection() { return Random.insideUnitCircle.normalized; } /// <summary> /// Return Random.Range between two values which are stored in pairMinMax Vector2. /// Where pairMinMax.x is min value and pairMinMax.y is max value. /// </summary> public static float Range(Vector2 pairMinMax) { return Random.Range(pairMinMax.x, pairMinMax.y); } /// <summary> /// Return random point from rect bound (inside rect). /// </summary> public static Vector2 NextPointOnRect(Rect rect) { return new Vector2(Random.Range(rect.xMin, rect.xMax), Random.Range(rect.yMin, rect.yMax)); } /// <summary> /// Return random point on rect border (perimeter of rect). /// </summary> public static Vector2 NextPointOnRectBorder(Rect rect) { float perimeterLength = (rect.width + rect.height) * 2f; float pointOnPerimeter = Random.Range(0f, perimeterLength); if (pointOnPerimeter < rect.width)//top border return new Vector2(rect.xMin + pointOnPerimeter, rect.yMax); pointOnPerimeter -= rect.width; if (pointOnPerimeter < rect.height)//right border return new Vector2(rect.xMax, rect.yMin + pointOnPerimeter); pointOnPerimeter -= rect.height; if (pointOnPerimeter < rect.width)//bottom border return new Vector2(rect.xMin + pointOnPerimeter, rect.yMin); pointOnPerimeter -= rect.width; //left border return new Vector2(rect.xMin, rect.yMin + pointOnPerimeter); } } }