{"id":1113,"date":"2026-07-30T18:11:23","date_gmt":"2026-07-30T18:11:23","guid":{"rendered":"https:\/\/docs.sisus.co\/init-args\/?p=1113"},"modified":"2026-07-31T07:14:31","modified_gmt":"2026-07-31T07:14:31","slug":"modding-support","status":"publish","type":"post","link":"https:\/\/docs.sisus.co\/init-args\/advanced\/modding-support\/","title":{"rendered":"Modding Support"},"content":{"rendered":"<h1>Dynamically Loaded Assemblies<\/h1>\n<p>Init(args) supports creating <a href=\"https:\/\/docs.sisus.co\/init-args\/reference\/global-services\/\">global services<\/a> registered using the <a href=\"https:\/\/docs.sisus.co\/init-args\/services\/service-attribute\/\">[Service] attribute<\/a> from assemblies that are loaded at runtime.<\/p>\n<p>If the assembly is loaded before Init(args) has finished initializing global services, then global services registered in the assembly using the [Service] attribute will get initialized as part of the initial service registration process. This occurs during the <a href=\"https:\/\/docs.unity3d.com\/ScriptReference\/RuntimeInitializeLoadType.BeforeSceneLoad.html\">[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]<\/a> event.<\/p>\n<p>If the assembly is loaded after initial global service initialization has finished, then non-lazy global services will found in the assembly be created when the assembly is loaded, and lazy global services will be created after the first client requests them after the assembly has been loaded.<\/p>\n<h1>Replacing Global Services<\/h1>\n<h2>Using Service.Register<\/h2>\n<pre>[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]\r\nstatic void InitServices() =&gt; ServiceUtility.ServiceInitializationStarting += OnServiceInitializationStarting;\r\n\r\nstatic void OnServiceInitializationStarting()\r\n{\r\n  Service.Create&lt;SomeServiceReplacement, SomeService&gt;();\r\n}\r\n\r\nclass SomeServiceReplacement : SomeService\r\n{\r\n  public override void DoSomething() =&gt; Debug.Log(\"Hello from mod!\");\r\n}<\/pre>\n<h2>Using Local Services<\/h2>\n<p>Because clients prioritize <a href=\"https:\/\/docs.sisus.co\/init-args\/reference\/local-services\/\">local services<\/a> registered using a <a href=\"https:\/\/docs.sisus.co\/init-args\/services\/service-tag\/\">Service Tag<\/a>, a <a href=\"https:\/\/docs.sisus.co\/init-args\/services\/services-component\/\">Services component<\/a> and <a href=\"https:\/\/docs.sisus.co\/init-args-reference\/class_sisus_1_1_init_1_1_service.html\">Service.AddFor<\/a> over global services registered using the [Service] attribute, it is possible for a mod to effectively replace a global service using them.<\/p>\n<pre>var newService = new SomeServiceReplacement();\r\nService.AddFor&lt;SomeService&gt;(Clients.Everywhere, newService, registerer: this);\r\n\r\n...\r\n\r\nclass SomeServiceReplacement : SomeService\r\n{\r\n    public override void DoSomething() =&gt; Debug.Log(\"Hello from mod!\");\r\n}<\/pre>\n<h1>Decorating Global Services<\/h1>\n<h2>Using Local Services<\/h2>\n<p>A local service could also be used to &#8220;decorate&#8221; or &#8220;wrap&#8221; an existing global service, to layer some additional functionality on top of it, instead of completely replacing all its functionality:<\/p>\n<pre>var oldService = Service.Get&lt;ISomeService&gt;();\r\nvar newService = new SomeServiceDecorator(oldService);\r\nService.AddFor&lt;ISomeService&gt;(Clients.Everywhere, newService, registerer: this);\r\n\r\n...\r\n\r\nclass SomeServiceDecorator : ISomeService\r\n{\r\n    ISomeService decoratedService;\r\n    public SomeServiceDecorator(ISomeService decoratedService)\r\n        =&gt; this.decoratedService = decoratedService;\r\n\r\n    public void DoSomething()\r\n    {\r\n        Debug.Log(\"Doing something...\");\r\n        decoratedService.DoSomething();\r\n        Debug.Log(\"Did something.\");\r\n    }\r\n}<\/pre>\n<article id=\"post-78\" class=\"clearfix post-78 post type-post status-publish format-standard hentry category-features\">\n<div class=\"clearfix post-78 post type-post status-publish format-standard hentry category-features\" role=\"article\">\n<div class=\"post_content\">\n<h1>Reacting To Changing Services<\/h1>\n<p>If a new mod DLL is loaded at runtime, and that mod makes changes to existing services after some clients have already been initialized, those existing clients will not automatically get re-initialized with the new services.<\/p>\n<p>To do this you can subscribe to receive callbacks when a service that a client depends on changes to a different one using the <a href=\"https:\/\/docs.sisus.co\/init-args-reference\/class_sisus_1_1_init_1_1_service.html\">Service.AddInstanceChangedListener<\/a> method:<\/p>\n<\/div>\n<div class=\"post_content\">\n<pre>class Player : MonoBehaviour&lt;IInputManager&gt;\r\n{\r\n\u00a0 IInputManager inputManager;\r\n  protected override void Init(IInputManager inputManager) =&gt; this.inputManager = inputManager;\r\n\r\n  void OnEnable() =&gt; Service.AddInstanceChangedListener(OnInputManagerChanged);\r\n  void OnDisable() =&gt; Service.RemoveInstanceChangedListener(OnInputManagerChanged);\r\n  void OnInputManagerChanged(Clients clients, IInputManager oldInstance, IInputManager newInstance) =&gt; inputManager = newInstance;\r\n}<\/pre>\n<\/div>\n<\/div>\n<\/article>\n<p>Alternatively you can also use Service.AddChangedListener to execute a method with no parameters in reaction to a service changing:<\/p>\n<pre>class Player : MonoBehaviour&lt;A, B, C&gt;\r\n{\r\n  A a;\r\n  B b;\r\n  C c;\r\n\r\n  protected override void Init(A a, B b, C c)\r\n  {\r\n      this.a = a;\r\n      this.b = b;\r\n      this.c = c;\r\n  }\r\n\r\n  void OnEnable()\r\n  {\r\n     Service.AddChangedListener&lt;A&gt;(OnServiceChanged);\r\n     Service.AddChangedListener&lt;B&gt;(OnServiceChanged);\r\n     Service.AddChangedListener&lt;C&gt;(OnServiceChanged);\r\n  }\r\n\r\n  void OnDisable()\r\n  {\r\n     Service.RemoveChangedListener&lt;A&gt;(OnServiceChanged);\r\n     Service.RemoveChangedListener&lt;B&gt;(OnServiceChanged);\r\n     Service.RemoveChangedListener&lt;C&gt;(OnServiceChanged);\r\n  }\r\n\r\n  void OnServiceChanged() =&gt; Init(Context.MainThread | Context.Runtime);\r\n}<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>Dynamically Loaded Assemblies Init(args) supports creating global services registered using the [Service] attribute from assemblies that are loaded at runtime. If the assembly is loaded before Init(args) has finished initializing global services, then global services registered in the assembly using the [Service] attribute will get initialized as part of the initial service registration process. This ..<\/p>\n<div class=\"clear-fix\"><\/div>\n<p><a href=\"https:\/\/docs.sisus.co\/init-args\/advanced\/modding-support\/\" title=\"read more\">Read more<\/a><\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1113"}],"collection":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/comments?post=1113"}],"version-history":[{"count":8,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1113\/revisions"}],"predecessor-version":[{"id":1126,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/posts\/1113\/revisions\/1126"}],"wp:attachment":[{"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/media?parent=1113"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/categories?post=1113"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/docs.sisus.co\/init-args\/wp-json\/wp\/v2\/tags?post=1113"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}