文档

Unity Engine

Unity Engine

Initialization paths for native iOS plug-ins

Learn about the different initialization paths available for native iOS plug-ins.
阅读时间5 分钟最后更新于 5 天前

Learn about the different initialization paths available for native iOS plug-ins.
Unity and Apple platforms provide multiple mechanisms for initializing a native plug-in. The best approach depends on whether you need to initialize the plug-in early (at application startup) or lazily (on its first use). You can perform initialization from managed C# code, native code, or within Unity's generated Xcode project code.

Managed C# initialization paths

  • RuntimeInitializeOnLoadMethodAttribute: Automatically runs a method at different points in the application lifecycle, such as
    BeforeSplashScreen
    or
    AfterSceneLoad
    . Use
    RuntimeInitializeOnLoadMethodAttribute
    to initialize your plug-in’s C# API and make the first call into native code. For more information, refer to RuntimeInitializeOnLoadMethodAttribute.
  • SceneManager Callbacks: Use
    SceneManager.sceneLoaded
    and
    SceneManager.sceneUnloaded
    for lazy initialization tied to specific scene content.
  • MonoBehaviour Lifecycle: Use standard
    MonoBehaviour
    methods like
    Awake
    ,
    OnEnable
    , and
    Start
    for initialization tied to a
    GameObject
    's lifecycle. Refer to Event function execution order for more information.

Native initialization paths

The native initialization paths and their timing differ depending on your plug-in's language. Swift follows a different path than C++ or Objective-C. The following sections outline the various initialization paths available for native code.

C++ and Objective-C++ initialization paths

You can use a global C++ object's constructor to run code before
main()
and its destructor to run code after
main()
completes. A global C++ object constructor is invoked automatically when the application binary loads and its destructor is invoked when the binary unloads.

Characteristics:

  • Timing: Before
    main()
    .
  • Execution order: Non-deterministic.
  • Unity state: Unity isn't initialized.
  • Execution: Triggered automatically on binary load and unload.
  • Compatibility: Works with
    .c
    ,
    .cpp
    ,
    .m
    ,
    .mm
    , and
    .a
    files.
  • Dependency: Behavior depends on
    UnityFramework.framework
    linking (static versus dynamic).

Code example

// Global object — constructor runs before main(), destructor after main()struct GlobalFoo { GlobalFoo() { std::cout << "GlobalFoo constructor running!\n"; } ~GlobalFoo() { std::cout << "GlobalFoo destructor running!\n"; }};GlobalFoo g_foo;

Clang and GCC initialization paths

This method uses the
__attribute__((constructor))
and
__attribute__((destructor))
attributes to register functions that run when a library loads and unloads.

Characteristics:

  • Timing: Runs before
    main()
    .
  • Execution order: Non-deterministic.
  • Unity state: Unity isn't initialized.
  • Execution: Triggered automatically on binary load and unload.
  • Compatibility: Works with
    .c
    ,
    .cpp
    ,
    .m
    , and
    .mm
    files.
  • Dependency: Behavior depends on
    UnityFramework.framework
    linking.

Example

// runs before main__attribute__((constructor))static void MyInit() { printf("Init called\n");}// after program exit/shared library unload__attribute__((destructor))static void MyDone() { printf("Done called\n");}

Objective-C

These methods are for use in
.m
and
.mm
files.

+load

The
+load
method is executed by the Objective-C runtime when a class loads, which occurs before
main()
and before C++ global constructors.
Characteristics:
  • Timing: Early. Runs before
    main()
    .
  • Execution order: Non-deterministic.
  • Unity state: Unity isn't initialized.
  • Execution: Runs automatically for every class and category that implements it, even if never referenced. Can't be disabled.
  • Compatibility: Works with
    .m
    and
    .mm
    files.
  • Dependency: Behavior depends on
    UnityFramework.framework
    linking.
Example
// Runs as soon as the Obj-C runtime loads the class (before main()).// Categories get +load before classes@implementation MyClass+ (void)load { NSLog(@"+load called");}@end

+initialize

The
+initialize
method is invoked lazily, just before the first message is sent to the class. It's ideal for on-demand initialization.

Characteristics:

  • Timing: Runs on the first message sent to the class.
  • Execution order: Deterministic.
  • Unity state: Unity might be initialized, depending on when the first message is sent.
  • Execution: Lazy. Doesn't run if the class is never used, thread-safe, and runs exactly once per class.
  • Compatibility: Works with
    .m
    and
    .mm
    files.

Example:

// Called on first message dispatch to the class@implementation MyClass+ (void)initialize { NSLog(@"+initialize called");}@end

Swift

In Swift, global variables and objects are lazily initialized. This means the
NativeManager
constructor runs only when the
manager
object is accessed for the first time. The initial access occurs when calling
GetValueFromManager
.

Characteristics:

  • Timing: On first use.
  • Execution order: Deterministic.
  • Execution: Lazy.

Example:

class NativeManager {init() { rint("NativeManager initialized") }func value() -> Int { return 42 }}// global objectlet manager = NativeManager()@_cdecl("GetValueFromManager")public func GetValueFromManager() -> Int { return manager.value() }

Plug-in callbacks

Set the name of a C function,
void f(void)
, in the plug-ins
Inspector

?

window. Unity calls the function at a fixed point of its startup sequence. Unity provides two callbacks:
  • Runtime will initialize: The earliest Unity setup point. Use it to subscribe to notifications, so the plug-in receives the first notifications.
  • Runtime did initialize: After the Unity Engine initializes, before graphics initialize and the first scene loads. Use it to register a low-level native plug-in with
    UnityRegisterPlugin
    or
    UnityRegisterAudioPlugin
    .

Characteristics:

  • Timing: At the earliest Unity setup point, and after the Unity Engine initializes.
  • Execution order: Deterministic. Alphabetical, by function name.
  • Unity state: No scene has loaded and no scripts have run.
  • Execution: Once per process, on the main thread.
  • Compatibility: Works with
    .c
    ,
    .cpp
    ,
    .m
    ,
    .mm
    ,
    .swift
    , and
    .a
    files, in both Xcode project types.

Example:

// MyPlugin.mm: called at the earliest Unity setup pointextern "C" void MyPlugin_RuntimeWillInitialize(void){ NSLog(@"MyPlugin_RuntimeWillInitialize called");}

Change App Controller Class

You can modify the Unity-provided
AppController
class to customize your application's startup behavior. The
IMPL_APP_CONTROLLER_SUBCLASS
macro achieves this by replacing Unity’s default
AppController
class with your own custom Objective-C subclass.
IMPL_APP_CONTROLLER_SUBCLASS
works as follows:
  1. Declare an Objective-C category on your subclass.
  2. Use
    +load
    (executed before
    main()
    ) to override the global
    AppControllerClassName
    symbol that Unity uses to decide which
    UIApplicationDelegate
    or
    AppController
    class to instantiate.
Use
IMPL_APP_CONTROLLER_SUBCLASS
if you need early lifecycle hooks, such as:
  • preStartUnity
  • startUnity
  • initUnityWithScene
  • application:didFinishLaunchingWithOptions
  • applicationDidEnterBackground
  • applicationWillTerminate
  • App-level system integrations that must run before Unity initializes.

Characteristics:

  • Dependency: Only compatible with an Objective-C project type.
  • Compatibility: Works with
    .m
    and
    .mm
    files.

Code example:

// MyAppController.mm#import "UnityAppController.h"// Custom AppController@interface MyAppController : UnityAppController@end@implementation MyAppController (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { NSLog(@"MyAppController didFinishLaunching"); return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end// Register this class as Unity's AppControllerIMPL_APP_CONTROLLER_SUBCLASS(MyAppController)

Additional resources