LoginSignup
0
0

【Unity】Swift のネイティブプラグインからのコールバックのスレッド

Last updated at Posted at 2023-12-19

本記事について

この記事は CoreBluetoothForUnity Advent Calendar 2023 の20日目の記事です。

ネイティブプラグインからのコールバックは SynchronizationContext.Postを使って処理を遅延実行させるのがおすすめという話をします。

環境

  • CoreBluetoothForUnity 0.4.6

Swift のネイティブプラグインはどのスレッドで呼ばれるのか

Swift のメインスレッドから呼ばれるコールバックは Unity のメインスレッドで実行されていました。

調べ方.cs
var context = SynchronizationContext.Current;
bool isUnityMainThread = context != null;
UnityEngine.Debug.Log($"MainThreadId: {System.Threading.Thread.CurrentThread.ManagedThreadId}");
// => 1
UnityEngine.Debug.Log($"isUnityMainThread: {isUnityMainThread}");
// => true

Swift がメインスレッド以外から読んだ時にどうなるかは調べていません!
メインスレッドで呼ばれるから問題ないというわけではありません。

コールバックの処理をそのまま実行することの問題

エラーが投げられると Unity がクラッシュします。

クラッシュする理由は把握できていません。

対応

コールバックの処理をそのまま実行するのではなく、遅延実行させることでクラッシュを回避できます。

CBCentralManager

CBCentralManager.cs
    public class CBCentralManager : CBManager, INativeCentralManagerDelegate, IDisposable
    {
...
        /// <summary>
        /// ICBCentralManagerDelegate callbacks will be called in this context.
        /// </summary>
        public SynchronizationContext CallbackContext { get; set; }
...
        public CBCentralManager(ICBCentralManagerDelegate centralDelegate = null, CBCentralManagerInitOptions options = null)
        {
            ...
            CallbackContext = SynchronizationContext.Current;
        }
...

        // コールバックで呼ばれるメソッド
        void INativeCentralManagerDelegate.DidConnect(string peripheralId)
        {
            CallbackContext.Post(_ =>
            {
                if (_disposed) return;
                // 処理
            }, null);
        }

本対応の問題点

メインスレッドから SynchronizationContext.Post で同じくメインスレッドで実行するように指定すると、
実行が1フレーム遅れます。

CoreBluetoothForUnity ではこの1フレームの遅れは許容しました。

参考

おわりに

開発終盤まで何度もクラッシュしてたけれど、これで回避できましたという内容でした!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0