diff --git a/NewHorizons/Builder/Props/DetailBuilder.cs b/NewHorizons/Builder/Props/DetailBuilder.cs index 87056fe1..a395e080 100644 --- a/NewHorizons/Builder/Props/DetailBuilder.cs +++ b/NewHorizons/Builder/Props/DetailBuilder.cs @@ -56,6 +56,7 @@ namespace NewHorizons.Builder.Props private static void SceneManager_sceneUnloaded(Scene scene) { + // would be nice to only clear when system changes, but fixed prefabs rely on stuff in the scene foreach (var prefab in _fixedPrefabCache.Values) { UnityEngine.Object.Destroy(prefab.prefab); @@ -230,15 +231,10 @@ namespace NewHorizons.Builder.Props if (detail.removeChildren != null) { - var detailPath = prop.transform.GetPath(); - var transforms = prop.GetComponentsInChildren(true); foreach (var childPath in detail.removeChildren) { - // Multiple children can have the same path so we delete all that match - var path = $"{detailPath}/{childPath}"; - var flag = true; - foreach (var childObj in transforms.Where(x => x.GetPath() == path)) + foreach (var childObj in prop.transform.FindAll(childPath)) { flag = false; childObj.gameObject.SetActive(false); @@ -274,7 +270,7 @@ namespace NewHorizons.Builder.Props UnityEngine.Object.DestroyImmediate(prop); prop = newDetailGO; } - + if (isItem) { // Else when you put them down you can't pick them back up @@ -286,7 +282,7 @@ namespace NewHorizons.Builder.Props // For DLC related props // Make sure to do this before its set active - if (!string.IsNullOrEmpty(detail?.path) && + if (!string.IsNullOrEmpty(detail?.path) && (detail.path.ToLowerInvariant().StartsWith("ringworld") || detail.path.ToLowerInvariant().StartsWith("dreamworld"))) { prop.AddComponent()._destroyOnDLCNotOwned = true; @@ -305,7 +301,7 @@ namespace NewHorizons.Builder.Props if (!string.IsNullOrEmpty(detail.activationCondition)) { - ConditionalObjectActivation.SetUp(prop, detail.activationCondition, detail.blinkWhenActiveChanged, true); + ConditionalObjectActivation.SetUp(prop, detail.activationCondition, detail.blinkWhenActiveChanged, true); } if (!string.IsNullOrEmpty(detail.deactivationCondition)) { @@ -579,22 +575,22 @@ namespace NewHorizons.Builder.Props // Manually copied these values from a artifact lantern so that we don't have to find it (works in Eye) lantern._origLensFlareBrightness = 0f; - lantern._focuserPetalsBaseEulerAngles = new Vector3[] - { - new Vector3(0.7f, 270.0f, 357.5f), - new Vector3(288.7f, 270.1f, 357.4f), + lantern._focuserPetalsBaseEulerAngles = new Vector3[] + { + new Vector3(0.7f, 270.0f, 357.5f), + new Vector3(288.7f, 270.1f, 357.4f), new Vector3(323.3f, 90.0f, 177.5f), - new Vector3(35.3f, 90.0f, 177.5f), - new Vector3(72.7f, 270.1f, 357.5f) + new Vector3(35.3f, 90.0f, 177.5f), + new Vector3(72.7f, 270.1f, 357.5f) }; lantern._dirtyFlag_focus = true; - lantern._concealerRootsBaseScale = new Vector3[] + lantern._concealerRootsBaseScale = new Vector3[] { Vector3.one, Vector3.one, Vector3.one }; - lantern._concealerCoversStartPos = new Vector3[] + lantern._concealerCoversStartPos = new Vector3[] { new Vector3(0.0f, 0.0f, 0.0f), new Vector3(0.0f, -0.1f, 0.0f), @@ -605,7 +601,7 @@ namespace NewHorizons.Builder.Props }; lantern._dirtyFlag_concealment = true; lantern.UpdateVisuals(); - + Destroy(this); } } diff --git a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs index eeb2b959..de4116aa 100644 --- a/NewHorizons/Builder/ShipLog/MapModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/MapModeBuilder.cs @@ -26,7 +26,7 @@ namespace NewHorizons.Builder.ShipLog if (_astroObjectToMapModeInfo.TryGetValue(slao, out var mapModeInfo)) { return mapModeInfo; - } + } else { return null; @@ -147,7 +147,7 @@ namespace NewHorizons.Builder.ShipLog Rect rect = new Rect(0, 0, texture.width, texture.height); Vector2 pivot = new Vector2(texture.width / 2, texture.height / 2); - newImage.sprite = Sprite.Create(texture, rect, pivot); + newImage.sprite = Sprite.Create(texture, rect, pivot, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false); return newImageGO; } @@ -188,7 +188,7 @@ namespace NewHorizons.Builder.ShipLog Texture2D image = null; Texture2D outline = null; - + string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite; string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite; @@ -589,7 +589,7 @@ namespace NewHorizons.Builder.ShipLog GameObject newNodeGO = CreateMapModeGameObject(node.mainBody, parent, layer, position); ShipLogAstroObject astroObject = AddShipLogAstroObject(newNodeGO, node.mainBody, greyScaleMaterial, layer); if (node.mainBody.Config.FocalPoint != null) - { + { astroObject._imageObj.GetComponent().enabled = false; astroObject._outlineObj.GetComponent().enabled = false; astroObject._unviewedObj.GetComponent().enabled = false; @@ -623,7 +623,7 @@ namespace NewHorizons.Builder.ShipLog } private static void ReplaceExistingMapModeIcon(NewHorizonsBody body, ModBehaviour mod, MapModeInfo info) - { + { var astroObject = _astroObjectToShipLog[body.Object]; var gameObject = astroObject.gameObject; var layer = gameObject.layer; diff --git a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs index 7f4d28f2..daab11bb 100644 --- a/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs +++ b/NewHorizons/Builder/ShipLog/RumorModeBuilder.cs @@ -246,7 +246,7 @@ namespace NewHorizons.Builder.ShipLog Texture2D newTexture = ImageUtilities.GetTexture(body.Mod, relativePath); Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - return Sprite.Create(newTexture, rect, pivot); + return Sprite.Create(newTexture, rect, pivot, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false); } catch (Exception) { diff --git a/NewHorizons/Components/Props/ConditionalObjectActivation.cs b/NewHorizons/Components/Props/ConditionalObjectActivation.cs index a0322ecc..4036d610 100644 --- a/NewHorizons/Components/Props/ConditionalObjectActivation.cs +++ b/NewHorizons/Components/Props/ConditionalObjectActivation.cs @@ -13,7 +13,7 @@ namespace NewHorizons.Components.Props public bool CloseEyes; public bool SetActiveWithCondition; - private PlayerCameraEffectController _playerCameraEffectController; + private static PlayerCameraEffectController _playerCameraEffectController; private bool _changeConditionOnExitConversation; private bool _inConversation; @@ -45,7 +45,7 @@ namespace NewHorizons.Components.Props public void Awake() { - _playerCameraEffectController = GameObject.FindObjectOfType(); + if (_playerCameraEffectController == null) _playerCameraEffectController = GameObject.FindObjectOfType(); GlobalMessenger.AddListener("DialogueConditionChanged", OnDialogueConditionChanged); GlobalMessenger.AddListener("ExitConversation", OnExitConversation); GlobalMessenger.AddListener("EnterConversation", OnEnterConversation); diff --git a/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs b/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs index cc5636eb..0ee7a574 100644 --- a/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs +++ b/NewHorizons/Components/ShipLog/ShipLogStarChartMode.cs @@ -63,7 +63,7 @@ namespace NewHorizons.Components.ShipLog } } - /* + /* if(VesselCoordinatePromptHandler.KnowsEyeCoordinates()) { AddSystemCard("EyeOfTheUniverse"); @@ -279,7 +279,7 @@ namespace NewHorizons.Components.ShipLog { var rect = new Rect(0, 0, texture.width, texture.height); var pivot = new Vector2(texture.width / 2, texture.height / 2); - return Sprite.Create(texture, rect, pivot); + return Sprite.Create(texture, rect, pivot, 100, 0, SpriteMeshType.FullRect, Vector4.zero, false); } private void OnTargetReferenceFrame(ReferenceFrame referenceFrame) diff --git a/NewHorizons/External/Configs/PlanetConfig.cs b/NewHorizons/External/Configs/PlanetConfig.cs index 40744878..596ca54f 100644 --- a/NewHorizons/External/Configs/PlanetConfig.cs +++ b/NewHorizons/External/Configs/PlanetConfig.cs @@ -64,6 +64,11 @@ namespace NewHorizons.External.Configs /// public string[] removeChildren; + /// + /// optimization. turn this off if you know you're generating a new body and aren't worried about other addons editing it. + /// + [DefaultValue(true)] public bool checkForExisting = true; + #endregion #region Modules @@ -530,7 +535,7 @@ namespace NewHorizons.External.Configs Spawn.shipSpawnPoints = new SpawnModule.ShipSpawnPoint[] { Spawn.shipSpawn }; } - // Because these guys put TWO spawn points + // Because these guys put TWO spawn points if (starSystem == "2walker2.OogaBooga" && name == "The Campground") { Spawn.playerSpawnPoints[0].isDefault = true; @@ -761,4 +766,4 @@ namespace NewHorizons.External.Configs } #endregion } -} \ No newline at end of file +} diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index 8fe48397..858131e9 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -172,26 +172,29 @@ namespace NewHorizons.Handlers // I don't remember doing this why is it exceptions what am I doing GameObject existingPlanet = null; - try + if (body.Config.checkForExisting) // TODO: remove this when we cache name->fullpath in Find { - existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.name).gameObject; - } - catch (Exception) - { - if (body?.Config?.name == null) + try { - NHLogger.LogError($"How is there no name for {body}"); + existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.name).gameObject; } - else + catch (Exception) { - existingPlanet = SearchUtilities.Find(body.Config.name.Replace(" ", "") + "_Body", false); + if (body?.Config?.name == null) + { + NHLogger.LogError($"How is there no name for {body}"); + } + else + { + existingPlanet = SearchUtilities.Find(body.Config.name.Replace(" ", "") + "_Body", false); + } } - } - if (existingPlanet == null && body.Config.destroy) - { - NHLogger.LogError($"{body.Config.name} was meant to be destroyed, but was not found"); - return false; + if (existingPlanet == null && body.Config.destroy) + { + NHLogger.LogError($"{body.Config.name} was meant to be destroyed, but was not found"); + return false; + } } if (existingPlanet != null) @@ -291,9 +294,9 @@ namespace NewHorizons.Handlers try { NHLogger.Log($"Creating [{body.Config.name}]"); - var planetObject = GenerateBody(body, defaultPrimaryToSun) + var planetObject = GenerateBody(body, defaultPrimaryToSun) ?? throw new NullReferenceException("Something went wrong when generating the body but no errors were logged."); - + planetObject.SetActive(true); var ao = planetObject.GetComponent(); @@ -320,7 +323,7 @@ namespace NewHorizons.Handlers { NHLogger.LogError($"Error in event handler for OnPlanetLoaded on body {body.Config.name}: {e}"); } - + body.UnloadCache(true); _loadedBodies.Add(body); return true; @@ -394,7 +397,7 @@ namespace NewHorizons.Handlers body.Config.MapMarker.enabled = false; const float sphereOfInfluence = 2000f; - + var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config); var ao = AstroObjectBuilder.Make(go, null, body, false); @@ -406,7 +409,7 @@ namespace NewHorizons.Handlers BrambleDimensionBuilder.Make(body, go, ao, sector, body.Mod, owRigidBody); go = SharedGenerateBody(body, go, sector, owRigidBody); - + // Not included in SharedGenerate to not mess up gravity on base game planets if (body.Config.Base.surfaceGravity != 0) { @@ -471,7 +474,7 @@ namespace NewHorizons.Handlers } var sphereOfInfluence = GetSphereOfInfluence(body); - + var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config); var ao = AstroObjectBuilder.Make(go, primaryBody, body, false); @@ -690,7 +693,7 @@ namespace NewHorizons.Handlers SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize); } } - + if (body.Config.Atmosphere.fogSize != 0) { fog = FogBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); @@ -1003,15 +1006,10 @@ namespace NewHorizons.Handlers private static void RemoveChildren(GameObject go, NewHorizonsBody body) { - var goPath = go.transform.GetPath(); - var transforms = go.GetComponentsInChildren(true); foreach (var childPath in body.Config.removeChildren) { - // Multiple children can have the same path so we delete all that match - var path = $"{goPath}/{childPath}"; - var flag = true; - foreach (var childObj in transforms.Where(x => x.GetPath() == path)) + foreach (var childObj in go.transform.FindAll(childPath)) { flag = false; // idk why we wait here but we do diff --git a/NewHorizons/Handlers/StreamingHandler.cs b/NewHorizons/Handlers/StreamingHandler.cs index c037594d..321a07d6 100644 --- a/NewHorizons/Handlers/StreamingHandler.cs +++ b/NewHorizons/Handlers/StreamingHandler.cs @@ -2,6 +2,7 @@ using NewHorizons.Utility; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.Profiling; namespace NewHorizons.Handlers { @@ -51,6 +52,9 @@ namespace NewHorizons.Handlers /// public static void SetUpStreaming(GameObject obj, Sector sector) { + // TODO: used OFTEN by detail builder. 20-40ms adds up to seconds. speed up! + + Profiler.BeginSample("get bundles"); // find the asset bundles to load // tries the cache first, then builds if (!_objectCache.TryGetValue(obj, out var assetBundles)) @@ -94,7 +98,9 @@ namespace NewHorizons.Handlers assetBundles = assetBundlesList.ToArray(); _objectCache[obj] = assetBundles; } + Profiler.EndSample(); + Profiler.BeginSample("get sectors"); foreach (var assetBundle in assetBundles) { // Track the sector even if its null. null means stay loaded forever @@ -105,7 +111,9 @@ namespace NewHorizons.Handlers } sectors.SafeAdd(sector); } + Profiler.EndSample(); + Profiler.BeginSample("load assets"); if (sector) { sector.OnOccupantEnterSector += _ => @@ -128,6 +136,7 @@ namespace NewHorizons.Handlers foreach (var assetBundle in assetBundles) StreamingManager.LoadStreamingAssets(assetBundle); } + Profiler.EndSample(); } public static bool IsBundleInUse(string assetBundle) @@ -152,4 +161,4 @@ namespace NewHorizons.Handlers } } } -} \ No newline at end of file +} diff --git a/NewHorizons/Handlers/SubtitlesHandler.cs b/NewHorizons/Handlers/SubtitlesHandler.cs index 1a42bc79..326b2e0c 100644 --- a/NewHorizons/Handlers/SubtitlesHandler.cs +++ b/NewHorizons/Handlers/SubtitlesHandler.cs @@ -109,7 +109,7 @@ namespace NewHorizons.Handlers var tex = ImageUtilities.GetTexture(mod, filepath, false); if (tex == null) return; - var sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100.0f); + var sprite = Sprite.Create(tex, new Rect(0.0f, 0.0f, tex.width, tex.height), new Vector2(0.5f, 0.5f), 100, 0, SpriteMeshType.FullRect, Vector4.zero, false); AddSubtitle(sprite); } diff --git a/NewHorizons/Handlers/VesselCoordinatePromptHandler.cs b/NewHorizons/Handlers/VesselCoordinatePromptHandler.cs index d53eb875..a55be9c9 100644 --- a/NewHorizons/Handlers/VesselCoordinatePromptHandler.cs +++ b/NewHorizons/Handlers/VesselCoordinatePromptHandler.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.UI; using static NewHorizons.External.Configs.StarSystemConfig; namespace NewHorizons.Handlers @@ -47,7 +48,7 @@ namespace NewHorizons.Handlers if (_textureCache == null) _textureCache = new List(); _textureCache.Add(texture); - var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(texture.width / 2f, texture.height / 2f)); + var sprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(texture.width / 2f, texture.height / 2f), 100, 0, SpriteMeshType.FullRect, Vector4.zero, false); var name = ShipLogStarChartMode.UniqueIDToName(systemID); diff --git a/NewHorizons/NewHorizons.csproj b/NewHorizons/NewHorizons.csproj index 5ae0cd1c..a38229e0 100644 --- a/NewHorizons/NewHorizons.csproj +++ b/NewHorizons/NewHorizons.csproj @@ -10,6 +10,8 @@ true None 1701;1702;1591 + + none @@ -39,4 +41,4 @@ - \ No newline at end of file + diff --git a/NewHorizons/Patches/ProfilerPatch.cs b/NewHorizons/Patches/ProfilerPatch.cs new file mode 100644 index 00000000..9cdde508 --- /dev/null +++ b/NewHorizons/Patches/ProfilerPatch.cs @@ -0,0 +1,73 @@ +#if ENABLE_PROFILER + +using HarmonyLib; +using System.Collections.Generic; +using System.Reflection; +using UnityEngine; +using UnityEngine.Profiling; + +namespace NewHorizons.Patches; + +/// +/// attach profiler markers to important methods +/// +[HarmonyPatch] +public static class ProfilerPatch +{ + private static string FriendlyName(this MethodBase @this) => $"{@this.DeclaringType.Name}.{@this.Name}"; + + [HarmonyTargetMethods] + public static IEnumerable TargetMethods() + { + foreach (var type in Assembly.GetExecutingAssembly().GetTypes()) + { + if (!( + type.Name == "Main" || + type.Name.EndsWith("Builder") || + type.Name.EndsWith("Handler") || + type.Name.EndsWith("Utilities") + )) continue; + + foreach (var method in type.GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly)) + { + if (method.ContainsGenericParameters) continue; + + // Main.Instance.ModHelper.Console.WriteLine($"[profiler] profiling {method.FriendlyName()}"); + yield return method; + } + } + } + + [HarmonyPrefix] + public static void Prefix(MethodBase __originalMethod /*, out Stopwatch __state*/) + { + Profiler.BeginSample(__originalMethod.FriendlyName()); + + // __state = new Stopwatch(); + // __state.Start(); + } + + [HarmonyPostfix] + public static void Postfix( /*MethodBase __originalMethod, Stopwatch __state*/) + { + Profiler.EndSample(); + + // __state.Stop(); + // Main.Instance.ModHelper.Console.WriteLine($"[profiler] {__originalMethod.MethodName()} took {__state.Elapsed.TotalMilliseconds:f1} ms"); + } +} + +/// +/// bundle loading causes log spam that slows loading, but only in unity dev profiler mode. +/// patch it out so it doesnt do false-positive slowness. +/// +[HarmonyPatch] +public static class DisableShaderLogSpamPatch +{ + [HarmonyPrefix] + [HarmonyPatch(typeof(StackTraceUtility), "ExtractStackTrace")] + [HarmonyPatch(typeof(Application), "CallLogCallback")] + private static bool DisableShaderLogSpam() => false; +} + +#endif diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index a06d1bf4..f5ed593d 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -43,6 +43,11 @@ "type": "string" } }, + "checkForExisting": { + "type": "boolean", + "description": "optimization. turn this off if you know you're generating a new body and aren't worried about other addons editing it.", + "default": true + }, "AmbientLights": { "type": "array", "description": "Add ambient lights to this body", diff --git a/NewHorizons/Utility/Files/AssetBundleUtilities.cs b/NewHorizons/Utility/Files/AssetBundleUtilities.cs index 87170770..0cdd2a9b 100644 --- a/NewHorizons/Utility/Files/AssetBundleUtilities.cs +++ b/NewHorizons/Utility/Files/AssetBundleUtilities.cs @@ -12,6 +12,7 @@ namespace NewHorizons.Utility.Files public static class AssetBundleUtilities { public static Dictionary AssetBundles = new(); + private static Dictionary _prefabCache = new(); private static readonly List _loadingBundles = new(); @@ -52,6 +53,7 @@ namespace NewHorizons.Utility.Files } AssetBundles = AssetBundles.Where(x => x.Value.keepLoaded).ToDictionary(x => x.Key, x => x.Value); + _prefabCache.Clear(); } public static void PreloadBundle(string assetBundleRelativeDir, IModBehaviour mod) @@ -113,11 +115,17 @@ namespace NewHorizons.Utility.Files public static GameObject LoadPrefab(string assetBundleRelativeDir, string pathInBundle, IModBehaviour mod) { - var prefab = Load(assetBundleRelativeDir, pathInBundle, mod); + if (_prefabCache.TryGetValue(assetBundleRelativeDir + pathInBundle, out var prefab)) + return prefab; + + prefab = Load(assetBundleRelativeDir, pathInBundle, mod); prefab.SetActive(false); ReplaceShaders(prefab); + + // replacing shaders is expensive, so cache it + _prefabCache.Add(assetBundleRelativeDir + pathInBundle, prefab); return prefab; } diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index 36e656e6..b6086917 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -2,6 +2,7 @@ using NewHorizons.Utility.OWML; using System.Collections.Generic; using System.Linq; using UnityEngine; +using UnityEngine.Profiling; using UnityEngine.SceneManagement; using Object = UnityEngine.Object; @@ -116,19 +117,23 @@ namespace NewHorizons.Utility if (CachedGameObjects.TryGetValue(path, out var go)) return go; // 1: normal find + Profiler.BeginSample("1"); go = GameObject.Find(path); if (go) { CachedGameObjects.Add(path, go); + Profiler.EndSample(); return go; } + Profiler.EndSample(); + Profiler.BeginSample("2"); // 2: find inactive using root + transform.find var names = path.Split('/'); // Cache the root objects so we don't loop through all of them each time var rootName = names[0]; - if (!CachedRootGameObjects.TryGetValue(rootName, out var root)) + if (!CachedRootGameObjects.TryGetValue(rootName, out var root)) { root = SceneManager.GetActiveScene().GetRootGameObjects().FirstOrDefault(x => x.name == rootName); if (root != null) @@ -142,9 +147,12 @@ namespace NewHorizons.Utility if (go) { CachedGameObjects.Add(path, go); + Profiler.EndSample(); return go; } + Profiler.EndSample(); + Profiler.BeginSample("3"); var name = names.Last(); if (warn) NHLogger.LogWarning($"Couldn't find object in path {path}, will look for potential matches for name {name}"); // 3: find resource to include inactive objects (but skip prefabs) @@ -153,10 +161,12 @@ namespace NewHorizons.Utility if (go) { CachedGameObjects.Add(path, go); + Profiler.EndSample(); return go; } if (warn) NHLogger.LogWarning($"Couldn't find object with name {name}"); + Profiler.EndSample(); return null; } @@ -169,5 +179,31 @@ namespace NewHorizons.Utility } return children; } + + /// + /// transform.find but works for gameobjects with same name + /// + public static List FindAll(this Transform @this, string path) + { + var names = path.Split('/'); + var currentTransforms = new List { @this }; + foreach (var name in names) + { + var newTransforms = new List(); + foreach (var currentTransform in currentTransforms) + { + foreach (Transform child in currentTransform) + { + if (child.name == name) + { + newTransforms.Add(child); + } + } + } + currentTransforms = newTransforms; + } + + return currentTransforms; + } } }