using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using UnityEditor; using UnityEngine; using UnityEngine.SceneManagement; namespace YagihataItems.YagiUtils { public static class UnityUtils { // // MIT LICENSE https://opensource.org/licenses/mit-license.php // public static bool IsChildOf(this GameObject target, GameObject parent) { Transform targetParent = target.transform.parent; while (targetParent != null) { if (targetParent == parent.transform) return true; else targetParent = targetParent.parent; } return false; } public static string GetRelativePath(this GameObject target, GameObject parent) { if (!target.IsChildOf(parent)) return null; var list = new List(); list.Add(target.name); Transform targetParent = target.transform.parent; while (targetParent != null) { if (targetParent == parent.transform) break; else { list.Insert(0, targetParent.name); targetParent = targetParent.parent; } } return string.Join("/", list); } public static void ReCreateFolder(string path) { path = path.Trim('/'); DeleteFolder(path); CreateFolderRecursively(path); } public static void DeleteFolder(string path) { path = path.Trim('/'); if (AssetDatabase.IsValidFolder(path)) DeleteAssetDirectory(path); } public static bool DeleteAssetDirectory(string assetPath) { if (AssetDatabase.DeleteAsset(assetPath)) { Debug.Log("Delete Asset: " + assetPath); return true; } string[] dirpathlist = Directory.GetDirectories(assetPath); foreach (string path in dirpathlist) { if (false == DeleteAssetDirectory(path)) { Debug.LogError("Delete Asset Directory Error: " + path); return false; } } string[] filepathlist = Directory.GetFiles(assetPath); foreach (string path in filepathlist) { if (path.EndsWith(".meta")) { continue; } if (false == AssetDatabase.DeleteAsset(path)) { Debug.LogError("Delete Asset Files Error: " + path); return false; } } Debug.Log("Delete Asset: " + assetPath); return true; } public static void CreateFolderRecursively(string path) { Debug.Assert(path.StartsWith("Assets/"), "arg `path` of CreateFolderRecursively doesn't starts with `Assets/`"); if (AssetDatabase.IsValidFolder(path)) return; if (path[path.Length - 1] == '/') { path = path.Substring(0, path.Length - 1); } var names = path.Split('/'); for (int i = 1; i < names.Length; i++) { var parent = string.Join("/", names.Take(i).ToArray()); var target = string.Join("/", names.Take(i + 1).ToArray()); var child = names[i]; if (!AssetDatabase.IsValidFolder(target)) { AssetDatabase.CreateFolder(parent, child); } } } public static void GetGameObjectsOfType(ref List list, GameObject gameObject, bool getInactive) { if (getInactive || (!getInactive && gameObject.activeInHierarchy)) { var component = gameObject.GetComponent(typeof(T)); if (component != null) list.Add((T)((object)component)); } if (gameObject.transform.childCount > 0) foreach (var v in Enumerable.Range(0, gameObject.transform.childCount)) { GetGameObjectsOfType(ref list, gameObject.transform.GetChild(v).gameObject, getInactive); } } public static string GetHierarchyPath(this GameObject target) { string path = ""; Transform current = target.transform; while (current != null) { int index = current.GetSiblingIndex(); path = "/" + current.name + index + path; current = current.parent; } Scene belongScene = target.GetBelongsScene(); return "/" + belongScene.name + path; } public static Scene GetBelongsScene(this GameObject target) { for (int i = 0; i < SceneManager.sceneCount; i++) { Scene scene = SceneManager.GetSceneAt(i); if (!scene.IsValid()) { continue; } if (!scene.isLoaded) { continue; } GameObject[] roots = scene.GetRootGameObjects(); foreach (var root in roots) { if (root == target.transform.root.gameObject) { return scene; } } } return default(Scene); } public static UnityEngine.Object TryGetAsset(string path, Type type, bool createNew = true) { var obj = AssetDatabase.LoadAssetAtPath(path, type); if (obj == null && createNew) { obj = ScriptableObject.CreateInstance(type); AssetDatabase.CreateAsset(obj, path); } return obj; } /// /// 座標を保ったままPivotを変更する /// /// 自身の参照 /// 変更先のPivot座標 public static void SetPivotWithKeepingPosition(this RectTransform rectTransform, Vector2 targetPivot) { var diffPivot = targetPivot - rectTransform.pivot; rectTransform.pivot = targetPivot; var diffPos = new Vector2(rectTransform.sizeDelta.x * diffPivot.x, rectTransform.sizeDelta.y * diffPivot.y); rectTransform.anchoredPosition += diffPos; } /// /// 座標を保ったままPivotを変更する /// /// 自身の参照 /// 変更先のPivotのx座標 /// 変更先のPivotのy座標 public static void SetPivotWithKeepingPosition(this RectTransform rectTransform, float x, float y) { rectTransform.SetPivotWithKeepingPosition(new Vector2(x, y)); } /// /// 座標を保ったままAnchorを変更する /// /// 自身の参照 /// 変更先のAnchor座標 (min,maxが共通の場合) public static void SetAnchorWithKeepingPosition(this RectTransform rectTransform, Vector2 targetAnchor) { rectTransform.SetAnchorWithKeepingPosition(targetAnchor, targetAnchor); } /// /// 座標を保ったままAnchorを変更する /// /// 自身の参照 /// 変更先のAnchorのx座標 (min,maxが共通の場合) /// 変更先のAnchorのy座標 (min,maxが共通の場合) public static void SetAnchorWithKeepingPosition(this RectTransform rectTransform, float x, float y) { rectTransform.SetAnchorWithKeepingPosition(new Vector2(x, y)); } /// /// 座標を保ったままAnchorを変更する /// /// 自身の参照 /// 変更先のAnchorMin座標 /// 変更先のAnchorMax座標 public static void SetAnchorWithKeepingPosition(this RectTransform rectTransform, Vector2 targetMinAnchor, Vector2 targetMaxAnchor) { var parent = rectTransform.parent as RectTransform; if (parent == null) { Debug.LogError("Parent cannot find."); } var diffMin = targetMinAnchor - rectTransform.anchorMin; var diffMax = targetMaxAnchor - rectTransform.anchorMax; // anchorの更新 rectTransform.anchorMin = targetMinAnchor; rectTransform.anchorMax = targetMaxAnchor; // 上下左右の距離の差分を計算 var diffLeft = parent.rect.width * diffMin.x; var diffRight = parent.rect.width * diffMax.x; var diffBottom = parent.rect.height * diffMin.y; var diffTop = parent.rect.height * diffMax.y; // サイズと座標の修正 rectTransform.sizeDelta += new Vector2(diffLeft - diffRight, diffBottom - diffTop); var pivot = rectTransform.pivot; rectTransform.anchoredPosition -= new Vector2( (diffLeft * (1 - pivot.x)) + (diffRight * pivot.x), (diffBottom * (1 - pivot.y)) + (diffTop * pivot.y) ); } /// /// 座標を保ったままAnchorを変更する /// /// 自身の参照 /// 変更先のAnchorMinのx座標 /// 変更先のAnchorMinのy座標 /// 変更先のAnchorMaxのx座標 /// 変更先のAnchorMaxのy座標 public static void SetAnchorWithKeepingPosition(this RectTransform rectTransform, float minX, float minY, float maxX, float maxY) { rectTransform.SetAnchorWithKeepingPosition(new Vector2(minX, minY), new Vector2(maxX, maxY)); } } }