Timelineでゲームスタート演出
スタート演出を組み込む
ゲーム開始時に、ステージを一望する、相手のキャラクタをアップで映すなどの演出を、TimelineとCinemachineで作りたいと思います。
これは何がいいのかというと、コードに縛られる事なく、デザイナーがマウスひとつで作ることができるというメリットがあります。
Virtual Cameraを設置し、Timelineで設定、最後使用されなくなったGameObjectを破棄してゲームを起動するというところまでを作ろうという試みです。
難易度としては、Unity使用して一年未満の学生でも出来るレベルです。
Timelineとは
UnityのTimelineは、シーケンシャルなイベントをビジュアル的に制御するための強力なツールです。これは、Unityエディタ内で動画のようなシーケンスを作成するために使われます。
まずは、UnityのTimelineの主な機能と利点をいくつか説明します。
-
アニメーションのシンクロナイゼーション:
Timelineを使用すると、アニメーション、サウンドトラック、その他のイベントを正確に同期させることができます。例えば、キャラクターが動くアニメーションとその動きに合わせた音楽や効果音をタイムライン上で調整できます。 -
直感的なインターフェース:
Timelineはドラッグアンドドロップのインターフェースを持っていて、非常に直感的です。アセットをタイムライン上に配置して、時間軸に沿って移動させることができます。 -
マルチトラック編集:
複数のトラックを使用して、異なるタイプのメディアやアニメーションを管理できます。例えば、一つのトラックにはキャラクターのアニメーション、別のトラックには背景音楽、さらに別のトラックには環境効果などを配置することが可能です。 -
プレビュー機能:
編集中にリアルタイムでシーケンスをプレビューすることができます。これにより、変更が即座に視覚化され、直感的なフィードバックを得ることができます。 -
拡張性:
Timelineはカスタマイズ可能で、プログラマーはC#スクリプトを使用して、タイムラインイベントを制御したり、カスタムトラックやクリップを作成することができます。 -
シネマティックコンテンツの作成:
シネマティックなカットシーンやプロモーションビデオなど、映画のようなコンテンツを作成するのに特に有効です。
Timelineを学ぶための最良の方法は、実際にUnityを開いて、いくつかの基本的なプロジェクトで実験を始めることです。Unityの公式ドキュメントやチュートリアルビデオを見ながら、基本的なタイムラインの作成から始めてみてください。これにより、タイムラインの使い方と、それがどのようにしてゲーム開発やインタラクティブメディアに利用できるのかが理解できるでしょう。
Cinemachineについて
CinemachineとUnityのTimelineを組み合わせることは非常に強力で、ゲーム開発やインタラクティブコンテンツ作成において多くのメリットがあります。
CinemachineはUnityでカメラワークを自動化し、動的かつ映画的なビデオ撮影を可能にするツールです。Timelineと組み合わせることで、さらに洗練されたビジュアル表現を簡単に実現できます。
以下は、この組み合わせの主な利点です。
-
自動カメラ制御:
Cinemachineはカメラの動きやフォーカスを自動で管理できます。Timelineと組み合わせることにより、特定のシーンやアクションに対してカメラを自動的に最適な位置や角度に調整できます。 -
複数のカメラアングル:
複数のCinemachine Virtual Cameraを設定し、Timelineを使ってそれらのカメラ間でスムーズに切り替えることができます。これにより、複雑なカメラワークを容易に実装し、映画のようなシーンを作成できます。 -
動的なカメラ追跡:
キャラクターやオブジェクトの動きに応じてカメラを追跡させることができます。Timelineを使用して特定のタイミングでカメラのビヘイビアやトラッキングの対象を変更することが可能です。 -
効果的なトランジション:
シーンやカメラの切り替えにおいて、シームレスで効果的なトランジションを実現できます。これは視覚的な物語性を強化し、ユーザーの没入感を高めるのに役立ちます。 -
リアルタイムのカメラ調整:
エディター内でリアルタイムにカメラ設定を試しながら調整できるため、開発中に即座にビジュアルフィードバックを得られます。
CinemachineとTimelineを一緒に使うことで、シネマティックなカットシーンの制作、インタラクティブなストーリーテリング、動的なイベントの演出など、より豊かでダイナミックなビジュアルエクスペリエンスを創出できます。これらのツールの組み合わせを活用することで、Unity内での表現の幅が大幅に広がります。
組み合わせると出来る事
UnityのTimeline内にCinemachineのシーケンスを組み込むことができ、これにより非常に動的で映画的なカメラワークをシーンに組み込むことが可能です。具体的には、Cinemachine Virtual CamerasをTimelineにトラックとして追加し、タイムライン上でこれらのカメラを制御することができます。この機能を使うことで、以下のようなことが実現可能です。
-
カメラのスイッチング:
複数のCinemachine Virtual Camerasを設定し、それぞれ異なるカメラアングルや動きを持たせることができます。Timeline上でこれらのカメラ間をシームレスに切り替えることにより、シーンにダイナミズムや視覚的な変化を与えることができます。 -
カメラモーション:
Cinemachineの機能を利用して、カメラがキャラクターを追跡する動きや、スムースなパン、ズームなどの動作を設計できます。これらのカメラモーションをTimeline上で調整し、シーケンスに合わせて最適なタイミングで発動させることができます。 -
カメラプロパティのキーフレーミング:
Timelineを使用して、特定の時間にカメラの特定のプロパティ(例えば焦点距離や露出など)を変更するキーフレームを設定できます。これにより、シーンに応じてカメラ設定を細かく調整することが可能です。 -
特定のタイミングでGameObjectをONにする:
SignalTrackを使用して、特定のタイミングでGameObjectをON(enabled)にするという機能を使いたいと思います。パーティクルの発動、GameObjectのインスタンスなど、簡単に使える機能で組み込む事が可能です
これらの機能を活用することで、ユーザーはインタラクティブなアプリケーションやゲーム内で、高度にカスタマイズされたビデオプロダクション品質のカメラワークを実現できます。特に、シネマティックなカットシーンの制作や、ゲーム内イベントの演出においてその力を発揮します。
使用するTrack
Cinemachine Track
Cinemachine TrackはUnityのTimeline内でCinemachine Virtual Camerasを活用するための機能です。これを使用すると、カメラのアクティベーション、ディアクティベーション、および異なるショット間のブレンドをタイムライン上で制御できます。具体的には、以下のステップで操作を行います:
-
Cinemachine Shot Clipsの追加:
Cinemachine TrackにCinemachine Shot Clipを追加して、特定のVirtual Cameraをタイムライン上でアクティブ化します。これにより、カメラの順序や持続時間を精密に管理でき、ショット間をカットまたはブレンドで繋げることが可能です。 -
カメラ遷移の管理:
二つのVirtual Cameras間でカットする場合、ショットクリップを隣り合わせに配置します。ブレンドする場合は、クリップを重ねます。これにより、ショット間のスムーズな遷移を実現できます。 -
複数のCinemachine Tracksの利用:
同じタイムライン内に複数のCinemachine Tracksを配置することができ、下に配置されたトラックが上にあるトラックより優先されます。これにより、一つのショットがアクティブな間に別のショットを開始し、映像表現の多様性を高めることができます。
この機能により、映画のようなシームレスなカメラワークとダイナミックなビジュアルストーリーテリングが可能になり、ユーザーの没入感を向上させることができます。
Signal Track
UnityのSignal TrackはTimeline内で特定のイベントやアクションをトリガーするために使われる非常に便利な機能です。このトラックを使用することで、タイムライン上の特定のタイミングでシグナルを発信し、そのシグナルに対応したリアクションをゲームオブジェクトやスクリプトが実行するように設定できます。以下に、Signal Trackの主な特徴と使用方法について説明します。
-
カスタムイベントのトリガー:
Signal Trackは、シーン内の特定のポイントでカスタムイベントをトリガーすることが可能です。これにより、アニメーション、サウンド、またはその他のゲーム内のイベントを精確にコントロールできます。 -
フレキシブルなイベントハンドリング:
シグナルは任意のスクリプトにリンクでき、シグナルを受け取ったスクリプトが特定の関数を呼び出すことができます。これにより、非常にダイナミックなインタラクションやシーンの変更がプログラム的に可能になります。 -
編集の容易さ:
Unityのエディターで直感的に操作が可能で、シグナルを発信するタイムラインのマーカーを簡単に追加、移動、削除できます。
使用方法
-
Signal Trackの追加:
Timelineに新しいSignal Trackを追加し、そのトラックにシグナルエミッターを配置します。 -
シグナルの設定:
シグナルエミッターには、トリガーするイベントに対応するアクションを定義します。このアクションは、特定のメソッドを呼び出すことで実行されるように設定することが一般的です。 -
リスナーの設定:
シグナルを受け取るオブジェクト(リスナー)には、受け取ったシグナルに応じて実行するスクリプトをアタッチします。リスナーはシグナルに応じて特定のメソッドを実行するように設計されます。 -
テストと調整:
シーンをプレイしてシグナルの発信と受信が期待通りに動作するかテストし、必要に応じて調整します。
Unityの公式ドキュメントやチュートリアルを参照すると、Signal Trackの設定や使用方法についてさらに詳細な情報を得ることができます。これにより、ゲームやアプリケーション内で複雑なイベントフローを管理しやすくなります。実際のプロジェクトでこの機能を使ってみることで、その強力さと便利さを実感できるでしょう。
準備
今回、TimelineとCinemachineを使用するので、手始めに準備をします。
以下の内容でセットアップをしてください。
Timelineの準備
UnityのTimelineを使う準備をするための手順は以下の通りです。Timelineを活用することで、アニメーション、オーディオ、およびその他のイベントをシンクロナイズして、シームレスなシーケンスを作成できます。
-
Unityエディタを開く:
まず、Unityエディタを開いて、作業中のプロジェクトをロードするか、新しいプロジェクトを作成します。 -
Timelineパッケージを確認:
Unity 2017以降のバージョンではTimelineはデフォルトで含まれていますが、確認のために「Window」→「Package Manager」を開き、「Timeline」がリストにあるか確認してください。もしリストになければ、Unity Registryからインストールが必要です。
-
Timelineを使うためのオブジェクトの準備:
Timelineを使用するには、まずターゲットとなるGameObjectにアタッチされるAnimatorコンポーネントやその他の必要なコンポーネントが設定されている必要があります。 -
Timelineウィンドウを開く:
「Window」→「Sequencing」→「Timeline」を選択してTimelineエディタを開きます。
-
Timelineを作成:
シーン内のGameObjectを選択し、「Create」をクリックして新しいTimelineアセットを作成します。これにより、選択したGameObjectに「Playable Director」コンポーネントが追加され、新しいTimelineアセットが関連付けられます。
-
トラックとクリップの追加:
Timelineエディタ内で右クリックし、「Add Track」から必要なトラックタイプ(例:アニメーショントラック、オーディオトラックなど)を選択します。トラックを追加したら、クリップを追加して具体的なコンテンツを設定します。 -
アニメーションとキーフレームの設定:
トラック内にクリップを配置し、必要に応じてアニメーションキーフレームを調整します。
-
プレビューと調整:
Timelineを再生してプレビューを見ながら、必要に応じて調整を行います。
これらの基本的なステップを踏むことで、UnityのTimeline機能を活用してプロジェクトにダイナミックなシーケンスやインタラクティブな要素を加えることができます。もっと詳しい情報や具体的な使い方については、Unityの公式ドキュメントやチュートリアルを参照すると良いでしょう。それぞれのプロジェクトのニーズに応じて、さらに複雑な機能やカスタマイズが必要になる場合もあります。
Cinemachineのインストール
CinemachineをUnityプロジェクトに導入するための手順は以下の通りです。UnityのPackage Managerを使用してCinemachineをインストールし、プロジェクトで使えるように設定するプロセスです。
-
Unityエディタを開く:
Unityを開き、プロジェクトを選択または新しいプロジェクトを作成します。 -
Package Managerを開く:
Unityエディタの上部にあるメニューバーから「Window」を選択し、「Package Manager」をクリックします。 -
Cinemachineを探す:
Package Managerが開いたら、「Packages: Unity Registry」を選択して、利用可能なUnity公式パッケージリストから「Cinemachine」を探します。
-
Cinemachineをインストール:
Cinemachineを見つけたら、それを選択し、「Install」ボタンをクリックします。これにより、Cinemachineがプロジェクトにインストールされます。 -
Cinemachineの使用開始:
Cinemachineがインストールされたら、Unityエディタの「GameObject」メニューを使用して、シーンにCinemachine Virtual CameraなどのCinemachineコンポーネントを追加し始めることができます。
実装
それでは、TimelineとCinemachineを使用して、Virtual Cameraの切り替えを行う手順を以下に説明します。
これは、ゲームのスタート演出で使用される典型的なカメラワークです。
Virtual Cameraの切り替えの実装
-
Virtual Camerasの設定:
- 最初に、シーンに必要なCinemachine Virtual Camerasを設置します。各カメラは異なる視点やアングルを持つように設定します。
- 最初に、シーンに必要なCinemachine Virtual Camerasを設置します。各カメラは異なる視点やアングルを持つように設定します。
-
Timelineの設定:
- Unityエディタの「Window」→「Sequencing」→「Timeline」を選択して、Timelineウィンドウを開きます。
- シーンにTimelineを追加するために、カメラ切り替えを制御したいGameObject(例えば、ゲームのスタートシーンを管理するコントローラー)に「Playable Director」をアタッチし、新しいTimelineアセットを作成します。
-
Cinemachine Trackの追加:
- Timelineに新しい「Cinemachine Track」を追加します。
-
Cinemachine Trackの設定:
- MainCamera(CinemachineBlain)を、追加したCinemachine Trackの参照欄にD&Dします。
- 作成したCinemachine Trackに対して、先に設定したVirtual Camerasをドラッグ&ドロップします。
-
Shot Clipsの設定:
- 各Virtual Cameraに対して「Cinemachine Shot Clip」を設定し、それぞれのカメラがアクティブになる時間を決定します。
- ショットクリップをタイムライン上で調整して、カメラが切り替わるタイミングを設定します。
-
プレビューと調整:
- Timelineを使ってシーンをプレビューし、カメラの切り替えがスムーズに行われるか確認します。
- 必要に応じて、各ショットクリップの長さや順序を調整して、理想的なカメラワークを実現します。
この手順により、シーン内でスムーズにカメラを切り替える基本的なシステムが完成します。
カメラブレンドを実装する
Cinemachineのカメラブレンドの機能を使っていきたいと思います。
これは、複数カメラを使いますが、クロスフェードと呼ばれるトランジションではなく、Virtual Camera間の座標をブレンドしてアニメーションするという機能になります。
挙動に関しては、座標以外は設定したコンポーネントに準じて動作します。
Cinemachine Shot Clip
の編集
1.並べたCinemachine Shot Clipが掴めるようになっています。
まずはTimeline上で動かしてみましょう。
Cinemachine Shot Clip
をクロスさせる
2.次に、隣同士にあるCinemachine Shot Clipを、めり込ませてみましょう。
クロスフェードしている状態が確認できると思います。
3.動作確認
再生ボタンを押してPlayしてみると、カメラ同士の座標に向かって画面が変わっているのがわかると思います。
この場合のクロスフェードは、画面を差し替えるような表現ではなく、先にも書いたvirtual Cameraの座標をブレンドするカメラ(座標の)ブレンドの機能による表現になります。
指定したGameObjectを起動する
UnityのTimeline内でSignal Trackを用いて複数のGameObjectのオン/オフ(アクティブ/非アクティブの状態変更)を制御する方法は、シーケンス制御において非常に便利です。
通常はActibation Trackで実装可能ですが、後々の予習も兼ねて、SignalTrackで実装したいと思います。
この機能を利用することで、ゲームのシーン内でのイベント発生時に特定のオブジェクトを動的に表示または非表示にすることができます。以下にその実装手順を詳しく説明します。
1. Signal Assetの作成
まず、Unityエディタで新しいSignal Asset
を作成します。これは、特定のアクション(この場合はGameObjectのアクティブ/非アクティブ化)をトリガーするためのものです。
- Unityエディタのメニューバーから「Assets」→「Create」→「Signal」を選択し、新しいシグナルを作成します。
2. Timelineの設定
次に、制御したいシーケンスが含まれるGameObjectにPlayable Director
とTimelineアセットを設定します。
- シーン内のGameObjectを選択し、「Add Component」→「Playable Director」を追加します。
- 「Playable Director」のインスペクター画面で「Create」ボタンを使用して新しいTimelineアセットを作成します。
3. Signal Trackの追加
作成したTimelineアセットにSignal Trackを追加します。
- Timelineウィンドウで右クリックし、「Add Signal Track」を選択します。
- 追加したTrackに先ほど作成したSignal Assetをドラッグアンドドロップします。
4. GameObjectのON/OFFを制御するスクリプトの作成
シグナルを受け取った際に実行されるスクリプトを作成します。このスクリプトは、GameObjectのアクティブ状態を切り替える機能を持ちます。
using UnityEngine;
public class ToggleGameObject : MonoBehaviour
{
public void ActivateGameObject()
{
gameObject.SetActive(true);
}
public void DeactivateGameObject()
{
gameObject.SetActive(false);
}
}
5. Signal Receiverの設定
Signal Trackから送信されたシグナルを受け取るために、対象のGameObjectにSignal Receiver
コンポーネントを追加し、シグナルとスクリプト内のメソッドをリンクします。
- GameObjectに
Signal Receiver
コンポーネントを追加します。 -
Signal Receiver
のインスペクター画面で「Add Reaction」をクリックし、シグナルを選択後、ToggleGameObject
スクリプトのActivateGameObject
やDeactivateGameObject
メソッドを割り当てます。
6. シーンでのテスト
設定が完了したら、Timelineを再生して、シグナルに応じてGameObjectのアクティブ/非アクティブ状態が適切に切り替わることを確認します。
この方法により、シーン内でのイベントに応じた動的なオブジェクト管理が可能になり、よりリッチなユーザー体験を提供できます。さらに詳細や他の用途については、Unityの公式ドキュメントやフォーラムで情報を得ることができます。
Signal Trackを使ったカラーフェード(暗転)の実装
カラーフェードは手順が複雑なので、ひとつずつ確認しながら進めましょう。
ここでは、uGUIのImageを用いて、SignalTrackのタイミングで画面全体を暗転させます。
FadeTransition
クラスの概要
1.FadeTransition
クラスは、UnityでUIの透明度をアニメーション化し、シーン間の遷移やイベントで暗転と明転を制御するために使用されます。
このクラスは通常、Image
コンポーネントを使って画面全体を覆うUI要素にアタッチされ、スクリプトによって透明度が制御されます。主な機能は、フェードイン(暗転)とフェードアウト(明転)のアニメーションです。
using UnityEngine;
using UnityEngine.UI;
public class FadeTransition : MonoBehaviour
{
public Image fadeImage;
public float fadeDuration = 1.0f;
public void FadeIn()
{
StartCoroutine(Fade(0, 1)); // 透明から不透明へ
}
public void FadeOut()
{
StartCoroutine(Fade(1, 0)); // 不透明から透明へ
}
private IEnumerator Fade(float startAlpha, float endAlpha)
{
float elapsedTime = 0.0f;
while (elapsedTime < fadeDuration)
{
elapsedTime += Time.deltaTime;
float newAlpha = Mathf.Lerp(startAlpha, endAlpha, elapsedTime / fadeDuration);
fadeImage.color = new Color(fadeImage.color.r, fadeImage.color.g, fadeImage.color.b, newAlpha);
yield return null;
}
}
}
FadeTransition
の使用方法
2.-
UIの準備:
-
Canvas
内にImage
を作成し、スクリーン全体を覆うように設定。 -
Image
のカラーを黒に設定し、初期の透明度を0にします。
-
-
スクリプトのアタッチ:
- 作成したUI要素に
FadeTransition
スクリプトをアタッチします。
- 作成したUI要素に
-
スクリプトの設定:
-
FadeTransition
スクリプト内で、Image
コンポーネントの参照とフェードの時間を設定します。
-
FadeTransition
の実装
3.Signal Trackでの-
Signal Assetの作成:
- Unityのエディタで新しい
Signal Asset
を作成し、それを使用してFadeIn
およびFadeOut
メソッドをトリガーするように設定します。
- Unityのエディタで新しい
-
Timelineの設定:
- 必要なGameObjectに
Playable Director
をアタッチし、新しいTimelineアセットを作成します。 - Timelineに
Signal Track
を追加し、作成したSignal Asset
を適切なタイミングで配置します。
- 必要なGameObjectに
-
リスナーの設定:
-
FadeTransition
スクリプトがアタッチされているGameObjectにSignal Receiver
コンポーネントを追加します。 -
Signal Receiver
で、受信したSignalに応じてFadeIn
とFadeOut
メソッドを実行するように設定します。
-
-
テストと調整:
- Timelineを再生して、
FadeIn
とFadeOut
が正確にトリガーされるか確認し、必要に応じてタイミングを調整します。
- Timelineを再生して、
このプロセスにより、FadeTransition
クラスを効果的に使用して、ゲームやアプリケーション内で視覚的なトランジションをスムーズに制御することができます。各ステップを適切に設定することで、ユーザー体験を向上させる洗練された演出が可能になります。
不要になったGameObjectを削除
UnityでTimelineとCinemachineを使い、特定のVirtual Cameraからメインカメラへの描画を受け渡し、使用していたVirtual Cameraを削除する方法を説明します。
このワークフローは、演出が完了した後にシームレスにゲームプレイに移行するために役立ちます。
1. Virtual Cameraの設定
まず、シーンに必要なCinemachine Virtual Camerasを設置します。これらのカメラが初期のカットシーンやイントロで使用されることを想定します。
2. TimelineとCinemachine Trackの設定
-
Timelineの作成: シーン内でカメラが切り替わる要素に
Playable Director
を追加し、新しいTimelineアセットを作成します。 -
Cinemachine Trackの追加: Timelineに
Cinemachine Track
を追加し、このトラックに序盤に使用するCinemachine Virtual Camerasを配置します。
3. カメラの切り替えと削除
- タイムラインの最後で、メインカメラ(通常のUnity Camera)をアクティブにするアクションを設定します。これには、Cinemachineの
Cinemachine Brain
がアタッチされたメインカメラをアクティブにすることで、CinemachineのVirtual Cameraから通常のカメラへの切り替えを行います。 - Virtual CamerasをTimelineの終了時に非アクティブ化または削除するには、スクリプトを使用して自動的に実行することができます。
4.スクリプトでのカメラの削除
以下のスクリプトは、タイムラインが終了した後に特定のVirtual Cameraを削除します。
using UnityEngine;
using UnityEngine.Playables;
using Cinemachine;
public class CameraSwitcher : MonoBehaviour
{
public PlayableDirector director;
public GameObject virtualCamera;
void Start()
{
director.stopped += OnPlayableDirectorStopped;
}
void OnPlayableDirectorStopped(PlayableDirector aDirector)
{
if (director == aDirector)
{
CinemachineBrain brain = Camera.main.GetComponent<CinemachineBrain>();
if (brain != null)
{
brain.enabled = false; // Cinemachineを無効化
}
Destroy(virtualCamera); // Virtual Cameraを削除
}
}
void OnDestroy()
{
director.stopped -= OnPlayableDirectorStopped;
}
}
このスクリプトは、PlayableDirector
のstopped
イベントにフックして、タイムラインが完了した時にVirtual Cameraを削除します。メインカメラにCinemachineBrain
コンポーネントがアタッチされている場合は、それを無効にすることで、Cinemachineの制御から通常のカメラ操作に戻すことができます。
5.テストと確認
Unityエディタでシーンをプレイし、カメラの切り替えとVirtual Cameraの削除が期待通りに動作するか確認します。動作がスムーズであることを確認し、必要に応じてタイムラインのキーフレームやスクリプトのパラメータを調整します。
これで、TimelineとCinemachineを使用して、シーン内でのカメラのスムーズな切り替えと後処理が行えるようになります。
GameLoopに組み込む
スタート演出としてTimelineを使う際に、再生が終わってからGameLoopをスタートさせるという実装が求められると思います。
PlayableDirectorのstoppedにイベント登録をし、再生が終わったら呼ばれるような仕組みを作りました。
using UnityEngine;
using UnityEngine.Playables;
public class GameManager : MonoBehaviour
{
public PlayableDirector director;
public GameObject DestroyVirtualCamera;
void Start()
{
director.stopped += OnDirectorStopped; // Timelineが終了したらイベントを追加
director.Play(); // Timelineを再生
}
private void OnDirectorStopped(PlayableDirector aDirector)
{
if (director == aDirector)
{
SetCameraTargets(); // Timelineの演出が終了したらカメラターゲットを設定
}
}
void OnDestroy()
{
director.stopped -= OnDirectorStopped; // イベントハンドラを削除
}
void SetCameraTargets()
{
Destroy(DestroyVirtualCamera);
DestroyVirtualCamera = null;
}
}
ここでは、演出用のVirtualCameraを削除するところまで実装しています。
Discussion