profiling nh (#1030)

semi-automated profile marker generation. disable-able with a
project-wide compiler flag
This commit is contained in:
xen-42 2025-02-15 23:38:55 -05:00 committed by GitHub
commit 7697e5bb49
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
15 changed files with 196 additions and 63 deletions

View File

@ -56,6 +56,7 @@ namespace NewHorizons.Builder.Props
private static void SceneManager_sceneUnloaded(Scene scene) 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) foreach (var prefab in _fixedPrefabCache.Values)
{ {
UnityEngine.Object.Destroy(prefab.prefab); UnityEngine.Object.Destroy(prefab.prefab);
@ -230,15 +231,10 @@ namespace NewHorizons.Builder.Props
if (detail.removeChildren != null) if (detail.removeChildren != null)
{ {
var detailPath = prop.transform.GetPath();
var transforms = prop.GetComponentsInChildren<Transform>(true);
foreach (var childPath in detail.removeChildren) 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; var flag = true;
foreach (var childObj in transforms.Where(x => x.GetPath() == path)) foreach (var childObj in prop.transform.FindAll(childPath))
{ {
flag = false; flag = false;
childObj.gameObject.SetActive(false); childObj.gameObject.SetActive(false);
@ -274,7 +270,7 @@ namespace NewHorizons.Builder.Props
UnityEngine.Object.DestroyImmediate(prop); UnityEngine.Object.DestroyImmediate(prop);
prop = newDetailGO; prop = newDetailGO;
} }
if (isItem) if (isItem)
{ {
// Else when you put them down you can't pick them back up // 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 // For DLC related props
// Make sure to do this before its set active // 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"))) (detail.path.ToLowerInvariant().StartsWith("ringworld") || detail.path.ToLowerInvariant().StartsWith("dreamworld")))
{ {
prop.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true; prop.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true;
@ -305,7 +301,7 @@ namespace NewHorizons.Builder.Props
if (!string.IsNullOrEmpty(detail.activationCondition)) 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)) 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) // Manually copied these values from a artifact lantern so that we don't have to find it (works in Eye)
lantern._origLensFlareBrightness = 0f; lantern._origLensFlareBrightness = 0f;
lantern._focuserPetalsBaseEulerAngles = new Vector3[] lantern._focuserPetalsBaseEulerAngles = new Vector3[]
{ {
new Vector3(0.7f, 270.0f, 357.5f), new Vector3(0.7f, 270.0f, 357.5f),
new Vector3(288.7f, 270.1f, 357.4f), new Vector3(288.7f, 270.1f, 357.4f),
new Vector3(323.3f, 90.0f, 177.5f), new Vector3(323.3f, 90.0f, 177.5f),
new Vector3(35.3f, 90.0f, 177.5f), new Vector3(35.3f, 90.0f, 177.5f),
new Vector3(72.7f, 270.1f, 357.5f) new Vector3(72.7f, 270.1f, 357.5f)
}; };
lantern._dirtyFlag_focus = true; lantern._dirtyFlag_focus = true;
lantern._concealerRootsBaseScale = new Vector3[] lantern._concealerRootsBaseScale = new Vector3[]
{ {
Vector3.one, Vector3.one,
Vector3.one, 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.0f, 0.0f),
new Vector3(0.0f, -0.1f, 0.0f), new Vector3(0.0f, -0.1f, 0.0f),
@ -605,7 +601,7 @@ namespace NewHorizons.Builder.Props
}; };
lantern._dirtyFlag_concealment = true; lantern._dirtyFlag_concealment = true;
lantern.UpdateVisuals(); lantern.UpdateVisuals();
Destroy(this); Destroy(this);
} }
} }

View File

@ -26,7 +26,7 @@ namespace NewHorizons.Builder.ShipLog
if (_astroObjectToMapModeInfo.TryGetValue(slao, out var mapModeInfo)) if (_astroObjectToMapModeInfo.TryGetValue(slao, out var mapModeInfo))
{ {
return mapModeInfo; return mapModeInfo;
} }
else else
{ {
return null; return null;
@ -147,7 +147,7 @@ namespace NewHorizons.Builder.ShipLog
Rect rect = new Rect(0, 0, texture.width, texture.height); Rect rect = new Rect(0, 0, texture.width, texture.height);
Vector2 pivot = new Vector2(texture.width / 2, texture.height / 2); 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; return newImageGO;
} }
@ -188,7 +188,7 @@ namespace NewHorizons.Builder.ShipLog
Texture2D image = null; Texture2D image = null;
Texture2D outline = null; Texture2D outline = null;
string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite; string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite;
string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite; string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite;
@ -589,7 +589,7 @@ namespace NewHorizons.Builder.ShipLog
GameObject newNodeGO = CreateMapModeGameObject(node.mainBody, parent, layer, position); GameObject newNodeGO = CreateMapModeGameObject(node.mainBody, parent, layer, position);
ShipLogAstroObject astroObject = AddShipLogAstroObject(newNodeGO, node.mainBody, greyScaleMaterial, layer); ShipLogAstroObject astroObject = AddShipLogAstroObject(newNodeGO, node.mainBody, greyScaleMaterial, layer);
if (node.mainBody.Config.FocalPoint != null) if (node.mainBody.Config.FocalPoint != null)
{ {
astroObject._imageObj.GetComponent<Image>().enabled = false; astroObject._imageObj.GetComponent<Image>().enabled = false;
astroObject._outlineObj.GetComponent<Image>().enabled = false; astroObject._outlineObj.GetComponent<Image>().enabled = false;
astroObject._unviewedObj.GetComponent<Image>().enabled = false; astroObject._unviewedObj.GetComponent<Image>().enabled = false;
@ -623,7 +623,7 @@ namespace NewHorizons.Builder.ShipLog
} }
private static void ReplaceExistingMapModeIcon(NewHorizonsBody body, ModBehaviour mod, MapModeInfo info) private static void ReplaceExistingMapModeIcon(NewHorizonsBody body, ModBehaviour mod, MapModeInfo info)
{ {
var astroObject = _astroObjectToShipLog[body.Object]; var astroObject = _astroObjectToShipLog[body.Object];
var gameObject = astroObject.gameObject; var gameObject = astroObject.gameObject;
var layer = gameObject.layer; var layer = gameObject.layer;

View File

@ -246,7 +246,7 @@ namespace NewHorizons.Builder.ShipLog
Texture2D newTexture = ImageUtilities.GetTexture(body.Mod, relativePath); Texture2D newTexture = ImageUtilities.GetTexture(body.Mod, relativePath);
Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); Rect rect = new Rect(0, 0, newTexture.width, newTexture.height);
Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); 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) catch (Exception)
{ {

View File

@ -13,7 +13,7 @@ namespace NewHorizons.Components.Props
public bool CloseEyes; public bool CloseEyes;
public bool SetActiveWithCondition; public bool SetActiveWithCondition;
private PlayerCameraEffectController _playerCameraEffectController; private static PlayerCameraEffectController _playerCameraEffectController;
private bool _changeConditionOnExitConversation; private bool _changeConditionOnExitConversation;
private bool _inConversation; private bool _inConversation;
@ -45,7 +45,7 @@ namespace NewHorizons.Components.Props
public void Awake() public void Awake()
{ {
_playerCameraEffectController = GameObject.FindObjectOfType<PlayerCameraEffectController>(); if (_playerCameraEffectController == null) _playerCameraEffectController = GameObject.FindObjectOfType<PlayerCameraEffectController>();
GlobalMessenger<string, bool>.AddListener("DialogueConditionChanged", OnDialogueConditionChanged); GlobalMessenger<string, bool>.AddListener("DialogueConditionChanged", OnDialogueConditionChanged);
GlobalMessenger.AddListener("ExitConversation", OnExitConversation); GlobalMessenger.AddListener("ExitConversation", OnExitConversation);
GlobalMessenger.AddListener("EnterConversation", OnEnterConversation); GlobalMessenger.AddListener("EnterConversation", OnEnterConversation);

View File

@ -63,7 +63,7 @@ namespace NewHorizons.Components.ShipLog
} }
} }
/* /*
if(VesselCoordinatePromptHandler.KnowsEyeCoordinates()) if(VesselCoordinatePromptHandler.KnowsEyeCoordinates())
{ {
AddSystemCard("EyeOfTheUniverse"); AddSystemCard("EyeOfTheUniverse");
@ -279,7 +279,7 @@ namespace NewHorizons.Components.ShipLog
{ {
var rect = new Rect(0, 0, texture.width, texture.height); var rect = new Rect(0, 0, texture.width, texture.height);
var pivot = new Vector2(texture.width / 2, texture.height / 2); 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) private void OnTargetReferenceFrame(ReferenceFrame referenceFrame)

View File

@ -64,6 +64,11 @@ namespace NewHorizons.External.Configs
/// </summary> /// </summary>
public string[] removeChildren; public string[] removeChildren;
/// <summary>
/// optimization. turn this off if you know you're generating a new body and aren't worried about other addons editing it.
/// </summary>
[DefaultValue(true)] public bool checkForExisting = true;
#endregion #endregion
#region Modules #region Modules
@ -530,7 +535,7 @@ namespace NewHorizons.External.Configs
Spawn.shipSpawnPoints = new SpawnModule.ShipSpawnPoint[] { Spawn.shipSpawn }; 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") if (starSystem == "2walker2.OogaBooga" && name == "The Campground")
{ {
Spawn.playerSpawnPoints[0].isDefault = true; Spawn.playerSpawnPoints[0].isDefault = true;
@ -761,4 +766,4 @@ namespace NewHorizons.External.Configs
} }
#endregion #endregion
} }
} }

View File

@ -172,26 +172,29 @@ namespace NewHorizons.Handlers
// I don't remember doing this why is it exceptions what am I doing // I don't remember doing this why is it exceptions what am I doing
GameObject existingPlanet = null; 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; try
}
catch (Exception)
{
if (body?.Config?.name == null)
{ {
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) if (existingPlanet == null && body.Config.destroy)
{ {
NHLogger.LogError($"{body.Config.name} was meant to be destroyed, but was not found"); NHLogger.LogError($"{body.Config.name} was meant to be destroyed, but was not found");
return false; return false;
}
} }
if (existingPlanet != null) if (existingPlanet != null)
@ -291,9 +294,9 @@ namespace NewHorizons.Handlers
try try
{ {
NHLogger.Log($"Creating [{body.Config.name}]"); 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."); ?? throw new NullReferenceException("Something went wrong when generating the body but no errors were logged.");
planetObject.SetActive(true); planetObject.SetActive(true);
var ao = planetObject.GetComponent<NHAstroObject>(); var ao = planetObject.GetComponent<NHAstroObject>();
@ -320,7 +323,7 @@ namespace NewHorizons.Handlers
{ {
NHLogger.LogError($"Error in event handler for OnPlanetLoaded on body {body.Config.name}: {e}"); NHLogger.LogError($"Error in event handler for OnPlanetLoaded on body {body.Config.name}: {e}");
} }
body.UnloadCache(true); body.UnloadCache(true);
_loadedBodies.Add(body); _loadedBodies.Add(body);
return true; return true;
@ -394,7 +397,7 @@ namespace NewHorizons.Handlers
body.Config.MapMarker.enabled = false; body.Config.MapMarker.enabled = false;
const float sphereOfInfluence = 2000f; const float sphereOfInfluence = 2000f;
var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config); var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config);
var ao = AstroObjectBuilder.Make(go, null, body, false); var ao = AstroObjectBuilder.Make(go, null, body, false);
@ -406,7 +409,7 @@ namespace NewHorizons.Handlers
BrambleDimensionBuilder.Make(body, go, ao, sector, body.Mod, owRigidBody); BrambleDimensionBuilder.Make(body, go, ao, sector, body.Mod, owRigidBody);
go = SharedGenerateBody(body, go, sector, owRigidBody); go = SharedGenerateBody(body, go, sector, owRigidBody);
// Not included in SharedGenerate to not mess up gravity on base game planets // Not included in SharedGenerate to not mess up gravity on base game planets
if (body.Config.Base.surfaceGravity != 0) if (body.Config.Base.surfaceGravity != 0)
{ {
@ -471,7 +474,7 @@ namespace NewHorizons.Handlers
} }
var sphereOfInfluence = GetSphereOfInfluence(body); var sphereOfInfluence = GetSphereOfInfluence(body);
var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config); var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config);
var ao = AstroObjectBuilder.Make(go, primaryBody, body, false); 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); SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize);
} }
} }
if (body.Config.Atmosphere.fogSize != 0) if (body.Config.Atmosphere.fogSize != 0)
{ {
fog = FogBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); 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) private static void RemoveChildren(GameObject go, NewHorizonsBody body)
{ {
var goPath = go.transform.GetPath();
var transforms = go.GetComponentsInChildren<Transform>(true);
foreach (var childPath in body.Config.removeChildren) 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; var flag = true;
foreach (var childObj in transforms.Where(x => x.GetPath() == path)) foreach (var childObj in go.transform.FindAll(childPath))
{ {
flag = false; flag = false;
// idk why we wait here but we do // idk why we wait here but we do

View File

@ -2,6 +2,7 @@ using NewHorizons.Utility;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.Profiling;
namespace NewHorizons.Handlers namespace NewHorizons.Handlers
{ {
@ -51,6 +52,9 @@ namespace NewHorizons.Handlers
/// </summary> /// </summary>
public static void SetUpStreaming(GameObject obj, Sector sector) 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 // find the asset bundles to load
// tries the cache first, then builds // tries the cache first, then builds
if (!_objectCache.TryGetValue(obj, out var assetBundles)) if (!_objectCache.TryGetValue(obj, out var assetBundles))
@ -94,7 +98,9 @@ namespace NewHorizons.Handlers
assetBundles = assetBundlesList.ToArray(); assetBundles = assetBundlesList.ToArray();
_objectCache[obj] = assetBundles; _objectCache[obj] = assetBundles;
} }
Profiler.EndSample();
Profiler.BeginSample("get sectors");
foreach (var assetBundle in assetBundles) foreach (var assetBundle in assetBundles)
{ {
// Track the sector even if its null. null means stay loaded forever // Track the sector even if its null. null means stay loaded forever
@ -105,7 +111,9 @@ namespace NewHorizons.Handlers
} }
sectors.SafeAdd(sector); sectors.SafeAdd(sector);
} }
Profiler.EndSample();
Profiler.BeginSample("load assets");
if (sector) if (sector)
{ {
sector.OnOccupantEnterSector += _ => sector.OnOccupantEnterSector += _ =>
@ -128,6 +136,7 @@ namespace NewHorizons.Handlers
foreach (var assetBundle in assetBundles) foreach (var assetBundle in assetBundles)
StreamingManager.LoadStreamingAssets(assetBundle); StreamingManager.LoadStreamingAssets(assetBundle);
} }
Profiler.EndSample();
} }
public static bool IsBundleInUse(string assetBundle) public static bool IsBundleInUse(string assetBundle)
@ -152,4 +161,4 @@ namespace NewHorizons.Handlers
} }
} }
} }
} }

View File

@ -109,7 +109,7 @@ namespace NewHorizons.Handlers
var tex = ImageUtilities.GetTexture(mod, filepath, false); var tex = ImageUtilities.GetTexture(mod, filepath, false);
if (tex == null) return; 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); AddSubtitle(sprite);
} }

View File

@ -4,6 +4,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.UI;
using static NewHorizons.External.Configs.StarSystemConfig; using static NewHorizons.External.Configs.StarSystemConfig;
namespace NewHorizons.Handlers namespace NewHorizons.Handlers
@ -47,7 +48,7 @@ namespace NewHorizons.Handlers
if (_textureCache == null) _textureCache = new List<Texture2D>(); if (_textureCache == null) _textureCache = new List<Texture2D>();
_textureCache.Add(texture); _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); var name = ShipLogStarChartMode.UniqueIDToName(systemID);

View File

@ -10,6 +10,8 @@
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch> <ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>None</ResolveAssemblyWarnOrErrorOnTargetArchitectureMismatch>
<NoWarn>1701;1702;1591</NoWarn> <NoWarn>1701;1702;1591</NoWarn>
<!-- <DefineConstants>ENABLE_PROFILER</DefineConstants>-->
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>none</DebugType> <DebugType>none</DebugType>
@ -39,4 +41,4 @@
<ItemGroup> <ItemGroup>
<Content Include="NewHorizons.csproj.user" /> <Content Include="NewHorizons.csproj.user" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@ -0,0 +1,73 @@
#if ENABLE_PROFILER
using HarmonyLib;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
using UnityEngine.Profiling;
namespace NewHorizons.Patches;
/// <summary>
/// attach profiler markers to important methods
/// </summary>
[HarmonyPatch]
public static class ProfilerPatch
{
private static string FriendlyName(this MethodBase @this) => $"{@this.DeclaringType.Name}.{@this.Name}";
[HarmonyTargetMethods]
public static IEnumerable<MethodBase> 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");
}
}
/// <summary>
/// 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.
/// </summary>
[HarmonyPatch]
public static class DisableShaderLogSpamPatch
{
[HarmonyPrefix]
[HarmonyPatch(typeof(StackTraceUtility), "ExtractStackTrace")]
[HarmonyPatch(typeof(Application), "CallLogCallback")]
private static bool DisableShaderLogSpam() => false;
}
#endif

View File

@ -43,6 +43,11 @@
"type": "string" "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": { "AmbientLights": {
"type": "array", "type": "array",
"description": "Add ambient lights to this body", "description": "Add ambient lights to this body",

View File

@ -12,6 +12,7 @@ namespace NewHorizons.Utility.Files
public static class AssetBundleUtilities public static class AssetBundleUtilities
{ {
public static Dictionary<string, (AssetBundle bundle, bool keepLoaded)> AssetBundles = new(); public static Dictionary<string, (AssetBundle bundle, bool keepLoaded)> AssetBundles = new();
private static Dictionary<string, GameObject> _prefabCache = new();
private static readonly List<AssetBundleCreateRequest> _loadingBundles = new(); private static readonly List<AssetBundleCreateRequest> _loadingBundles = new();
@ -52,6 +53,7 @@ namespace NewHorizons.Utility.Files
} }
AssetBundles = AssetBundles.Where(x => x.Value.keepLoaded).ToDictionary(x => x.Key, x => x.Value); AssetBundles = AssetBundles.Where(x => x.Value.keepLoaded).ToDictionary(x => x.Key, x => x.Value);
_prefabCache.Clear();
} }
public static void PreloadBundle(string assetBundleRelativeDir, IModBehaviour mod) 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) public static GameObject LoadPrefab(string assetBundleRelativeDir, string pathInBundle, IModBehaviour mod)
{ {
var prefab = Load<GameObject>(assetBundleRelativeDir, pathInBundle, mod); if (_prefabCache.TryGetValue(assetBundleRelativeDir + pathInBundle, out var prefab))
return prefab;
prefab = Load<GameObject>(assetBundleRelativeDir, pathInBundle, mod);
prefab.SetActive(false); prefab.SetActive(false);
ReplaceShaders(prefab); ReplaceShaders(prefab);
// replacing shaders is expensive, so cache it
_prefabCache.Add(assetBundleRelativeDir + pathInBundle, prefab);
return prefab; return prefab;
} }

View File

@ -2,6 +2,7 @@ using NewHorizons.Utility.OWML;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.Profiling;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
@ -116,19 +117,23 @@ namespace NewHorizons.Utility
if (CachedGameObjects.TryGetValue(path, out var go)) return go; if (CachedGameObjects.TryGetValue(path, out var go)) return go;
// 1: normal find // 1: normal find
Profiler.BeginSample("1");
go = GameObject.Find(path); go = GameObject.Find(path);
if (go) if (go)
{ {
CachedGameObjects.Add(path, go); CachedGameObjects.Add(path, go);
Profiler.EndSample();
return go; return go;
} }
Profiler.EndSample();
Profiler.BeginSample("2");
// 2: find inactive using root + transform.find // 2: find inactive using root + transform.find
var names = path.Split('/'); var names = path.Split('/');
// Cache the root objects so we don't loop through all of them each time // Cache the root objects so we don't loop through all of them each time
var rootName = names[0]; 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); root = SceneManager.GetActiveScene().GetRootGameObjects().FirstOrDefault(x => x.name == rootName);
if (root != null) if (root != null)
@ -142,9 +147,12 @@ namespace NewHorizons.Utility
if (go) if (go)
{ {
CachedGameObjects.Add(path, go); CachedGameObjects.Add(path, go);
Profiler.EndSample();
return go; return go;
} }
Profiler.EndSample();
Profiler.BeginSample("3");
var name = names.Last(); var name = names.Last();
if (warn) NHLogger.LogWarning($"Couldn't find object in path {path}, will look for potential matches for name {name}"); 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) // 3: find resource to include inactive objects (but skip prefabs)
@ -153,10 +161,12 @@ namespace NewHorizons.Utility
if (go) if (go)
{ {
CachedGameObjects.Add(path, go); CachedGameObjects.Add(path, go);
Profiler.EndSample();
return go; return go;
} }
if (warn) NHLogger.LogWarning($"Couldn't find object with name {name}"); if (warn) NHLogger.LogWarning($"Couldn't find object with name {name}");
Profiler.EndSample();
return null; return null;
} }
@ -169,5 +179,31 @@ namespace NewHorizons.Utility
} }
return children; return children;
} }
/// <summary>
/// transform.find but works for gameobjects with same name
/// </summary>
public static List<Transform> FindAll(this Transform @this, string path)
{
var names = path.Split('/');
var currentTransforms = new List<Transform> { @this };
foreach (var name in names)
{
var newTransforms = new List<Transform>();
foreach (var currentTransform in currentTransforms)
{
foreach (Transform child in currentTransform)
{
if (child.name == name)
{
newTransforms.Add(child);
}
}
}
currentTransforms = newTransforms;
}
return currentTransforms;
}
} }
} }