<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Fusion on Wuyukwi's Notebook</title><link>https://wuyukwi.duckdns.org/tags/fusion/</link><description>Recent content in Fusion on Wuyukwi's Notebook</description><generator>Hugo</generator><language>ja</language><lastBuildDate>Wed, 04 Jun 2025 19:50:30 +0900</lastBuildDate><atom:link href="https://wuyukwi.duckdns.org/tags/fusion/index.xml" rel="self" type="application/rss+xml"/><item><title>💨 Fusionの[Networked]属性はどう動いている？IL変換と自動同期の仕組みを解剖する</title><link>https://wuyukwi.duckdns.org/posts/zenn-79685434adc2f5/</link><pubDate>Wed, 04 Jun 2025 19:50:30 +0900</pubDate><guid>https://wuyukwi.duckdns.org/posts/zenn-79685434adc2f5/</guid><description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;この記事は &lt;a href="https://zenn.dev/wuyukwi/articles/79685434adc2f5"&gt;Zenn&lt;/a&gt; に投稿した内容のアーカイブです。&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="はじめに"&gt;はじめに&lt;/h2&gt;
&lt;p&gt;Photon Fusionは、高性能・高柔軟性なネットワーク同期システムを提供する次世代ネットワークライブラリです。&lt;br&gt;
その中でも特に重要な役割を担っているのが、&lt;code&gt;[Networked]&lt;/code&gt; 属性です。&lt;/p&gt;
&lt;p&gt;この属性を使うことで、&lt;strong&gt;プレイヤーの位置やアニメーション状態、ゲーム内オブジェクトの変化&lt;/strong&gt; などを自動的に同期でき、煩雑な手動のデータ送受信処理を省くことができます。&lt;/p&gt;
&lt;p&gt;本シリーズでは、Fusionの内部同期処理を段階的に掘り下げて解説していきますが、今回は、&lt;code&gt;[Networked]&lt;/code&gt; 属性の裏側で何が起きているのか、どのようにして自動同期が実現されているのかを詳しく見ていきます。&lt;/p&gt;
&lt;h2 id="fusionにおけるnetworked属性の同期処理概要"&gt;Fusionにおける[Networked]属性の同期処理概要&lt;/h2&gt;
&lt;h3 id="networked-属性は"&gt;&lt;code&gt;[Networked]&lt;/code&gt; 属性は？&lt;/h3&gt;
&lt;p&gt;Fusionでは、&lt;code&gt;[Networked]&lt;/code&gt; 属性が付与されたプロパティは&lt;strong&gt;ネットワーク状態の同期対象&lt;/strong&gt; として扱われますが、ユーザーが手動で同期コードを書く必要はありません。&lt;br&gt;
この仕組みは、Unityが提供する &lt;strong&gt;ILPostProcessor API&lt;/strong&gt; を活用しており、C# で書かれたコードをビルド後に&lt;strong&gt;IL（中間言語）レベルで自動変換&lt;/strong&gt; しています。&lt;/p&gt;
&lt;p&gt;IL&lt;/p&gt;
&lt;p&gt;ILは、.NET における中間言語です。&lt;br&gt;
Unity では、C# で書いたスクリプトは必ずこの IL を経由してからネイティブコードに変換されます。&lt;/p&gt;
&lt;p&gt;具体的には、以下のような処理が行われます：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;NetworkedWeaved&lt;/code&gt; という属性を追加して、該当プロパティがネットワーク状態バッファに割り当てられることを明示&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;getter/setter が &lt;code&gt;NetworkBehaviour&lt;/code&gt; の内部バッファ（&lt;code&gt;StateBuffer&lt;/code&gt;）への&lt;strong&gt;メモリアクセスに差し替え&lt;/strong&gt; られる&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;実行時に &lt;code&gt;Spawned()&lt;/code&gt; されていない場合のアクセス制限も挿入される&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="変換前のcコード"&gt;変換前のC#コード：&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt; [Networked] private Vector2 _position { get; set; }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="il変換後ilspyで逆コンパイルしたコード"&gt;IL変換後（ILSpyで逆コンパイルしたコード）：&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;    [Networked]
    [NetworkedWeaved(0, 2)]
    private unsafe Vector2 _position
    {
        get
        {
            if (base.Ptr == null)
            {
                throw new InvalidOperationException(&amp;quot;Error when accessing PhotonCapybara._position. Networked properties can only be accessed when Spawned() has been called.&amp;quot;);
            }
            return (Vector2)base.Ptr[0];
        }
        set
        {
            if (base.Ptr == null)
            {
                throw new InvalidOperationException(&amp;quot;Error when accessing PhotonCapybara._position. Networked properties can only be accessed when Spawned() has been called.&amp;quot;);
            }
            Unsafe.Write(base.Ptr + 0, value);
        }
    }
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id="補足解説"&gt;補足解説：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;base.Ptr&lt;/code&gt; は &lt;code&gt;NetworkBehaviour&lt;/code&gt; に割り当てられた&lt;strong&gt;ネットワーク状態メモリの先頭ポインタ&lt;/strong&gt; です。&lt;/p&gt;</description></item></channel></rss>