---
lang: ja
path: user-guide/unity-sdk/quickstart-windows
labels: ユーザーガイド/Unity SDK/クイックスタート(Windows)
metaTitle: クイックスタート(Windows) ｜ Unity SDK ｜ ユーザーガイド ｜ SkyWay（スカイウェイ）
---

# 🚀 クイックスタート

SkyWay のメディア通信を体験できるシンプルなサンプルアプリケーションを作成します。

ここでは、デバイスのマイク音源を SFU サーバーに送信し、それを自分が受信して音声を再生するというアプリケーションを作ります。

## 開発環境
- Unity: 6000.3.6f1
- Windows 10以降(x64)

## アプリケーション ID とシークレットキーを取得する

※SkyWay への登録がまだの方は[こちら](https://console.skyway.ntt.com/login/)から

SkyWay コンソールへログインし、以下の 3 つを行います。
1. 「アプリケーションを作成」ボタンを押す
![Peer](/media/posts/docs/unity-sdk/MakeApplication.png)
2. アプリケーション名を入力して作成ボタンを押す
3. アプリケーション一覧からアプリケーション ID とシークレットキーをコピーする（後の手順で利用するため、控えておいてください）。

## SkyWay Auth Token を作成する

SkyWay Auth Token とは、SkyWay を利用するための JWT 形式のトークンです。

トークンごとに権限を細かく設定することができ、例えば Room ごとの入室を特定ユーザーに制限する、といったことができます。

SkyWay Auth Token はサーバーサイドでの生成になるので、Unity SDK にはトークンの生成機能はございません。ここでは JavaScript SDK で配布している Token ライブラリを利用し、サーバーから認可された後トークンを取得してきたとしましょう。

npm がインストールされた環境でライブラリをインストールします。

```shell
$ mkdir skyway_token && cd skyway_token
$ npm i @skyway-sdk/token
```

次に `token.js` を作成します。

```shell
$ touch token.js
```

ファイルを開き以下のコードをペーストします。

先ほど作成したアプリケーション ID とシークレットキーをスコープの `app.id` と `encode` メソッドの引数にペーストしてください。

```js
const token = new SkyWayAuthToken({
  jti: uuidV4(),
  iat: nowInSec(),
  exp: nowInSec() + 60 * 60 * 24,
  version: 3,
  scope: {
    appId: "ここにアプリケーションIDをペーストしてください",
    rooms: [
      {
        name: "*",
        methods: ["create", "close", "updateMetadata"],
        member: {
          name: "*",
          methods: ["publish", "subscribe", "updateMetadata"],
        },
      },
    ],
  },
}).encode("ここにシークレットキーをペーストしてください");
console.log(token);
```

node で `token.js` を実行すると SkyWay Auth Token が生成されます。このトークンは後程使うのでコピーしてください。

```shell
// こちらの出力結果はサンプルのため、コピーして用いないようにしてください。
$ node token.js
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIxOTA1MzU5Yi0xOGY3LTRhOWMtYmU4Zi1kMTgxMTQ0OTY1MjMiLCJpYXQiOjE2NzQxOTg3MDQsImV4cCI6MTY3NDI4NTEwNCwic2NvcGUiOnsiYXBwIjp7ImlkIjoi44GT44GT44Gr44Ki44OX44Oq44Kx44O844K344On44OzSUTjgpLjg5rjg7zjgrnjg4jjgZfjgabjgY_jgaDjgZXjgYQiLCJ0dXJuIjp0cnVlLCJhY3Rpb25zIjpbInJlYWQiXSwiY2hhbm5lbHMiOlt7ImlkIjoiKiIsIm5hbWUiOiIqIiwiYWN0aW9ucyI6WyJ3cml0ZSJdLCJtZW1iZXJzIjpbeyJpZCI6IioiLCJuYW1lIjoiKiIsImFjdGlvbnMiOlsid3JpdGUiXSwicHVibGljYXRpb24iOnsiYWN0aW9ucyI6WyJ3cml0ZSJdfSwic3Vic2NyaXB0aW9uIjp7ImFjdGlvbnMiOlsid3JpdGUiXX19XSwic2Z1Qm90cyI6W3siYWN0aW9ucyI6WyJ3cml0ZSJdLCJmb3J3YXJkaW5ncyI6W3siYWN0aW9ucyI6WyJ3cml0ZSJdfV19XX1dfX19.qmLpoOjou0S5JwxAiaBvH0KaGzZqN4-0t1xq708_b3M
```
なお、上記の例ではトークンの有効期限は生成から1日間です。

## UnityProjectを作成する

新規で UnityProject を作成してください。

## 依存ライブラリをインストールする
1. 上部ツールバーの `Window` から `Package Manager` を開きます。
2. `+` ボタンをクリックし、`Add package from git URL` をクリックします。
3. 以下の[UniTask](https://github.com/Cysharp/UniTask)の URL を入力します。
  `https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.4.1`
4. `Add` をクリックします。

![Install UniTask](/media/posts/docs/unity-sdk/InstallUniTask.png)

以上で、依存ライブラリの設定は完了です。

## unitypackageをダウンロードする
1. [SkyWay Unity SDK](https://github.com/skyway/unity-sdk/releases)にアクセスします。
2. `SkyWayRoom.unitypackage` をダウンロードします。

以上でダウンロードが完了します。

## プロジェクトにSkyWay Unity SDKをインポートする
1. プロジェクトの `Assets` をクリックします。
2. ポップアップメニューから `import package` をクリックし、`Custom Package` をクリックします。
3. ダウンロードした `SkyWayRoom.unitypackage` を選択し、`Import` をクリックします。

以上でインポートは完了です。

## Graphics APIの設定をする
> 注意: Graphics APIの設定はUnity6以降でのみ必要となります。

1. 上部ツールバーの`File`->`Build Settings`を開きます。
2. `Player Settings`を開きます。
3. `Player`を選択し、`Other Settings`を開きます。
4. `The Others`を開き、`Rendering`セクションへ移動します。
5. `Auto Graphics API for Windows`のチェックを外し、`Direct3D12`を削除します。
6. エディタの再起動を要求されるので、再起動します。
もう一度同じように開き、`Graphics API for Windows`が`Direct3D11`のみになっていればOKです。

![Graphics API](/media/posts/docs/unity-sdk/GraphicsAPISetting.png)

## オブジェクトを配置する
### 音声出力用のオブジェクトの配置
受信した音声を再生する Audio Source を配置します。
1. Unity Scene ペインで右クリックをしてポップアップメニューを開き、`Audio`->`Audio Source` を選択します。

## Scriptをアタッチする
1. Scene ペインから Main Camera を選択した状態で、Inspector の最下層の `Add Component` をクリックします。
2. `New scripts` をクリックし、任意の名前を入力します。
3. `Create and Add` をクリックすると、Script が生成されます。
4. `Assets` フォルダで、ポップアップメニューを開き、`Create`->`Assembly Definition Reference` を選択します。
5. Inspector の `Assembly Definition` に `SkyWayRoom` を選択します。

![Assembly Definition](/media/posts/docs/unity-sdk/AssemblyDefinition.png)

## 必要なメンバー変数の宣言とオブジェクトのアタッチを行う
`using Com.Ntt.SkyWay.Core` と `using Com.Ntt.SkyWay.Room` で SkyWay をインポートし、前節で作成した Script に必要なメンバー変数を宣言します。

```csharp
using UnityEngine;
using UnityEngine.UI;
using Com.Ntt.SkyWay.Core;
using Com.Ntt.SkyWay.Room;

class SampleScript : MonoBehaviour
{
    // 受信した音声を再生するAudio Source
    public AudioSource remoteOutputAudioSource;

   // 以下略
```

次に Unity の Scene に戻り、Main Camera を選択します。

Inspector 最下層の Script コンポーネントに移動し、作成した AudioSource を `remoteOutputAudioSource` にアタッチします。

![attachObject](/media/posts/docs/unity-sdk/AttachObject.png)

## SkyWayの利用を開始する
ここでは、簡易的に `Start` に SkyWay のロジックを記述していきます。

`SWContext.Setup(SWContextOptions options, Action<string>? onErrorHandler)` で SkyWay のセットアップを行います。先ほど生成した JWT を引数に入れてください。
このメソッドを `await` するため、 `Start()` メソッドを `async` にしてください。

```csharp
async void Start()
{
    var authToken = "トークンを入力";

    // SkyWayのセットアップ
    await SWContext.Setup(this, authToken);
}
```

## Roomを作成する
SkyWay のセットアップが完了したら Room を作成します。
`SWSFURoom.Create(string? name = null, string? metadata = null)` で Room を作成できます。

```csharp
var sfuRoom = await SWSFURoom.Create();
```

## Roomへ参加する
`SWSFURoom.Join(SWRoomMemberOptions? memberInit)` でルームに参加し、メンバーを作成します。

```csharp
var memberInit = new SWRoomMemberOptions
{
    name = "Alice" // Memberに名前をつけることができます。
};
var localMember = await sfuRoom.Join(memberInit);
```

## 音声を送受信する
### マイク音源のAudioStreamの作成とRoomへのPublish
マイクを音声入力として Stream を作成します。

Publish をするための LocalStream を作成するためには、Source が必要です。

`SWAudioSource` のインスタンスを作成し、`CreateStream()` で LocalStream を作成します。

`LocalSFUMember.Publish(SWLocalStream localStream, SWRoomPublicationOptions? options)` で Room に Publish します。

```csharp
// AudioStreamの作成
var audioSource = new SWAudioSource();
var localAudiostream = audioSource.CreateStream();

// audioをPublishします
var audioPublication = await localMember.Publish(localAudiostream, null);
```

### AudioStreamのSubscribe
`LocalSFUMember.Subscribe(SWRoomPublication publication, SWRoomSubscriptionOptions? options = null)` を実行し、Subscription を受け取ります。
その後、Subscription から `SWRemoteAudioStream` を入手し、出力用の Audio Source と紐づけます。

```csharp
// audioをSubscribeします
var audioSubscription = await localMember.Subscribe(audioPublication);

// 受信した音声をAudio Sourceから出力します
var remoteAudioStream = audioSubscription.Stream as SWRemoteAudioStream;
remoteAudioStream.SetAudioSource(remoteOutputAudioSource);
```

## 映像を送受信する
### テクスチャソースのVideoStreamの作成とRoomへのPublish
`SWVideoSource.CreateRenderTexture`で RenderTexture を作成し、プレビュー用の RawImage にアタッチします。

以降は AudioStream と同様に、`CreateStream`で stream を作成し、`LocalSFUMember.Publish(SWLocalStream localStream, SWRoomPublicationOptions? options)`で Room に Publish します。

```csharp
// RenderTextureの作成
var render = SWVideoSource.CreateRenderTexture(camera.pixelWidth, camera.pixelHeight);
RenderTexture.active = render;
camera.targetTexture = render;
localRenderingImage.texture = render;

// VideoStreamの作成
var videoSource = new SWVideoSource(render);
var localVideoStream = videoSource.CreateStream();

// videoをPublishします
var videoPublication = await localMember.Publish(localVideoStream, null);
```

### VideoStreamのSubscribe
`LocalSFUMember.Subscribe(SWRoomPublication publication, SWRoomSubscriptionOptions? options = null)`を実行し、Subscription を受け取ります。
その後、Subscriptionから `SWRemoteAudioStream` を入手し、表示用の Raw Image と紐づけます。

```csharp
// videoをSubscribeします
var videoSubscription = await localMember.Subscribe(videoPublication);

var remoteVideoStream = videoSubscription.Stream as SWRemoteVideoStream;
remoteVideoStream.onTextureHandler = texture =>
{
    // 受信した映像テクスチャをRaw Imageに描画します
    remoteRenderingImage.texture = texture;
};
```

実行し、受信した音声がデバイスのスピーカーから出力され、送信する映像と受信した映像がRaw Imageに表示されれば完成です。
![](/media/posts/docs/unity-sdk/Complete.png)

## QuickStartの完成コード

```csharp
using UnityEngine;
using UnityEngine.UI;
using Com.Ntt.SkyWay.Core;
using Com.Ntt.SkyWay.Room;

public class SampleScript : MonoBehaviour
{
    // 受信した音声を再生するAudio Source
    public AudioSource remoteOutputAudioSource;
    // 送信したいカメラオブジェクト
    public Camera camera;
    // カメラ映像をプレビューするためのテクスチャ
    public RawImage localRenderingImage;
    // 受信した映像を反映するRaw Image
    public RawImage remoteRenderingImage;

    async void Start()
    {
        var authToken = "トークンを入力してください。";

        // SkyWayのセットアップ
        await SWContext.Setup(authToken);

        var sfuRoom = await SWSFURoom.Create();

        var memberInit = new SWRoomMemberOptions
        {
            name = "Alice" // Memberに名前をつけることができます。
        };
        var localMember = await sfuRoom.Join(memberInit);

        // AudioStreamの作成
        var audioSource = new SWAudioSource();
        var localAudiostream = audioSource.CreateStream();

        // audioをPublishします
        var audioPublication = await localMember.Publish(localAudiostream, null);

        // audioをSubscribeします
        var audioSubscription = await localMember.Subscribe(audioPublication);

        // 受信した音声をAudio Sourceから出力します
        var remoteAudioStream = audioSubscription.Stream as SWRemoteAudioStream;
        remoteAudioStream.SetAudioSource(remoteOutputAudioSource);

        // RenderTextureの作成
        var render = SWVideoSource.CreateRenderTexture(camera.pixelWidth, camera.pixelHeight);
        RenderTexture.active = render;
        camera.targetTexture = render;
        localRenderingImage.texture = render;

        // VideoStreamの作成
        var videoSource = new SWVideoSource(render);
        var localVideoStream = videoSource.CreateStream();

        // videoをPublishします
        var videoPublication = await localMember.Publish(localVideoStream, null);

        // videoをSubscribeします
        var videoSubscription = await localMember.Subscribe(videoPublication);

        var remoteVideoStream = videoSubscription.Stream as SWRemoteVideoStream;
        remoteVideoStream.onTextureHandler = texture =>
        {
            // 受信した映像テクスチャを反映します
            remoteRenderingImage.texture = texture;
        };
    }
}
```
