using UnityEngine; using UnityEngine.UI; using System.Collections; using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Linq; #if UNITY_EDITOR using UnityEditor; #endif namespace MoreMountains.Tools { /// /// Debug helpers /// public static class MMDebug { #region Commands // the cached list of debug log commands private static MethodInfo[] _commands; // the max length of the log private static readonly int _logHistoryMaxLength = 256; #if UNITY_EDITOR private static bool _debugDrawEnabledSet = false; #endif private static bool _debugDrawEnabled = false; private static bool _debugLogEnabled = false; private static bool _debugLogEnabledSet = false; /// /// Returns a list of all the debug command lines found in the project's assemblies /// public static MethodInfo[] Commands { get { if (_commands == null) { _commands = AppDomain.CurrentDomain.GetAssemblies() .SelectMany( m => m.GetTypes().SelectMany( n => n.GetMethods(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public) .Where(o => o.GetCustomAttribute() != null))).ToArray(); } return _commands; } } /// /// Tries to input a command /// /// public static void DebugLogCommand(string command) { // if the command is empty we output an empty line if (command == string.Empty || command == null) { LogCommand("", "#ff2a00"); return; } // we split around spaces string[] splitCommand = command.Split(new char[] { ' ' }, System.StringSplitOptions.RemoveEmptyEntries); if (splitCommand == null || splitCommand.Length == 0) { LogCommand("Empty command", "#ff2a00"); return; } // we check if the first command exists string commandFirst = MMString.UppercaseFirst(splitCommand[0]); MethodInfo[] methods = Commands.Where(m => m.Name == commandFirst).ToArray(); if (methods.Length == 0) { LogCommand("Command " + commandFirst + " not found.", "#ff2a00"); return; } MethodInfo commandInfo; object[] parameters = null; if (splitCommand.Length > 1) { // if there are arguments commandInfo = methods.Where(m => m.GetParameters().Length > 0).FirstOrDefault(); if (commandInfo == null) { LogCommand("A version of command " + commandFirst + " with arguments could not be found. Maybe try without arguments.", "#ff2a00"); return; } MMDebugLogCommandArgumentCountAttribute argumentAttribute = commandInfo.GetCustomAttributes(true).FirstOrDefault(); if (argumentAttribute != null && argumentAttribute.ArgumentCount > splitCommand.Length - 1) { LogCommand("A version of command " + commandFirst + " needs at least " + argumentAttribute.ArgumentCount + " arguments.", "#ff2a00"); return; } parameters = new object[] { splitCommand }; } else { // if there are no arguments commandInfo = methods.Where(m => m.GetParameters().Length == 0).FirstOrDefault(); if (commandInfo == null) { LogCommand("A version of command " + commandFirst + " without arguments could not be found.", "#ff2a00"); return; } } LogCommand(command, "#FFC400"); methods[0].Invoke(null, parameters); } /// /// Logs the command, adding it to the log history and triggers an event /// /// /// private static void LogCommand(string command, string color) { DebugLogItem item = new DebugLogItem(command, color, Time.frameCount, Time.time, 3, true); LogHistory.Add(item); MMDebugLogEvent.Trigger(new DebugLogItem(null, "", Time.frameCount, Time.time, 0, false)); } #endregion #region DebugLog /// /// A struct used to store log items /// public struct DebugLogItem { public object Message; public string Color; public int Framecount; public float Time; public int TimePrecision; public bool DisplayFrameCount; public DebugLogItem(object message, string color, int framecount, float time, int timePrecision, bool displayFrameCount) { Message = message; Color = color; Framecount = framecount; Time = time; TimePrecision = timePrecision; DisplayFrameCount = displayFrameCount; } } /// /// A list of all the debug logs (up to DebugLogMaxLength entries) /// public static List LogHistory = new List(_logHistoryMaxLength); /// /// Returns a string with all log history condensed /// public static string LogHistoryText { get { string colorPrefix = ""; string colorSuffix = ""; StringBuilder log = new StringBuilder(); for (int i = 0; i < LogHistory.Count; i++) { // colors if (!string.IsNullOrEmpty(LogHistory[i].Color)) { colorPrefix = ""; colorSuffix = ""; } // build output if (LogHistory[i].DisplayFrameCount) { log.Append("[" + LogHistory[i].Framecount + "] "); } log.Append("[" + MMTime.FloatToTimeString(LogHistory[i].Time, false, true, true, true) + "] "); log.Append(colorPrefix + LogHistory[i].Message + colorSuffix); log.Append(Environment.NewLine); } return log.ToString(); } } /// /// Clears the debug log /// public static void DebugLogClear() { LogHistory.Clear(); MMDebugLogEvent.Trigger(new DebugLogItem(null, "", Time.frameCount, Time.time, 0, false)); } /// /// Outputs the message object to the console, prefixed with the current timestamp /// /// Message. public static void DebugLogTime(object message, string color = "", int timePrecision = 3, bool displayFrameCount = true) { if (!DebugLogsEnabled) { return; } // colors string colorPrefix = ""; string colorSuffix = ""; if (!string.IsNullOrEmpty(color)) { colorPrefix = ""; colorSuffix = ""; } // build output string output = ""; if (displayFrameCount) { output += "[" + Time.frameCount + "] "; } output += "[" + MMTime.FloatToTimeString(Time.time, false, true, true, true) + "] "; output += colorPrefix + message + colorSuffix; // we output to the console Debug.Log(output); DebugLogItem item = new DebugLogItem(message, color, Time.frameCount, Time.time, timePrecision, displayFrameCount); // we add to our DebugLog if (LogHistory.Count > _logHistoryMaxLength) { LogHistory.RemoveAt(0); } LogHistory.Add(item); // we trigger an event MMDebugLogEvent.Trigger(item); } /// /// An event used to broadcast debug logs /// public struct MMDebugLogEvent { public delegate void Delegate(DebugLogItem item); static private event Delegate OnEvent; static public void Register(Delegate callback) { OnEvent += callback; } static public void Unregister(Delegate callback) { OnEvent -= callback; } static public void Trigger(DebugLogItem item) { OnEvent?.Invoke(item); } } #endregion #region EnableDisableDebugs /// /// whether or not debug logs (MMDebug.DebugLogTime, MMDebug.DebugOnScreen) should be displayed /// public static bool DebugLogsEnabled { get { if (_debugLogEnabledSet) { return _debugLogEnabled; } if (PlayerPrefs.HasKey(_editorPrefsDebugLogs)) { _debugLogEnabled = (PlayerPrefs.GetInt(_editorPrefsDebugLogs) == 0) ? false : true; } else { _debugLogEnabled = true; } _debugLogEnabledSet = true; return _debugLogEnabled; } private set { } } /// /// whether or not debug draws should be executed /// public static bool DebugDrawEnabled { get { #if UNITY_EDITOR if (_debugDrawEnabledSet) { return _debugDrawEnabled; } if (PlayerPrefs.HasKey(_editorPrefsDebugDraws)) { _debugDrawEnabled = (PlayerPrefs.GetInt(_editorPrefsDebugDraws) == 0) ? false : true; } else { _debugDrawEnabled = true; } _debugDrawEnabledSet = true; return _debugDrawEnabled; #else return false; #endif } private set { } } private const string _editorPrefsDebugLogs = "DebugLogsEnabled"; private const string _editorPrefsDebugDraws = "DebugDrawsEnabled"; /// /// Enables or disables debug logs /// /// public static void SetDebugLogsEnabled(bool status) { DebugLogsEnabled = status; _debugLogEnabled = status; #if UNITY_EDITOR int newStatus = status ? 1 : 0; PlayerPrefs.SetInt(_editorPrefsDebugLogs, newStatus); #endif } /// /// Enables or disables debug draws /// /// public static void SetDebugDrawEnabled(bool status) { DebugDrawEnabled = status; _debugDrawEnabled = status; #if UNITY_EDITOR int newStatus = status ? 1 : 0; PlayerPrefs.SetInt(_editorPrefsDebugDraws, newStatus); #endif } #endregion #region Casts /// /// Draws a debug ray in 2D and does the actual raycast /// /// The raycast hit. /// Ray origin point. /// Ray direction. /// Ray distance. /// Mask. /// If set to true debug. /// Color. public static RaycastHit2D RayCast(Vector2 rayOriginPoint, Vector2 rayDirection, float rayDistance, LayerMask mask, Color color,bool drawGizmo=false) { if (drawGizmo && DebugDrawEnabled) { Debug.DrawRay (rayOriginPoint, rayDirection * rayDistance, color); } return Physics2D.Raycast(rayOriginPoint,rayDirection,rayDistance,mask); } /// /// Does a boxcast and draws a box gizmo /// /// /// /// /// /// /// /// /// /// public static RaycastHit2D BoxCast(Vector2 origin, Vector2 size, float angle, Vector2 direction, float length, LayerMask mask, Color color, bool drawGizmo = false) { if (drawGizmo && DebugDrawEnabled) { Quaternion rotation = Quaternion.Euler(0f, 0f, angle); Vector3[] points = new Vector3[8]; float halfSizeX = size.x / 2f; float halfSizeY = size.y / 2f; points[0] = rotation * (origin + (Vector2.left * halfSizeX) + (Vector2.up * halfSizeY)); // top left points[1] = rotation * (origin + (Vector2.right * halfSizeX) + (Vector2.up * halfSizeY)); // top right points[2] = rotation * (origin + (Vector2.right * halfSizeX) - (Vector2.up * halfSizeY)); // bottom right points[3] = rotation * (origin + (Vector2.left * halfSizeX) - (Vector2.up * halfSizeY)); // bottom left points[4] = rotation * ((origin + Vector2.left * halfSizeX + Vector2.up * halfSizeY) + length * direction); // top left points[5] = rotation * ((origin + Vector2.right * halfSizeX + Vector2.up * halfSizeY) + length * direction); // top right points[6] = rotation * ((origin + Vector2.right * halfSizeX - Vector2.up * halfSizeY) + length * direction); // bottom right points[7] = rotation * ((origin + Vector2.left * halfSizeX - Vector2.up * halfSizeY) + length * direction); // bottom left Debug.DrawLine(points[0], points[1], color); Debug.DrawLine(points[1], points[2], color); Debug.DrawLine(points[2], points[3], color); Debug.DrawLine(points[3], points[0], color); Debug.DrawLine(points[4], points[5], color); Debug.DrawLine(points[5], points[6], color); Debug.DrawLine(points[6], points[7], color); Debug.DrawLine(points[7], points[4], color); Debug.DrawLine(points[0], points[4], color); Debug.DrawLine(points[1], points[5], color); Debug.DrawLine(points[2], points[6], color); Debug.DrawLine(points[3], points[7], color); } return Physics2D.BoxCast(origin, size, angle, direction, length, mask); } /// /// Draws a debug ray without allocating memory /// /// The ray cast non alloc. /// Array. /// Ray origin point. /// Ray direction. /// Ray distance. /// Mask. /// Color. /// If set to true draw gizmo. public static RaycastHit2D MonoRayCastNonAlloc(RaycastHit2D[] array, Vector2 rayOriginPoint, Vector2 rayDirection, float rayDistance, LayerMask mask, Color color,bool drawGizmo=false) { if (drawGizmo && DebugDrawEnabled) { Debug.DrawRay (rayOriginPoint, rayDirection * rayDistance, color); } if (Physics2D.RaycastNonAlloc(rayOriginPoint, rayDirection, array, rayDistance, mask) > 0) { return array[0]; } return new RaycastHit2D(); } /// /// Draws a debug ray in 3D and does the actual raycast /// /// The raycast hit. /// Ray origin point. /// Ray direction. /// Ray distance. /// Mask. /// If set to true debug. /// Color. /// If set to true draw gizmo. public static RaycastHit Raycast3D(Vector3 rayOriginPoint, Vector3 rayDirection, float rayDistance, LayerMask mask, Color color,bool drawGizmo=false) { if (drawGizmo && DebugDrawEnabled) { Debug.DrawRay (rayOriginPoint, rayDirection * rayDistance, color); } RaycastHit hit; Physics.Raycast(rayOriginPoint, rayDirection, out hit, rayDistance, mask); return hit; } #endregion #region DebugOnScreen //public static MMConsole _console; public static MMDebugOnScreenConsole _console; private const string _debugConsolePrefabPath = "MMDebugOnScreenConsole"; /// /// Instantiates a MMConsole if there isn't one already, and adds the message in parameter to it. /// /// Message. public static void DebugOnScreen(string message) { if (!DebugLogsEnabled) { return; } InstantiateOnScreenConsole(); _console.AddMessage(message, "", 30); } /// /// Instantiates a MMConsole if there isn't one already, and displays the label in bold and its value next to it. /// /// Label. /// Value. /// The optional font size. public static void DebugOnScreen(string label, object value, int fontSize=25) { if (!DebugLogsEnabled) { return; } InstantiateOnScreenConsole(fontSize); _console.AddMessage(label, value, fontSize); } /// /// Instantiates the on screen console if there isn't one already /// public static void InstantiateOnScreenConsole(int fontSize=25) { if (!DebugLogsEnabled) { return; } if (_console == null) { // we try to find one in the scene _console = (MMDebugOnScreenConsole) GameObject.FindObjectOfType(typeof(MMDebugOnScreenConsole)); } if (_console == null) { // we instantiate the console GameObject loaded = UnityEngine.Object.Instantiate(Resources.Load(_debugConsolePrefabPath) as GameObject); loaded.name = "MMDebugOnScreenConsole"; _console = loaded.GetComponent(); } } /// /// Use this method to specify what console to use /// /// public static void SetOnScreenConsole(MMDebugOnScreenConsole newConsole) { _console = newConsole; } #endregion #region DebugDraw /// /// Draws a gizmo arrow going from the origin position and along the direction Vector3 /// /// Origin. /// Direction. /// Color. public static void DrawGizmoArrow(Vector3 origin, Vector3 direction, Color color, float arrowHeadLength = 3f, float arrowHeadAngle = 25f) { if (!DebugDrawEnabled) { return; } Gizmos.color = color; Gizmos.DrawRay(origin, direction); DrawArrowEnd(true, origin, direction, color, arrowHeadLength, arrowHeadAngle); } /// /// Draws a debug arrow going from the origin position and along the direction Vector3 /// /// Origin. /// Direction. /// Color. public static void DebugDrawArrow(Vector3 origin, Vector3 direction, Color color, float arrowHeadLength = 0.2f, float arrowHeadAngle = 35f) { if (!DebugDrawEnabled) { return; } Debug.DrawRay(origin, direction, color); DrawArrowEnd(false,origin,direction,color,arrowHeadLength,arrowHeadAngle); } /// /// Draws a debug arrow going from the origin position and along the direction Vector3 /// /// Origin. /// Direction. /// Color. /// Arrow length. /// Arrow head length. /// Arrow head angle. public static void DebugDrawArrow(Vector3 origin, Vector3 direction, Color color, float arrowLength, float arrowHeadLength = 0.20f, float arrowHeadAngle = 35.0f) { if (!DebugDrawEnabled) { return; } Debug.DrawRay(origin, direction * arrowLength, color); DrawArrowEnd(false,origin,direction * arrowLength,color,arrowHeadLength,arrowHeadAngle); } /// /// Draws a debug cross of the specified size and color at the specified point /// /// Spot. /// Cross size. /// Color. public static void DebugDrawCross (Vector3 spot, float crossSize, Color color) { if (!DebugDrawEnabled) { return; } Vector3 tempOrigin = Vector3.zero; Vector3 tempDirection = Vector3.zero; tempOrigin.x = spot.x - crossSize / 2; tempOrigin.y = spot.y - crossSize / 2; tempOrigin.z = spot.z ; tempDirection.x = 1; tempDirection.y = 1; tempDirection.z = 0; Debug.DrawRay (tempOrigin, tempDirection * crossSize, color); tempOrigin.x = spot.x - crossSize / 2; tempOrigin.y = spot.y + crossSize / 2; tempOrigin.z = spot.z ; tempDirection.x = 1; tempDirection.y = -1; tempDirection.z = 0; Debug.DrawRay (tempOrigin, tempDirection * crossSize, color); } /// /// Draws the arrow end for DebugDrawArrow /// /// If set to true draw gizmos. /// Arrow end position. /// Direction. /// Color. /// Arrow head length. /// Arrow head angle. private static void DrawArrowEnd (bool drawGizmos, Vector3 arrowEndPosition, Vector3 direction, Color color, float arrowHeadLength = 0.25f, float arrowHeadAngle = 40.0f) { if (!DebugDrawEnabled) { return; } if (direction == Vector3.zero) { return; } Vector3 right = Quaternion.LookRotation (direction) * Quaternion.Euler (arrowHeadAngle, 0, 0) * Vector3.back; Vector3 left = Quaternion.LookRotation (direction) * Quaternion.Euler (-arrowHeadAngle, 0, 0) * Vector3.back; Vector3 up = Quaternion.LookRotation (direction) * Quaternion.Euler (0, arrowHeadAngle, 0) * Vector3.back; Vector3 down = Quaternion.LookRotation (direction) * Quaternion.Euler (0, -arrowHeadAngle, 0) * Vector3.back; if (drawGizmos) { Gizmos.color = color; Gizmos.DrawRay (arrowEndPosition + direction, right * arrowHeadLength); Gizmos.DrawRay (arrowEndPosition + direction, left * arrowHeadLength); Gizmos.DrawRay (arrowEndPosition + direction, up * arrowHeadLength); Gizmos.DrawRay (arrowEndPosition + direction, down * arrowHeadLength); } else { Debug.DrawRay (arrowEndPosition + direction, right * arrowHeadLength, color); Debug.DrawRay (arrowEndPosition + direction, left * arrowHeadLength, color); Debug.DrawRay (arrowEndPosition + direction, up * arrowHeadLength, color); Debug.DrawRay (arrowEndPosition + direction, down * arrowHeadLength, color); } } /// /// Draws handles to materialize the bounds of an object on screen. /// /// Bounds. /// Color. public static void DrawHandlesBounds(Bounds bounds, Color color) { if (!DebugDrawEnabled) { return; } #if UNITY_EDITOR Vector3 boundsCenter = bounds.center; Vector3 boundsExtents = bounds.extents; Vector3 v3FrontTopLeft = new Vector3(boundsCenter.x - boundsExtents.x, boundsCenter.y + boundsExtents.y, boundsCenter.z - boundsExtents.z); // Front top left corner Vector3 v3FrontTopRight = new Vector3(boundsCenter.x + boundsExtents.x, boundsCenter.y + boundsExtents.y, boundsCenter.z - boundsExtents.z); // Front top right corner Vector3 v3FrontBottomLeft = new Vector3(boundsCenter.x - boundsExtents.x, boundsCenter.y - boundsExtents.y, boundsCenter.z - boundsExtents.z); // Front bottom left corner Vector3 v3FrontBottomRight = new Vector3(boundsCenter.x + boundsExtents.x, boundsCenter.y - boundsExtents.y, boundsCenter.z - boundsExtents.z); // Front bottom right corner Vector3 v3BackTopLeft = new Vector3(boundsCenter.x - boundsExtents.x, boundsCenter.y + boundsExtents.y, boundsCenter.z + boundsExtents.z); // Back top left corner Vector3 v3BackTopRight = new Vector3(boundsCenter.x + boundsExtents.x, boundsCenter.y + boundsExtents.y, boundsCenter.z + boundsExtents.z); // Back top right corner Vector3 v3BackBottomLeft = new Vector3(boundsCenter.x - boundsExtents.x, boundsCenter.y - boundsExtents.y, boundsCenter.z + boundsExtents.z); // Back bottom left corner Vector3 v3BackBottomRight = new Vector3(boundsCenter.x + boundsExtents.x, boundsCenter.y - boundsExtents.y, boundsCenter.z + boundsExtents.z); // Back bottom right corner Handles.color = color; Handles.DrawLine (v3FrontTopLeft, v3FrontTopRight); Handles.DrawLine (v3FrontTopRight, v3FrontBottomRight); Handles.DrawLine (v3FrontBottomRight, v3FrontBottomLeft); Handles.DrawLine (v3FrontBottomLeft, v3FrontTopLeft); Handles.DrawLine (v3BackTopLeft, v3BackTopRight); Handles.DrawLine (v3BackTopRight, v3BackBottomRight); Handles.DrawLine (v3BackBottomRight, v3BackBottomLeft); Handles.DrawLine (v3BackBottomLeft, v3BackTopLeft); Handles.DrawLine (v3FrontTopLeft, v3BackTopLeft); Handles.DrawLine (v3FrontTopRight, v3BackTopRight); Handles.DrawLine (v3FrontBottomRight, v3BackBottomRight); Handles.DrawLine (v3FrontBottomLeft, v3BackBottomLeft); #endif } /// /// Draws a solid rectangle at the specified position and size, and of the specified colors /// /// /// /// /// public static void DrawSolidRectangle(Vector3 position, Vector3 size, Color borderColor, Color solidColor) { if (!DebugDrawEnabled) { return; } #if UNITY_EDITOR Vector3 halfSize = size / 2f; Vector3[] verts = new Vector3[4]; verts[0] = new Vector3(halfSize.x, halfSize.y, halfSize.z); verts[1] = new Vector3(-halfSize.x, halfSize.y, halfSize.z); verts[2] = new Vector3(-halfSize.x, -halfSize.y, halfSize.z); verts[3] = new Vector3(halfSize.x, -halfSize.y, halfSize.z); Handles.DrawSolidRectangleWithOutline(verts, solidColor, borderColor); #endif } /// /// Draws a gizmo sphere of the specified size and color at a position /// /// Position. /// Size. /// Color. public static void DrawGizmoPoint(Vector3 position, float size, Color color) { if (!DebugDrawEnabled) { return; } Gizmos.color = color; Gizmos.DrawWireSphere(position,size); } /// /// Draws a cube at the specified position, and of the specified color and size /// /// Position. /// Color. /// Size. public static void DrawCube (Vector3 position, Color color, Vector3 size) { if (!DebugDrawEnabled) { return; } Vector3 halfSize = size / 2f; Vector3[] points = new Vector3 [] { position + new Vector3(halfSize.x,halfSize.y,halfSize.z), position + new Vector3(-halfSize.x,halfSize.y,halfSize.z), position + new Vector3(-halfSize.x,-halfSize.y,halfSize.z), position + new Vector3(halfSize.x,-halfSize.y,halfSize.z), position + new Vector3(halfSize.x,halfSize.y,-halfSize.z), position + new Vector3(-halfSize.x,halfSize.y,-halfSize.z), position + new Vector3(-halfSize.x,-halfSize.y,-halfSize.z), position + new Vector3(halfSize.x,-halfSize.y,-halfSize.z), }; Debug.DrawLine (points[0], points[1], color ); Debug.DrawLine (points[1], points[2], color ); Debug.DrawLine (points[2], points[3], color ); Debug.DrawLine (points[3], points[0], color ); } /// /// Draws a cube at the specified position, offset, and of the specified size /// /// /// /// /// public static void DrawGizmoCube(Transform transform, Vector3 offset, Vector3 cubeSize, bool wireOnly) { if (!DebugDrawEnabled) { return; } Matrix4x4 rotationMatrix = transform.localToWorldMatrix; Gizmos.matrix = rotationMatrix; if (wireOnly) { Gizmos.DrawWireCube(offset, cubeSize); } else { Gizmos.DrawCube(offset, cubeSize); } } /// /// Draws a gizmo rectangle /// /// Center. /// Size. /// Color. public static void DrawGizmoRectangle(Vector2 center, Vector2 size, Color color) { if (!DebugDrawEnabled) { return; } Gizmos.color = color; Vector3 v3TopLeft = new Vector3(center.x - size.x/2, center.y + size.y/2, 0); Vector3 v3TopRight = new Vector3(center.x + size.x/2, center.y + size.y/2, 0);; Vector3 v3BottomRight = new Vector3(center.x + size.x/2, center.y - size.y/2, 0);; Vector3 v3BottomLeft = new Vector3(center.x - size.x/2, center.y - size.y/2, 0);; Gizmos.DrawLine(v3TopLeft,v3TopRight); Gizmos.DrawLine(v3TopRight,v3BottomRight); Gizmos.DrawLine(v3BottomRight,v3BottomLeft); Gizmos.DrawLine(v3BottomLeft,v3TopLeft); } /// /// Draws a gizmo rectangle /// /// Center. /// Size. /// Color. public static void DrawGizmoRectangle(Vector2 center, Vector2 size, Matrix4x4 rotationMatrix, Color color) { if (!DebugDrawEnabled) { return; } GL.PushMatrix(); Gizmos.color = color; Vector3 v3TopLeft = rotationMatrix * new Vector3(center.x - size.x / 2, center.y + size.y / 2, 0); Vector3 v3TopRight = rotationMatrix * new Vector3(center.x + size.x / 2, center.y + size.y / 2, 0); ; Vector3 v3BottomRight = rotationMatrix * new Vector3(center.x + size.x / 2, center.y - size.y / 2, 0); ; Vector3 v3BottomLeft = rotationMatrix * new Vector3(center.x - size.x / 2, center.y - size.y / 2, 0); ; Gizmos.DrawLine(v3TopLeft, v3TopRight); Gizmos.DrawLine(v3TopRight, v3BottomRight); Gizmos.DrawLine(v3BottomRight, v3BottomLeft); Gizmos.DrawLine(v3BottomLeft, v3TopLeft); GL.PopMatrix(); } /// /// Draws a rectangle based on a Rect and color /// /// Rectangle. /// Color. public static void DrawRectangle (Rect rectangle, Color color) { if (!DebugDrawEnabled) { return; } Vector3 pos = new Vector3( rectangle.x + rectangle.width/2, rectangle.y + rectangle.height/2, 0.0f ); Vector3 scale = new Vector3 (rectangle.width, rectangle.height, 0.0f ); MMDebug.DrawRectangle (pos, color, scale); } /// /// Draws a rectangle of the specified color and size at the specified position /// /// Position. /// Color. /// Size. public static void DrawRectangle (Vector3 position, Color color, Vector3 size) { if (!DebugDrawEnabled) { return; } Vector3 halfSize = size / 2f; Vector3[] points = new Vector3 [] { position + new Vector3(halfSize.x,halfSize.y,halfSize.z), position + new Vector3(-halfSize.x,halfSize.y,halfSize.z), position + new Vector3(-halfSize.x,-halfSize.y,halfSize.z), position + new Vector3(halfSize.x,-halfSize.y,halfSize.z), }; Debug.DrawLine (points[0], points[1], color ); Debug.DrawLine (points[1], points[2], color ); Debug.DrawLine (points[2], points[3], color ); Debug.DrawLine (points[3], points[0], color ); } /// /// Draws a point of the specified color and size at the specified position /// /// Position. /// Col. /// Scale. public static void DrawPoint (Vector3 position, Color color, float size) { if (!DebugDrawEnabled) { return; } Vector3[] points = new Vector3[] { position + (Vector3.up * size), position - (Vector3.up * size), position + (Vector3.right * size), position - (Vector3.right * size), position + (Vector3.forward * size), position - (Vector3.forward * size) }; Debug.DrawLine (points[0], points[1], color ); Debug.DrawLine (points[2], points[3], color ); Debug.DrawLine (points[4], points[5], color ); Debug.DrawLine (points[0], points[2], color ); Debug.DrawLine (points[0], points[3], color ); Debug.DrawLine (points[0], points[4], color ); Debug.DrawLine (points[0], points[5], color ); Debug.DrawLine (points[1], points[2], color ); Debug.DrawLine (points[1], points[3], color ); Debug.DrawLine (points[1], points[4], color ); Debug.DrawLine (points[1], points[5], color ); Debug.DrawLine (points[4], points[2], color ); Debug.DrawLine (points[4], points[3], color ); Debug.DrawLine (points[5], points[2], color ); Debug.DrawLine (points[5], points[3], color ); } #endregion #region Info public static string GetSystemInfo() { string result = "SYSTEM INFO"; #if UNITY_IOS result += "\n[iPhone generation]iPhone.generation.ToString()"; #endif #if UNITY_ANDROID result += "\n[system info]" + SystemInfo.deviceModel; #endif result += "\nDevice Type : " + SystemInfo.deviceType; result += "\nOS Version : " + SystemInfo.operatingSystem; result += "\nSystem Memory Size : " + SystemInfo.systemMemorySize; result += "\nGraphic Device Name : " + SystemInfo.graphicsDeviceName + " (version " + SystemInfo.graphicsDeviceVersion + ")"; result += "\nGraphic Memory Size : " + SystemInfo.graphicsMemorySize; result += "\nGraphic Max Texture Size : " + SystemInfo.maxTextureSize; result += "\nGraphic Shader Level : " + SystemInfo.graphicsShaderLevel; result += "\nCompute Shader Support : " + SystemInfo.supportsComputeShaders; result += "\nProcessor Count : " + SystemInfo.processorCount; result += "\nProcessor Type : " + SystemInfo.processorType; result += "\n3D Texture Support : " + SystemInfo.supports3DTextures; result += "\nShadow Support : " + SystemInfo.supportsShadows; result += "\nPlatform : " + Application.platform; result += "\nScreen Size : " + Screen.width + " x " + Screen.height; result += "\nDPI : " + Screen.dpi; return result; } #endregion } }