记录下开发中会使用的一些通用api,避免之后每次都去查看过去工程的代码。
1.记录运行日志:
/// <summary>
/// 保持的日志文件名称
/// </summary>
public const string saveLogFileName = "runLog.txt";
private void Awake()
{
Application.logMessageReceived += SaveLog;
}
private string tempBeforeLog;
/// <summary>
/// 保存日志
/// </summary>
/// <param name="condition"></param>
/// <param name="stackTrace"></param>
/// <param name="type"></param>
private void SaveLog(string condition, string stackTrace, LogType type)
{
if (condition.Equals(tempBeforeLog))//如果是相同的信息就不再写入
{
return;
}
string path = GetSaveLogPath();
using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
{
using (StreamWriter sw = new StreamWriter(fs))
{
fs.Seek(0, SeekOrigin.End);
sw.WriteLine(DateTime.Now.ToString("G") + " " + type.ToString() + ":" + condition + "{" + stackTrace + "}");
}
}
tempBeforeLog = condition;
}
2.监听程序退出和编辑器下的停止运行:
Application.wantsToQuit += OnQuitEvent;
#if UNITY_EDITOR
EditorApplication.wantsToQuit += OnQuitEvent;
#endif
//返回false回阻止发布后的程序关闭
private bool OnQuitEvent()
{
return true;
}
3.监听UGUI窗口变化:
public void OnRectTransformDimensionsChange()
{
Debug.Log("窗口大小发生改变");
}
4.在Awake之前执行
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
static void AwakeBefore()
{
Debug.Log("在Awake之前调用");
}
5.隐藏标题栏
[DllImport("user32.dll")]
public static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
public static extern long GetWindowLong(IntPtr hwd, int nIndex);
[DllImport("user32.dll")]
public static extern void SetWindowLong(IntPtr hwd, int nIndex, long dwNewLong);
[DllImport("user32")]
static extern int EnumWindows(EnumWindowsCallBack lpEnumFunc, IntPtr lParam);
[DllImport("user32")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, ref IntPtr lpdwProcessId);
[DllImport("user32.dll", EntryPoint = "FindWindow")]
public static extern System.IntPtr FindWindow(System.String className, System.String windowName);
/// <summary>
/// 窗口风格
/// </summary>
const int GWL_STYLE = -16;
/// <summary>
/// 标题栏
/// </summary>
const int WS_CAPTION = 0x00c00000;
/// <summary>
/// 外边框显示隐藏
/// </summary>
const uint WS_VISIBLE = 0x10000000;
private void Awake()
{
#if !UNITY_EDITOR && UNITY_STANDALONE_WIN
HideTitle();
Screen.SetResolution(defaultWindowWidth,defaultWindowHeight,false);
#endif
}
private static void HideTitle()
{
GetSelfWindows();
IntPtr window = myWindowHandle;//GetForegroundWindow();
//GetForegroundWindow是获取的当前焦点程序窗口,在启动的一瞬间如果选中别的窗口,则会出现将选中的窗口标题栏隐藏的问题。
var wl = GetWindowLong(window, GWL_STYLE);
wl &= ~WS_CAPTION & WS_VISIBLE;
SetWindowLong(window, GWL_STYLE, wl);
}
private static IntPtr myWindowHandle;
/// <summary>
/// 获取程序自身窗口
/// </summary>
public static void GetSelfWindows()
{
IntPtr handle = (IntPtr)System.Diagnostics.Process.GetCurrentProcess().Id; //获取进程ID
EnumWindows(new EnumWindowsCallBack(EnumWindCallback), handle); //枚举查找本窗口
//打包时的ProductName
//myWindowHandle = FindWindow(null, "WindowTitleChange");
}
隐藏后,会出现UGUI鼠标点击位置识别偏差问题,应该是差了一个标题栏的高度,在awake手动设置一下分辨率即可。
6.坐标旋转
/// <summary>
/// 围绕某点旋转指定角度
/// </summary>
/// <param name="position">自身坐标</param>
/// <param name="center">旋转中心</param>
/// <param name="axis">围绕旋转轴</param>
/// <param name="angle">旋转角度</param>
/// <returns></returns>
public static Vector3 RotateRound(Vector3 position, Vector3 center, Vector3 axis, float angle)
{
return Quaternion.AngleAxis(angle, axis) * (position - center) + center;
}
7 清理所有进程内存
[DllImport("psapi.dll")]
private static extern int EmptyWorkingSet(IntPtr hwProc);
public static void ClearMemory()
{
GC.Collect();
GC.WaitForPendingFinalizers();
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
try
{
EmptyWorkingSet(process.Handle);
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
}
8 UGUI识别当前鼠标是否位于UI控件上
public static bool GetOverUI()
{
bool isOver=false;
EventSystem uiEventSystem = EventSystem.current;
if (uiEventSystem != null)
{
PointerEventData uiPointerEventData = new PointerEventData(uiEventSystem);
uiPointerEventData.position = Input.mousePosition;
List<RaycastResult> uiRaycastResultCache = new List<RaycastResult>();
uiEventSystem.RaycastAll(uiPointerEventData, uiRaycastResultCache);
if (uiRaycastResultCache.Count > 0)
{
Transform obj = uiRaycastResultCache[0].gameObject.transform;
isOver = obj is RectTransform;
}
}
return isOver;
}
9 Inspector 面板显示按钮,调用方法
#if UNITY_EDITOR
[UnityEditor.CustomEditor(typeof(TestClass))]
public class ViveInputAdapterManagerEditor : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
base.OnInspectorGUI();
if (!Application.isPlaying)
{
var targetNode = target as TestClass;
if (targetNode == null)
{
return;
}
GUILayout.BeginHorizontal();
if (GUILayout.Button("自定义按钮"))
{
targetNode.Init();
}
GUILayout.EndHorizontal();
}
}
}
#endif
10.获取模型中心点坐标
public static Vector3 GetModelsCenter(GameObject go)
{
Vector3 center = Vector3.zero;
MeshRenderer mr = go.GetComponent<MeshRenderer>();
if (mr != null)
{
center = mr.bounds.center;
}
else
{
MeshRenderer[] mrs = go.GetComponentsInChildren<MeshRenderer>();
for (int i = 0; i < mrs.Length; i++)
{
center += mrs[i].bounds.center;
}
if (mrs.Length > 0)
{
center /= mrs.Length;
}
}
return center;
}
11.计算相对坐标
/// <summary>
/// 获取position相对origin的坐标
/// </summary>
/// <param name="origin"></param>
/// <param name="position"></param>
/// <returns></returns>
private Vector3 GetRelativePosition(Vector3 origin, Vector3 position)
{
if (origin == Vector3.zero)
{
return position;
}
Vector3 distance = position - origin;
Vector3 relativePosition = Vector3.zero;
relativePosition.x = Vector3.Dot(distance, new Vector3(origin.x, 0, 0).normalized);
relativePosition.y = Vector3.Dot(distance, new Vector3(0, origin.y, 0).normalized);
relativePosition.z = Vector3.Dot(distance, new Vector3(0, 0, origin.z).normalized);
return relativePosition;
}
12.动态给UI添加事件
public static void SetUIComponentEvent(GameObject go, EventTriggerType type, UnityAction<BaseEventData> call)
{
EventTrigger trigger = go.GetComponent<EventTrigger>();
if (trigger == null)
{
trigger = go.AddComponent<EventTrigger>();
}
EventTrigger.Entry entry = new EventTrigger.Entry();
entry.eventID = type;
entry.callback.AddListener(call);
trigger.triggers.Add(entry);
}
13.解析URL参数
/// <summary>
/// 解析url参数
/// </summary>
/// <param name="urlArguments"></param>
/// <param name="key"></param>
/// <returns></returns>
public static string GetURLArguments(string urlArguments, string key,string defaultValue)
{
if (!string.IsNullOrEmpty(urlArguments)&&urlArguments.Contains("?"))
{
urlArguments = urlArguments.Substring(1, urlArguments.Length - 1);
string[] argRoot = urlArguments.Split('&');
if (string.IsNullOrEmpty(key))
{
return urlArguments;
}
for (int i = 0; i < argRoot.Length; i++)
{
string[] arguments = argRoot[i].Split('=');
if (arguments.Length >= 2)
{
if (arguments[0].Equals(key))
{
return arguments[1];
}
}
}
}
return defaultValue;
}
14.获取指定模型顶点
/// <summary>
/// 获取指定物体的顶点,如果没有递归查询子物体,返回第一个顶点数大于0的物体顶点
/// </summary>
/// <param name="go"></param>
/// <returns></returns>
public static List<Vector3> GetModelVertices(GameObject go)
{
MeshFilter mf = go.GetComponent<MeshFilter>();
if (mf != null)
{
return new List<Vector3>(mf.mesh.vertices);
}
else
{
for (int i = 0; i < go.transform.childCount; i++)
{
List<Vector3> vertices = GetModelVertices(go.transform.GetChild(i).gameObject);
if (vertices.Count > 0)
{
return vertices;
}
}
}
return new List<Vector3>();
}
15.获取鼠标相对点击UI上的坐标和相对中心点的角度。
/// <summary>
/// 获取鼠标点击UI上范围的相对坐标,0~1
/// </summary>
/// <param name="eventData"></param>
/// <returns></returns>
public static Vector2 GetMouseClickPointByUI(RectTransform rectTf, PointerEventData eventData)
{
Vector2 localPoint;
Vector2 normalizedPoint = Vector2.zero;
//将屏幕空间的点转换成RectTransform指定的本地空间点
if (RectTransformUtility.ScreenPointToLocalPointInRectangle(rectTf, eventData.position, eventData.pressEventCamera, out localPoint))
{
// localPoint 是相对于轴点的本地坐标,和轴点有关
//转换成归一化的坐标,范围是0到1,和轴点无关,ugui左下角为(0, 0),右上角为(1, 1)
normalizedPoint = Rect.PointToNormalized(rectTf.rect, localPoint);
//Debug.Log("normalizedPoint=" + normalizedPoint.ToString());
//计算相对中心的角度
Vector2 formV2 = normalizedPoint - new Vector2(0.5f, 0.5f);
Vector2 toV2 = new Vector2(0.5f, 0) - new Vector2(0.5f, 0.5f);
float angle = Vector2.Angle(formV2, toV2);
if (normalizedPoint.x < 0.5f)
{
angle = 360 - angle;
}
}
return normalizedPoint;
}
16.将传入数据,扩容或压缩到指定个数(最简单方式)
/// <summary>
/// 将传入数据,扩容或压缩到指定个数(最简单方式)
/// </summary>
/// <param name="inputList"></param>
/// <param name="targetCount"></param>
/// <returns></returns>
public static List<float> ScaleV2List(List<float> inputList, int targetCount)
{
List<float> result = new List<float>();
int unit = 0;
if (inputList.Count > targetCount)
{
unit = Mathf.CeilToInt(inputList.Count / (float)targetCount);
for (int i = 0; i < inputList.Count; i++)
{
if (i % unit == 0)
{
result.Add(inputList[i]);
}
}
}
else if (inputList.Count < targetCount)
{
unit = targetCount / inputList.Count;
for (int i = 0; i < inputList.Count - 1; i++)
{
for (int j = 0; j < unit; j++)
{
float rate = (float)j / unit;
float f = Mathf.Lerp(inputList[i], inputList[i + 1], rate);
result.Add(f);
}
}
}
else
{
result = inputList;
}
int replenishCount = result.Count - targetCount;
if (replenishCount > 0)
{
for (int i = 0; i < replenishCount; i++)
{
int tempIndex = Random.Range(0, result.Count);
result.RemoveAt(tempIndex);
}
}
else if (replenishCount < 0)
{
int count = Mathf.Abs(replenishCount);
for (int i = 0; i < count; i++)
{
result.Add(result[result.Count - 1]);
}
}
return result;
}
17.使用位移和按位与操作来检查指定位
private bool GetBit(int n, int position)
{
// 使用位移和按位与操作来检查指定位
int result = n & (1 << position);
//result = 0或非0的数字
return result != 0;
}