/* *Copyright(C) 2020 by GYYX All rights reserved. *Unity版本:2018.4.36f1 *作者:Chief *创建日期: 2022-01-04 *模块说明: *版本: 1.2 */ using System.Collections.Generic; using Unity.Collections; using UnityEngine; namespace Oroxylum { /// /// 通用工具; /// public static class Utils { #region 组件相关 public static GameObject CreateGameObjectAtPath(string path) { if (string.IsNullOrEmpty(path)) return null; var obj = GameObject.Find(path); if (obj == null) { //在最近父节点进行创建; var index = path.LastIndexOf('/'); if (index == -1) return new GameObject(path); var parentPath = path.Substring(0, index); var selftPath = path.Substring(index + 1); obj = new GameObject(selftPath); var parent = CreateGameObjectAtPath(parentPath); if (parent != null) obj.transform.parent = parent.transform; obj.NormalizeGameObject(); } return obj; } public static Transform CreateTransformAtParent(string name, Transform parentTrans) { var go = new GameObject(name); go.SetParent(parentTrans); go.NormalizeGameObject(); return go.transform; } public static Transform CreateChild(this Transform parentTrans, string name) { var go = new GameObject(name); go.SetParent(parentTrans); go.NormalizeGameObject(); return go.transform; } public static void NormalizeGameObject(this GameObject target) { target.transform.localPosition = Vector3.zero; target.transform.localRotation = Quaternion.identity; target.transform.localScale = Vector3.one; } [System.Obsolete("使用 SetActiveSafe 替换。")] public static void SetActive2(this GameObject obj, bool active) { obj.SetActiveSafe(active); } public static void SetActiveSafe(this GameObject obj, bool active) { if (obj == null) return; if (obj.activeSelf == active) return; obj.SetActive(active); } [System.Obsolete("使用 SetActiveSafe 替换。")] public static void SetActive2(this Component compT, bool active) { compT.SetActiveSafe(active); } public static void SetActiveSafe(this Component compT, bool active) { if (compT == null) return; compT.gameObject.SetActiveSafe(active); } public static void Destory(this UnityEngine.Object obj) { if (obj == null) return; //特殊:于Transform的判定; if (obj is Transform) (obj as Transform).gameObject.Destory(); #if UNITY_EDITOR if (!Application.isPlaying) UnityEngine.Object.DestroyImmediate(obj); else #endif UnityEngine.Object.Destroy(obj); } /// /// 获取层级名; /// public static string GetHierarchyName(this Transform trans) { if (trans == null) return null; string name = trans.name; var parent = trans.parent; while (parent != null) { name = $"{parent.name}/{name}"; parent = parent.parent; } return name; } /// /// 获取根节点 /// /// public static Transform GetRootTransform(this Transform trans) { if (trans == null) return null; if (trans.parent == null) return trans; return trans.parent.GetRootTransform(); } /// /// 获取,或者添加一个组件; /// public static T GetOrAddComponent(this GameObject obj) where T : Component { if (obj == null) return null; var compt = obj.GetComponent(); if (compt == null) compt = obj.AddComponent(); return compt; } /// /// 获取,或者添加一个组件; /// public static T GetOrAddComponent(this Transform trans) where T : Component { if (trans == null) return null; return trans.gameObject.GetOrAddComponent(); } /// /// 获取,或者添加一个组件; /// public static T GetOrAddComponent(this Component compt) where T : Component { if (compt == null) return null; return compt.gameObject.GetOrAddComponent(); } #endregion #region 扩展方法 public static void AddOrReplace(this Dictionary dict, T1 key, T2 val) { if (dict == null) return; if (key == null || val == null) return; if (dict.ContainsKey(key)) dict[key] = val; else dict.Add(key, val); } public static void AddOrIngore(this Dictionary dict, T1 key, T2 val) { if (dict == null) return; if (key == null || val == null) return; if (dict.ContainsKey(key)) return; else dict.Add(key, val); } public static T2 GetValue(this Dictionary dict, T1 key) { if (dict == null) return default(T2); T2 ret; dict.TryGetValue(key, out ret); return ret; } public static long Int2ToLong(Vector2Int v) { int q = v.x, r = v.y; long rt = (long)q << 32; rt = rt | (r & 0xffffffff); return rt; } public static Vector2Int LongToInt2(long id) { int x = (int)(id >> 32); int y = (int)id; return new Vector2Int(x, y); } /// /// 通过线性采样获得的颜色值; /// public static Color GetBilinearPixel(NativeArray pixelData, float u, float v, int width, int height) { u *= width; v *= height; width = Mathf.Max(width, 2); height = Mathf.Max(height, 2); int x = Mathf.Clamp(Mathf.FloorToInt(u), 0, width - 2); int y = Mathf.Clamp(Mathf.FloorToInt(v), 0, height - 2); float s = u - x; float t = v - y; Color c1 = pixelData[x + (y * width)]; Color c2 = pixelData[x + 1 + (y * width)]; Color c3 = pixelData[x + ((y + 1) * width)]; Color c4 = pixelData[x + 1 + ((y + 1) * width)]; Color a = Color.Lerp(c1, c2, s); Color b = Color.Lerp(c3, c4, s); return Color.Lerp(a, b, t); } #endregion #region 数学计算 /// /// 计算直线与平面的交点 /// /// 通用的部分; /// /// ——程一峰;2020.11.09 /// /// 直线上某一点 /// 直线的方向 /// 垂直于平面的的向量 /// 平面上的任意一点 /// public static Vector3 GetIntersectWithLineAndPlane(Vector3 point, Vector3 direct, Vector3 planeNormal, Vector3 planePoint) { float d = Vector3.Dot(planePoint - point, planeNormal) / Vector3.Dot(direct.normalized, planeNormal); //直线与平面的交点 Vector3 hitPoint = (d * direct.normalized) + point; return hitPoint; } /// /// 点到直线的距离; /// /// 目标点 /// 直线上一点 /// 直线上另一点 /// public static float GetDistancePointToLine(Vector3 point, Vector3 linePoint1, Vector3 linePoint2) { Vector3 vec1 = point - linePoint1; Vector3 vec2 = linePoint2 - linePoint1; Vector3 vecProj = Vector3.Project(vec1, vec2); float dis = Mathf.Sqrt(Mathf.Pow(Vector3.Magnitude(vec1), 2) - Mathf.Pow(Vector3.Magnitude(vecProj), 2)); return dis; } /// /// /// 计算射线与平面的交点 /// /// 通用的部分; /// /// ——程一峰;2020.11.17 /// /// 射线 /// 垂直于平面的的向量 /// 平面上的任意一点 /// public static Vector3 GetIntersectWithLineAndPlane(Ray ray, Vector3 planeNormal, Vector3 planePoint) { return GetIntersectWithLineAndPlane(ray.origin, ray.direction, planeNormal, planePoint); } /// /// /// 计算射线与水平平面的交点 /// /// 通用的部分; /// /// ——程一峰;2020.11.17 /// /// 射线 /// 高度 /// public static Vector3 GetIntersectWithLineAndPlane(Ray ray, float height) { var point = GetIntersectWithLineAndPlane(ray.origin, ray.direction, Vector3.up, new Vector3(0, height, 0)); point.y = height; return point; } /// /// 将值限制在两个Vector3之间 /// /// /// /// /// public static Vector3 Clamp(Vector3 pos, Vector3 min, Vector3 max) { pos.x = Mathf.Clamp(pos.x, min.x, max.x); pos.y = Mathf.Clamp(pos.y, min.y, max.y); pos.z = Mathf.Clamp(pos.z, min.z, max.z); return pos; } public static Vector2 Clamp(this Vector2 source, Vector2 min, Vector2 max) { source.x = Mathf.Clamp(source.x, min.x, max.x); source.y = Mathf.Clamp(source.y, min.y, max.y); return source; } /// /// 距离的平方; /// public static float DistanceSq(Vector3 a, Vector3 b) { float xSq = (a.x - b.x) * (a.x - b.x); float ySq = (a.y - b.y) * (a.y - b.y); float zSq = (a.z - b.z) * (a.z - b.z); return xSq + ySq + zSq; } /// /// 距离的平方; /// public static float DistanceSq(Vector2 a, Vector2 b) { float xSq = (a.x - b.x) * (a.x - b.x); float ySq = (a.y - b.y) * (a.y - b.y); return xSq + ySq; } /// /// 获取坐标差值之和; /// 忽略Y轴; /// 这个计算值一定大于等于其实际距离; /// public static float Distance_FastByCoDiff_NoY(Vector3 v1, Vector3 v2) { float x = v1.x - v2.x; if (x < 0) x = -x; float z = v1.z - v2.z; if (z < 0) z = -z; return x + z; } public static Vector2 XZ(this Vector3 pos) { return new Vector2(pos.x, pos.z); } public static Vector2 XY(this Vector3 pos) { return new Vector2(pos.x, pos.y); } public static Vector2 ZY(this Vector3 pos) { return new Vector2(pos.z, pos.y); } /// /// 看向某个目标时,旋转的欧拉角 /// /// /// 目标点 /// 旋转欧拉角 public static Vector3 LookAtEulerAngle(this Vector3 pos, Vector3 target) { Vector3 fwd = target - pos; return Quaternion.LookRotation(fwd, Vector3.up).eulerAngles; } public static int ToInt(this long val) { //极值判定; if (val > int.MaxValue) { Logger.LogError($"传入值过大: {val}"); return int.MaxValue; } if (val < int.MinValue) { Logger.LogError($"传入值过小: {val}"); return int.MinValue; } return System.Convert.ToInt32(val); } public static int Add(this int a, long b) { long addRet = a + b; return addRet.ToInt(); } /// /// 是否是有效的 Vector3; /// public static bool IsVaild(this Vector3 point) { if (float.IsNaN(point.x) || float.IsNaN(point.y) || float.IsNaN(point.z)) return false; if (float.IsInfinity(point.x) || float.IsInfinity(point.y) || float.IsInfinity(point.z)) return false; return true; } public static Vector3 Div(this Vector3 a, Vector3 b) { float x = a.x / b.x; float y = a.y / b.y; float z = a.z / b.z; return new Vector3(x, y, z); } public static Vector2 Div(this Vector2 a, Vector2 b) { float x = a.x / b.x; float y = a.y / b.y; return new Vector2(x, y); } public static Vector3 Mul(this Vector3 a, Vector3 b) { float x = a.x * b.x; float y = a.y * b.y; float z = a.z * b.z; return new Vector3(x, y, z); } public static Vector2 Mul(this Vector2 a, Vector2 b) { float x = a.x * b.x; float y = a.y * b.y; return new Vector2(x, y); } #endregion #region 字符串操作 /// /// 把字符串用 . 分开; /// 然后获取最后一个字符串; /// /// /// public static string GetLastStrAfterDot(string oldStr) { var arrStr = oldStr.Split('.'); return arrStr[arrStr.Length - 1]; } #endregion } }