You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There seems to be another issue that closes/crashes the game immediately on games with lots of components.
The call stack count can grow to enormous numbers, this happens because components that are finished loading directly call other components OnLoaded callbacks, which again directly call other components.
The problem here is two fold
many of the components with dependencies subscribe to a generic callback
dataManager.MessageCenter.AddSubscriber(MessageCenterMessageType.DataManagerRequestCompleteMessage, new ReceiveMessageCenterMessage(this.CheckDependenciesAfterLoad));
components, once all dependencies are loaded, call the following directly
This can produce a cascade effect with lots of callers.
e.g. if a SVG is finally loaded, a weapondef could finally met its dependencies and is finished loaded. then the onloaded method is called which again finds another weapondefs dependency check to call.
so a trace like
SVGAsset loaded -> WeaponDef complete -> WeaponDef complete ... can come about.
It can then even continue after ~4500 stack frames with a MechDef.Refresh call (at which point I wasn't logging anymore).
Provide an example of the code where the problem occurs
Part of a stack trace (just some lines, these can easily grow to the thousands of stack frames for a single call)
at MessageCenter.SendMessagesForType(MessageCenterMessageType messageType, .MessageCenterMessage message)
at MessageCenter.PublishMessage(.MessageCenterMessage message)
at BattleTech.Data.DataManager+ResourceLoadRequest`1.NotifyLoadComplete()
at BattleTech.Data.DataManager+WeaponDefLoadRequest.OnLoaded()
at BattleTech.MechComponentDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at BattleTech.WeaponDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at MessageCenter.SendMessagesForType(MessageCenterMessageType messageType, .MessageCenterMessage message)
at MessageCenter.PublishMessage(.MessageCenterMessage message)
at BattleTech.Data.DataManager+ResourceLoadRequest`1.NotifyLoadComplete()
at BattleTech.Data.DataManager+WeaponDefLoadRequest.OnLoaded()
at BattleTech.MechComponentDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at BattleTech.WeaponDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at MessageCenter.SendMessagesForType(MessageCenterMessageType messageType, .MessageCenterMessage message)
at MessageCenter.PublishMessage(.MessageCenterMessage message)
at BattleTech.Data.DataManager+ResourceLoadRequest`1.NotifyLoadComplete()
at BattleTech.Data.DataManager+WeaponDefLoadRequest.OnLoaded()
at BattleTech.MechComponentDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at BattleTech.WeaponDef.CheckDependenciesAfterLoad(.MessageCenterMessage message)
at MessageCenter.SendMessagesForType(MessageCenterMessageType messageType, .MessageCenterMessage message)
at MessageCenter.PublishMessage(.MessageCenterMessage message)
at BattleTech.Data.DataManager+ResourceLoadRequest`1.NotifyLoadComplete()
at BattleTech.Data.DataManager+SVGAssetLoadRequest.OnLoaded()
at BattleTech.Data.DataManager+SVGAssetLoadRequest.AssetLoaded(SVGImporter.SVGAsset resource)
at BattleTech.Data.DataManager+GenericResourceRequestHelper`1[[SVGImporter.SVGAsset, Assembly-CSharp-firstpass, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]].Complete()
at BattleTech.Data.DataManager.Update(Single deltaTime)
at BattleTech.GameInstance.Update(Single deltaTime)
at BattleTech.UnityGameInstance.Update()
Provide an example of your proposed solution
Seems to be a fundamental issue, instead of directly calling the completion, one would need to queue the notification and then only the top-most caller of the in the call stack should do some kind of iteration. Well you know the issue with recursion vs iteration.
For now I did a quick hack by capturing and managing mechdef dependencies at the data manager level. It works quite well and can really trim the stack. A more generic version can potentially be done for all ResourceLoadRequest which will make more sense.
Describe the problem
There seems to be another issue that closes/crashes the game immediately on games with lots of components.
The call stack count can grow to enormous numbers, this happens because components that are finished loading directly call other components OnLoaded callbacks, which again directly call other components.
The problem here is two fold
This can produce a cascade effect with lots of callers.
e.g. if a SVG is finally loaded, a weapondef could finally met its dependencies and is finished loaded. then the onloaded method is called which again finds another weapondefs dependency check to call.
so a trace like
SVGAsset loaded -> WeaponDef complete -> WeaponDef complete ... can come about.
It can then even continue after ~4500 stack frames with a MechDef.Refresh call (at which point I wasn't logging anymore).
Provide an example of the code where the problem occurs
Part of a stack trace (just some lines, these can easily grow to the thousands of stack frames for a single call)
Provide an example of your proposed solution
Seems to be a fundamental issue, instead of directly calling the completion, one would need to queue the notification and then only the top-most caller of the in the call stack should do some kind of iteration. Well you know the issue with recursion vs iteration.
Leave any additional comments here
smaller call stack example:
weapondef_loop_sample.txt
larger call stack example:
mechdef_loop_sample.txt
The text was updated successfully, but these errors were encountered: