見出し画像

Turn Based Strategy Framework 公式ドキュメントを日本語にしてみる

※このTurn Based Strategy Framework解説シリーズはアセット開発者のCrooked Head様から一部のコードやドキュメントなどの掲載の許可をいただいて公開しています。

※現段階で筆者の本フレームワークの理解度並びに、Unityの理解度が乏しいため、ドキュメントの翻訳が曖昧な箇所が多数あります。理解が進むにつれて適宜修正していく予定です(2024/2/5)。


Turn Based Strategy Framework(以後、TBSF)のドキュメント並びにコードの解説・コメントは英語で書かれています。そのため、私の理解度に乏しい箇所があります。一方でエディタと睨めっこしながら、もう一方では脳みそを英語モードになるのが面倒です。そこで、本稿はざっくり公式ドキュメンを日本語にし、以後の解説記事やカスタマイズの礎とします。ちなみに公式ドキュメントはアセット未購入の方でも読めます。

TBSFの公式ドキュメントを日本語にする

1. イントロダクション

このプロジェクトはターンベースストラテジーゲーム開発のために用意されたカスタマイズ可能なフレームワークです。これにより、カスタムマップを作成し、その上にユニットや障害物といったオブジェクトを配置して、手動・AIのどちらでもプレイすることができるようになります。また、このフレームワークは様々なゲームプレイマカニズムを簡単に実装できるように設計されています。このドキュメントではその使い方を詳しく解説しています。

次の章以降ではプロジェクトの構造(どういったファイルが入っていて、どんな時に必要なのか)、シーンの構造(どのようにセットアップするのか)を説明します。どのファイルが必要で、どのスクリプトを使うのかといった方法を解説しています。また、最後に短いチュートリアルがあり、全てのドキュメントの総括となっています。それに加えて、いくつかのサンプルシーンも用意しました。

2. プロジェクトの構成

プロジェクトの構造を以下の画像(Fig1)に紹介しています。本プロジェクトの本質はScriptsフォルダに格納されているコードです。他のライブラリとの衝突を避け、ナビゲートしやすくするために名前空間に分けられています。

プロジェクトの構成

また、Unityエディタを拡張するスクリプトはEditorフォルダに入っています。

それらで最も重要なスクリプトはGridHelperです。シーンをセットアップする際に非常に役に立つ強力なツールです。

Exampleフォルダにはフレームワークを使い始めるために用意したサンプルシーンが用意されています。各シーンには独自のアセット、コード、プレハブが含まれています。そのExamplesで使用したアセットは以下の通りです。

  • 1bit Pack

  • Roguelike/RPG Pack

  • Alien UFO Pack

  • Hexagon Tiles

  • UI Pack

  • Kenny Fonts

  • Background by Kronbits

  • Aekashics Battlers

これらのアセットは非常に素晴らしいので、ぜひチェックしてみてください。

3.シーンの構成

Unityで利用できるシンプルなアセットで作成したシーンを見てみましょう。画像2はこのシーンは六角形(ヘキサゴン)のセルグリッド、3種類のユニット数個、障害物、最小限のユーザーインターフェースで構成されています。

画像2。最小構成のシーン

今のところあまりパッとしないでしょうか?では、これからプロジェクトをカスタマイズするために何ができるか見てみましょう。まず、画像3に示すシーンのセットアップを見てください。

画像3。ヒエラルキー

ライト、カメラ、UI、イベントシステムはごく一般的なものです。最も重要なオブジェクトはCellGrid、Players、Unitsです。これらのオブジェクトの解説をします。

3.1 CellGrid

セルグリッドはシーンのメインオブジェクトです。グリッドが構成する全てのセルの親となります。画像4はCellGridのゲームオブジェクトを示しています。また、画像の通り、このCellGridには以下のスクリプトがアタッチされています。

画像4。CellGridの構成

・CellGrid
このスクリプトはゲームをトラック(追跡)し、セル・ユニット・プレイヤーオブジェクトを保存しています。ゲームを開始し、ターンの遷移をしてくれます。ユーザーがユニットやセルを操作すると反応し、ゲーム進行に関するイベントを発生させます。基本的にはゲームを管理する役割を担っています。

・CustomUnitGenerator
ユニットをゲームにロードするスクリプトです。

・SubsequentTurnResolver
次にどのプレイヤーが進行し、どのユニットが扱えるか決定するスクリプトです。「Turn Transitioning(ターン移行)」の章で解説しますが、別のResolverに置き換えることができます。

・DominationCondition
このスクリプトはゲームが終わったかどうか、勝者は誰なのかをチェックします。「Ending the Game(ゲームの終了)」の章でも解説しますが、別のResolverに置き換えることができます。

3.2 Players

Players ゲームオブジェクトはプレイヤーのゲームオブジェクトを保持します(そのままの意味だね)。
ここで述べるプレイヤーとはPlayerスクリプトを持つゲームオブジェクトを指します。プレイヤーの数に制限はありませんが、CellGridスクリプトを正しく動作させるには少なくとも1つのプレイヤーオブジェクトが必要です。属性(Attribute)のPlayer Numberは各プレイヤーにおいて固有でなければなりません(被らないようにする)。

本プロジェクトには強力な対戦AIプレイヤーの実装が含まれています。次の章ではAIのセットアップについて詳しく説明します。また、V2.1より前に使用されていたNaiveAiPlayerもありますが、互換性のために廃止されています。

画像5。Playerオブジェクト。

3.3 Units

Unitsゲームオブジェクトはゲームに参加する全てのユニットを保持します。親オブジェクトの外にユニットを配置すると正しく動作せず、エラーが発生します。各ユニットにはPlayer Number属性があり、PlayerオブジェクトのPlayer Numberと対応している必要があります。Playerを持たないユニットを追加しても良いですが、その場合はコントロールすることができないため注意が必要です。

画像6。Unitsゲームオブジェクト。

4.シーンの作成

前章で説明したセットアップは少々難しく感じるかもしれません。それはフレームワークがGrid Helperを含んでいるからです。この章では実際に準備する必要のあるプレハブとシーンの生成について学んでいきます。

4.1 Cell prefab

グリッドを生成する前にCellのプレファブが必要です。CellとはゲームオブジェクトでCellスクリプトが実装されています。また、マウスイベントが動作するようにコライダーを持っている必要があります。Cellプレファブのサンプルは画像7のようになります。

本プロジェクトには3つの抽象クラスがあります。「Cell」、「Square」、「Hexagon」です。あなたのプロジェクトでどのようなセルのスタイルにするかによって、SquareかHexagonのどちらを継承するか選べます(四角形か六角形のどちらか)。
三角形のような別のタイプのセルを追加したい場合はCellクラスから直接継承する必要があります。
Cellにはいくつかの抽象メソッドがあります。

int GetDistance(Cell other)
List<Cell> GetNeighbours(List<Cell> cells)
void CopyFields(Cell newCell)

SquareとHexagonのクラスはこれら3つのメソッドに対応しているので、派手なことをしないのであれば、特に気にする必要はありません。
次にカスタマイズメソッドがありますが、この時点では空の実装を与えていても構いません。これらは次の章で学びます。

void MarkAsReachable()
void MarkAsPath()
void MarkAsHighlighted()
void UnMark()

最後にグリッド生成の前に正しく実装する必要があるメソッドが一つあります。

Vector3 GetCellDimensions()

メソッドの名前が示すように、このメソッドはセルの座標を返します。これはグリッドを生成する際に必要で、ゲームオブジェクトを配置する間隔を教えてくれます。

どのように座標を得るのでしょうか。タイルのスプライトが16*16ピクセルで、Pixels per Unitを10に設定してインポートしたとします。その場合、座標は(16/10, 16/10)になりますよね。メソッドはVector3(1.6f, 1.6f, 0)を返すということになります。3Dセルの場合は実際のサイズをチェックする必要があります。

画像7。Cellプレファブのサンプル。

4.2 Grid生成

Cellプレファブの準備ができたらグリッドの生成をしましょう。グリッド生成はGrid Helperというツールで実行します。
UnityメニューからWindow>Grid Helperを選択するとアクセスできます。画像8はそのウィンドウです。

画像8。Grid Helperのウィンドウ。

Grid Helperの目的はユーザーによって与えられたパラメータで基本的なシーンを構造を生成することにあります。

Grid Helperのパラメータの意味は以下の通りです。

・Use movable camera
可動カメラスクリプトをシーンに追加するかどうか。

・Human Players No
生成する人間のプレイヤーの数

・AI Players No
生成するAIプレイヤーの数

・Plane
グリッドを生成する平面のタイプ(XY2Dなど)

・Generator
グリッドを生成するスクリプトの種類

本ブロジェクトには長方形、三角形、平行四辺形、六角形のグリッドを生成するスクリプトが含まれています。
それぞれのジェネレータはCellのプレファブとグリッドの座標という独自のパラメータを持っています。ICellGridGeneratorを実装することで、独自のジェネレータを作成することができます。それはドロップダウンリストに表示されます。

パラメータの設定が終わったら、Generate Sceneボタンをクリックしてください。このスクリプトは前章で説明したCellGrid、Players、Unitsなどの必要なゲームオブジェクトを全て生成します。
さらに、シーンにメインカメラがあることを確認し、マップを表示するように設定、ライティングを追加、ターン遷移をトリガーするためのシンプルなGUIコントローラを追加します。

4.3 タイルペインティング

Tile painter(タイルペインター)はTBSFのV2.0で導入されたGrid Helperの新機能です。このツールの使用目的はさまざまな種類のCellプレファブでグリッドをペイントすることです。このツールUnityメニューのWindow>Grid Helperで開くことができます。インターフェースは画像9の通りです。

画像9。Tile painterのウィンドウ。

このツールを使うにはブラシの半径(Brush radius)を選択し、使いたいタイルのプレハブを割り当て、インターフェース下部のボタンで編集モードに入ります。
プレハブはインスペクタのフィールドにドラッグするか、プロジェクトのエクスプローラで選択しましょう。
編集モードを終了するまで、シーン内のオブジェクトを選択、移動、操作をすることはできません。
画像10はTile painterの動作を示しています。ペインティングの半径を示す赤い円が描かれています。このツールはUnityネイティブのアンドゥ・リドゥ操作もサポートされています。

画像10。Tile painterの操作。

4.4 Unit Prefab

もう一つ用意しないといけないプレハブにUnitプレハブがあります。ユニットとはユニットクラスとコライダーを実装したゲームオブジェクトのことです。

Cellと同様にUnitにはいくつかの仮想的な外観カスタマイズメソッドがあり、派生クラスで実装する必要があります。繰り返しになりますが、今は空の実装をしてください。メソッドは以下の通りです。

void MarkAsDefending(Unit aggressor)
● void MarkAsAttacking(Unit target)
● void MarkAsDestroyed()
● void MarkAsFriendly()
● void MarkAsReachableEnemy()
● void MarkAsSelected()
● void MarkAsFinished()
● void UnMark()

次の章でこれらメソッドと残りの仮想メソッドについて学びます。

4.5 Unit Painting

Unit painter(ユニット・ペインター)はTBSF V2.0で導入されたもう一つの新機能です。これはグリッドにユニットをペイントするためのものです。UnityメニューのWindow>Grid Helperからアクセスできます。そのインタフェースを画像11に示します。

画像11。Unit painterのインターフェース。

ペインターを使用するにはユニットが所属するプレイヤーの番号を入力し、Unit prefabを選択します。
Tile painterと同じく、prefabをインスペクタのフィールドにドラッグするか、プロジェクトエクスプローラーで選択することで適用できます(ユニット編集モードがオンの時のみ)。

最後に、インターフェース下部のボタンでユニット編集モードをオンにして、シーンビューを使ってユニットを作成します。UndoとRedoがサポートされています。画像12はUnit painterの動作です。

画像12。Unit painterの動作している様子。

4.6 Prefab Helper

レベル(ステージ)を作成するにはかなりの数のprefabが必要になるでしょう。Unityでは複数のprefabを一度に保存することはできません。Prefab Helperはこの問題を解決するために作られました。
この機能はGrid Helperウィンドウで利用できます。現在のところ、このヘルパーの唯一の機能は選択されている複数のゲームオブジェクトをprefabに保存することです。手順は以下の通りです。

  1. prefabとして保存したいゲームオブジェクトを選択します。

  2. Prefab Helperのインターフェースの「Selection to Prefabs」または「Selection to prefab(variants)」ボタンをクリックします。後者のオプションはprefabをVariantとして保存します。

  3. ダイアログウィンドウで保存先を選択します。

画像13。Prefab Helperのインターフェース。

5. Customization(カスタマイズ)

TBSFの強みは簡単にカスタマイズできることです。本プロジェクトではそれぞれ異なる種類のスタイルをもつ3つの例を提供しています。

5.1 Cell カスタマイズ

まずはこのドキュメント用に作成したCellを見てみましょう。
画像14の通り、Cellは3Dオブジェクト、スプライト、六角形、正方形にすることができます。また、異なる種類のCellを実装することも可能です。

画像14。異なる種類のCell。

Cellはその状態に応じて外見を変えるようにプログラムすることができます。そのためにはCellから派生したクラスで適切なメソッドをオーバーライドします。使用できるメソッドは以下の通りです。

void MarkAsReachable()
● void MarkAsPath()
● void MarkAsHighlighted()
● void UnMark()

画像15にあるように、異なる状態のCellを見てみましょう。
左から通常、ハイライトされた状態(マウスがCell上にある時)、到達可能としてマークされた状態(現在選択されているユニットの移動可能なCell)、グレー、黄色、緑を多用していますが、もちろんこれに限りません。マーカーは色でなくても設定可能です。パーティクルや画像なども使えます。

画像15。Cellのさまざまな状態。

Cell Gridの振る舞いを全体として変えることができる抽象メソッドが2つあります。

int GetDistance(Cell other)

パラメータとして与えられたCellまでの距離を返します。デフォルトではマンハッタン距離が使われます。距離は経路探索や攻撃範囲の計算に使用されます。

List<Cell> GetNeighbours(List<Cell> cells)

このメソッドは隣接するCellのリストを返します。隣接するCellは経路探索関数で使用されます。

5.2 Unit Customization(ユニットカスタマイズ)

Cellと同様にUnitの外観もオーバーライドすることでカスタマイズできます。

void MarkAsFriendly()
● void MarkAsSelected()
● void MarkAsReachableEnemy()
● void MarkAsFinished()
● void MarkAsDefending()
● void MarkAsAttacking()
● void MarkAsDestroyed()
● void UnMark()

これらの異なる状態のUnitを画像16に示します。
左から味方ユニットとしてマークされた状態、選択されたユニット、攻撃範囲内にある敵ユニットの状態、行動終了後のユニット(移動も攻撃を終了した状態)です。

画像16。ユニットの状態によって変わる見た目。

外観とは別にユニットの動作もオーバーライドすることで、さまざまにカスタマイズできます。

void OnMouseDown()
● void OnMouseEnter()
● void OnMouseExit()

これら3つのメソッドは「ユーザーがユニットをクリックしたとき」、「マウスでユニットをハイライトした時」、「そのマウスポインタがユニットのコライダーから出た時」にUnityによって呼び出されます。
これらメソッドはUnitClicked、UnitHighlighted、UnitDehighlightedイベントを呼び出します。

void OnUnitSelected()
● void OnUnitDeselected()

これらはユニットが選択されている時と選択解除された時に呼び出されるメソッドです。選択されているということは現在、プレイヤーがそのユニットをクリックし、使用を試みているということを指します。

void OnTurnStart()
● void OnTurnEnd()

プレイヤーがターンを開始した時と終了した時に、そのプレイヤーに属する全てのユニットに対して呼び出されます。

void OnDestroyed()

ユニットが破壊された(倒された)時に呼び出されます。

bool IsUnitAttackable(Unit other, Cell sourceCell)

パラメータが二つあります。あるユニットがパラメータとして与えられたCellから、パラメータとして与えられたユニットを攻撃できるかどうかを示すbool値を返します。つまり、今いる場所から狙いたい相手を攻撃できるかどうかということ。

● AttackAction DealDamage(Unit unitToAttack)

攻撃したユニットが対象に与えるダメージの計算をします。

void AttackActionPerformed()

攻撃が実行された後に呼び出されるメソッドです。

int Defend(Unit aggressor, int damage)

攻撃によって実際にどれだけのダメージが与えられたか計算するメソッドです。先述のDealDamage()と違う点は地形防御ボーナスなど、ダメージ付与を実装したい場合にも対応するためです。

void DefenceActionPerformed()

防御アクションが実行された後に呼び出されるメソッドです。

bool IsCellMovableTo(Cell cell)
● bool IsCellTraversable(Cell cell)

これらのメソッドはユニットが指定されたCellで移動を終了できるかどうか、または指定されたCellを通過できるかどうかを示すbool値を返します。

void Move(Cell destination, List<Cell> path)

このメソッドはユニットをあるCellから別のCellに移動させます。

上述のメソッドは仮想的なもので、いくつかのデフォルトの振る舞いが実装されていることを忘れないでください。
派生コードでは基本実装を呼び出すか、クラス内の基底コードを統合する必要があります。

5.3 Unit special abilities(ユニットの特殊能力)

ユニットの能力システムはユニットにカスタマイズされた挙動を追加することを容易にする強力なツールです。
これは直感的に再利用可能であり、人間のプレイヤーとAIプレイヤー両方が簡単にアクセスできるようにカプセル化されています。
移動や攻撃といった基本的なユニット能力も例外ではなく、この方法で実装されています。
これは非常に重要なトピックであり、それ自体で詳しく説明する価値があります。

5.3.1 使用方法

アビリティをユニットで使用可能にするにはアビリティスクリプトをユニットのPrefabに追加するだけです。
移動と攻撃のアビリティはデフォルトではUnitスクリプトがゲームオブジェクトにアタッチされるとデフォルトで追加されます。
新しいアビリティを実装するにはAbilityクラスを継承します。実装ではアビリティがプレイヤーにどのように表示されるか、また能力が発動した時に何が起きるかを定義します。
そのインターフェースは以下の通りです。

void Display(CellGrid cellGrid)
● void CleanUp(CellGrid cellGrid)

これらのメソッドは人間のプレイヤーに対してのみ呼び出されます。Displayの目的はアビリティを可視化することです。例えば、移動可能なCellや範囲内にいる敵をハイライトします。
アビリティの選択が解除されるとCleanUpメソッドが実行されます。グリッドがデフォルトの見た目になります。

void OnUnitClicked(Unit unit, CellGrid cellGrid)
● void OnUnitHighlighted(Unit unit, CellGrid cellGrid)
● void OnUnitDehighlighted(Unit unit, CellGrid cellGrid)
● void OnCellClicked(Cell cell, CellGrid cellGrid)
● void OnCellSelected(Cell cell, CellGrid cellGrid)
● void OnCellDeselected(Cell cell, CellGrid cellGrid)`

人間のプレイヤーに対してのみ呼び出されるメソッドの別のバッチ。アビリティに関するコンテキスト情報を表示するために使用できる。効果範囲攻撃の影響を表示するために使用できる。
OnUnitClickedとOnCellClickedは通常アビリティを実行するために使用されます。

void OnAbilitySelected(CellGrid cellGrid)
● void OnAbilityDeselected(CellGrid cellGrid)
● void OnTurnStart(CellGrid cellGrid)
● void OnTurnEnd(CellGrid cellGrid)
● void OnUnitDestroyed(CellGrid cellGrid)

これらのメソッドはアビリティを使用するプレイヤータイプに関係なく実行されます。OnTurnStartとOnTurnEndはパッシブアビリティを実装するために使用できます。

bool CanPerform(CellGrid cellGrid)

アビリティを使用できるかどうかを定義するためのメソッドです。例えば、ユニットが移動するための移動ポイントが残っているかどうかをチェックすることができます。

● IEnumerator Act(CellGrid cellGrid)

最後にこのActメソッドはアビリティが実際に何をするか定義する場所です。これはコルーチンとして実行されます。ほとんどのアビリティはアニメーションの再生など、実行に時間がかかるためそうしています。
通常の関数のようにメソッドを呼び出しても何の効果もないので、コルーチンとして実行することを覚えることが重要です。そのため、ベースとなるAbilityクラスはExecuteというユーティリティメソッドがあります。
これはActを直接使う代わりにアビリティを適用するために使われるべきものです。このメソッドはあなたの代わりにコルーチンを実行し、またコルーチンの終了後に実行される二つの関数をパラメータとして受け取ります。
プリアクションおよびポストアクションがすでに設定されている便利なメソッドがさらに二つあります。
アビリティが実行されている間、入力をブロックするHumanExecuteと空のプリアクションおよびポストアクションをもつAI Executeです。

5.3.2 仕組み

前述したようにAbilityスクリプトはユニットゲームオブジェクトにアタッチする必要があります。アビリティをパラメータとして受け取る、CellGridStateAbilitySelectedオブジェクトによって処理されます。
デフォルトではユニットに直接アタッチされた全てのアビリティが選択されます。異なるCellGridStateスクリプトについては次の章で説明します。

このシステムを活用して、アビリティを個別に選択することができます
。プレースホルダーアビリティというプレースホルダーを用意し、選択可能なアビリティのスクリプトを保持し、各アビリティをボタンとして表現します。
ボタンをクリックするとGridStateがCellGridStateAbilitySelectedに設定され、パラメータとして特定のアビリティが渡されます。

5.3.3 結論


アビリティシステムはターンベースストラテジーに全く新しいレベルの深みをもたらします。
以前は追加するのが厄介だった昨日も、今では簡単に直感的に実装できるようになりました。
TBSFコミュニティの皆さんはいつもさまざまなゲームプレイメカニズムについて質問していただきありがとうございます。
皆さんの質問はフレームワークを改善する上で、いつも私を刺激してくれます。

5.4 カスタマイズの例

いかにプロジェクトのカスタマイズ例をいくつか紹介します。まず、Cellのビジュアルのカスタマイズにどのようにアプローチしたのか見ていきましょう。Cell Prefabのサンプルを画像17に示します。

画像17。Cell Prefabのサンプル。

このPrefabはCellに必要なコンポーネント(Cellスクリプトと2Dコライダー)を保持する親オブジェクトと「marker」と呼ばれるその子オブジェクトから構成されています。Markerは写真にあるような淡いオーバーレイです。コードは以下のようになります。

Markerのコード。

基本的にこれは各状態でマーカーを異なる色に設定するものです。UnMarkerメソッドではマーカーは透明に設定されます。画像18はこれがどのように機能しているか示しています。

Markerがどのように機能しているか。

次にユニットの振る舞いをカスタマイズしてみましょう。画像19の例では空飛ぶ円盤は水面や障害物の上を移動できますが、地上にいるユニットはそれらを移動できません。

画像19。空飛ぶ円盤と地上ユニットの例。

そうした効果を実現するには以下の手順を踏みます。

・Cellの派生クラスを作り、2つの新しい属性を持たせます。

Cellの派生クラス。地上タイプと飛行タイプといったところだろう。

GroundTypeは次のような列挙型です。

GroundType。

本ドキュメントではこのクラスを「MyOtherHexagon」と命名します。

・Unitから派生したクラスでエイリアンユニットを作ります。IsCellMovableToメソッドとIsCellTraversableメソッドをオーバーライドします。このクラスをAlienと命名します。

メソッドをオーバーライド。

・Alienから派生したクラスを作成します。

今回はできることを増やすために、さらに多くのメソッドをオーバーライドしていきます。このクラスをFlyingAlienと命名します。

FlyingAlienのコード。先述のオーバーライドしていく。

見てわかる通り、これらはとても簡単です。IsCellTraversableでユニットが他の飛行ユニットに占領されていないCellを移動できることを定義しています。
次に、MoveメソッドでIsSkyTakenフィールドをユニットが離れるCellではfalseに移動するCellではtrueにしています。(基底クラスのMoveメソッドもisTakenフィールドに同じことをしています)。
最後に、ユニットが破壊されるとIsSkyTakenフィールドはfalseになります。
飛行ユニットは水上を移動することができないので、IsCellMovableToメソッドをオーバーライドする必要はありません。

他の例ではジャンケンのようなユニットの相性システムを作ることができます。Example Scene1にはそのようなシステムの実装が含まれています。その効果を得るには単純にUnitのサブクラスを3つ作り、それらのDefend()メソッドをオーバーライドするのです。
このメソッドでは相手のユニットのタイプをチェックし、それに応じてダメージを倍増させるのです。

相性システムの実装。まさにジャンケン。

最後にユーザーインターフェースについて説明します。アイディアとしてはイベントに基づいています。GUIControllerを次のような構造にします。

画像20。GUIControllerの構造。

ここで最も関連する属性はCellGridとUnitsParentです。これらはUIがそれらにどのような反応をするか定義しています。利用可能なイベントの完全なリストはコードを参照してください。
UIの3つの例をとして画像2、画像18、画像19も確認ください。また、別のアプローチとして画像21にも示します。

画像21。UIはゲームに合わせてアイディアを練っていきましょう。

6. AI Player(AIプレイヤー)

本プロジェクトにはカスタマイズや拡張が容易なAIの実装が含まれています。ルールベースでありながら、人間のプレイヤーに本当の挑戦を提供することができます。次の章ではシステムの使い方とカスタマイズ方法について説明します。

6.1 概要

AIを使うにはAIPlayerスクリプトがアタッチsあれたプレイヤーオブジェクトを用意します。
グリッド生成中にGrid Helperがプレイヤーをセットアップしてくれるので、手動ではセットする必要はありません。
スクリプトにはUnitSelectionコンポーネントが必要です。基本的な実装はデフォルトで追加されています。

AIはルールベースであり、個々のユニットにアタッチされているAIActionスクリプトを使用します。AIActionはユニットが取ることができる一つのアクションを表します。AIはそれぞれのアクションを順番に処理し、アクションが実行されるべきかどうかを評価し、それに従って行動します。

6.2 AIアクションの概要

各アクションをいくつかのユニット能力に対応しています(通常は一つですが、それ以上の可能性もあります)。
一方、一つの能力を複数のAIアクションで使用することがあります。本プロジェクトにはユニットアビリティに関する二つのAIアクションMoveToPositionAIActionとAttackAIActionがあります。
AIActionのパブリックインターフェースは以下の通りです。

bool ShouldExecute(Player player, Unit unit, CellGrid
cellGrid)

これはアクションがAIによって実行されるべきか決定します。

● Precalculate(Player player, Unit unit, CellGrid cellGrid)

ゲーム状態を処理して、どのユニットを攻撃するかなどのアクションを決定します。このアイディアはExecuteメソッドが実行される前に、この情報が利用可能であるべきということです。

● IEnumerator Execute(Player player, Unit unit, CellGrid
cellGrid)

基底となるユニットのアビリティを使ってアクションをします。Ability .Actと同様にコルーチンとして実行します。

● ShowDebugInfo(Player player, Unit unit, CellGrid
cellGrid)

デバッグ情報を表示します。AIアクションのデバッグについては次の章で説明します。

● CleanUp(Player player, Unit unit, CellGrid cellGrid)

Precalculateが設定したフィールドを全てクリアし、グリッドをデフォルトに戻します。

6.3 基本的なAIアクション

本プロジェクトには基本的なユニットアビリティのMoveToPositionAIActionとAttackAIActionに関連する基本的なAIアクションが含まれています。
それぞれMoveAbilityとAttackAbilityに対応しています。

この二つのAIActionを持つ基本的な頭脳はすべてのUnityスクリプトがアタッチされたオブジェクトに追加されます。

本プロジェクトで提供されているエバリュエーターは数種類であり、簡単に追加することができます。

6.3.1 MoveToPositionAIAction

MoveToPositionアクションはユニットを移動させるためにMoveAbilityを使用します。重い作業のほとんどはShouldExecuteメソッドで行われます。グリッド上に現在のCellよりも高いスコアを持つCellがあるかどうかをチェックします。スコアはCellエバリュエーターのスコアの合計として計算されます。
注目すべきは移動範囲を超えたCellが選択される可能性があることです。そのような場合、ユニットは可能な限りそのCellに向かって移動するか、その経路上にあるスコアの高いCellを選択します。
この動作はUnityのインスペクタで設定できるShouldMoveAllTheWayフラグによって制御されます。Cellのエバリュエーターは以下のインターフェースを持っています。

float Weight

このエバリュエーターに割り当てられたウェイトです。デフォルトではウェイトは1です。Unityインスペクタで設定できます。

void Precalculate(Unit evaluatingUnit, Player
currentPlayer, CellGrid cellGrid)

連続したエバリュエーターの呼び出しによって再利用の可能性があるデータをキャッシュします。

float Evaluate(Cell cellToEvaluate, Unit evaluatingUnit,
Player currentPlayer, CellGrid cellGrid)

与えられたスコアの計算とプロジェクトに含まれているエバリュエーターを組み合わせるか、自分で実装してください。
使用するにはMoveToPositionAIActionと一緒にアタッチするだけです。エバリュエーターはプロジェクトの以下に含まれます。

● DamageCellEvaluator

与えられたスコアからもらうダメージを基づいてセルにスコアを付与します。

● DamageRecievedCellEvaluator

与えられたCellからもらうダメージに基づいてCellのスコアを評価します。

● DistanceCellEvaluator

Cellに到達するのにかかるターン数に基づいてCellのスコアを評価します。

● AlliesNearbyEvaluator

隣接する味方の数に基づいてCellのスコアを評価します。

● PositionProximityCellEvaluator

他のCellとの近さに基づいてCellのスコアを評価します。

● UnitProximityCellEvaluator

他のユニットへの近さに基づいてCellのスコアを評価します。

● RandomCellEvaluator

Cellにランダムな得点を割り当てます。

6.3.2 AttackAIAction

AttackAIActionはAttackAbilityを使用して敵ユニットに攻撃します。ShouldExecuteは攻撃範囲内にユニットがあるかどうかをチェックし、Precalculateはevaluatorsからのスコアに基づいてトップターゲットを選択し、Executeが攻撃を開始します。
UnitEvaluatorは以下のようなインターフェースを持っています。

float Weight
● float Evaluate(Unit unitToEvaluate, Unit evaluatingUnit,
Player currentPlayer, CellGrid cellGrid)

Evaluateを使うにはAttackAIActionの次にアタッチします。プロジェクトには二つのユニットevaluatorがあります。

● DamageUnitEvaluator

与えることができるダメージによってユニットを評価します。

● HPUnitEvaluator

残りのHPに基づいてユニットを評価します。

6.4 AI Actionのデバッグ

AIのプレイを観察していると、なぜそのような判断をしたのか不思議に思うことがあるかもしれません。そこで、AIのデバッグモードが活躍します。
AIPlayerスクリプトのDebugModeフラグでオン・オフ・切り替えます。デバッグログはAIAction.ShowDebugInfoからくるようになります。
基本的なAIActionにはすぐに使える状態で実装されていますが、カスタムAIActionには自分で実装する必要があります。
ログはUnityコンソールへのプリントのような単純なものにすることができます。また、ビルトインのCellとユニットのカラーリングメカニズムもあり、データを視覚しやすくなっています。
デバッグモードをオンにすると、AIユニットを選択し、アクションををトリガーするためのボタンを押すように促されます。
アクションが実行される前にデバッグ情報が表示されます。画像22は選択されたユニットのセルスコアを示します。
緑は高得点、赤は得点が低い得点を表します。最高得点は青色で強調され、ユニットが実際に動かせるセルは紫で強調表示されます。
任意のセルをクリックすると、その得点と個々の構成要素がコンソールに表示されます。

画像22。AI ACtionのデバッグモード。

6.5 ユニットの選択される順番

もう一つ考慮すべき点はAIがユニットを選択する順番です。この点に関するコンポーネントはUnitSelectionであり、以下のインターフェースを持っています。

● IEnumerable<Unit> SelectNext(List<Unit> units, CellGrid
cellGrid)

本プロジェクトにはユニット選択の二つの基本的な実装が含まれています(以下)。

● MovementFreedomUnitSelection

移動能力に基づいてユニットを選択します。これはデフォルトでAIPlayerに付与されています。

● SubsequentUnitSelection

ユニットを一つずつ選択します。

6.6 結論

AIシステムは対戦していて楽しい、有能なコンピュータが制御したプレイヤーを作るための強固な土台となります。今後の開発ステップとしてはこのフレームワークをUnityMLAgentパッケージと統合することです。
AIに強化学習を使うことはフレームワークのもう一つのブレークスルーになるでしょう。将来のリリースのいずれかに実装することが楽しみです。

7.ゲーム状態の管理

この章ではユーザーとゲームとのインタラクションを司るメカニズムを取り上げます。ゲームとのインタラクション、ターン遷移、ゲームオーバー条件の処理などを担当するメカニズムを見てみましょう。

7.1 ユーザーとの対話

ユニットの選択、移動、攻撃はCellGridによって「CellGrid .CellGridState」クラスのサブクラスに譲渡されます。
もしあなたがStateデザインパターンに慣れていればこの仕組みはすぐに分かるでしょう。
CellGridStateは抽象クラスで、Cellが選択されたり、選択解除されたり、選択された時に呼び出されるコールバックメソッドを含んでいます。そして、どのユニットがクリックされた時にも呼び出されるメソッドです。
それとは別に初期化とクリーンアップに使われるOnStateEnterメソッドとOnStateExitメソッドがあります。

これらのメソッドはシーン内のCellGridオブジェクトによって呼び出されます。全てのメソッドは仮想で、派生クラスによってオーバーライドできます。
本プロジェクトには三つのグリッド状態の実装が含まれています。
このフレームワークのバージョン2.1ではユニットの移動と攻撃の処理はCellGridStateUnitSelectedから切り離され、State自体はCellGridStateAbilitySelectedに置き換えられました。新しいStateはアビリティを実行するために使われます。

CellGridStateWaitingForInputはOnUnitClickedメソッドだけを実装しており、味方ユニットがクリックされるとグリッドの状態をCellGridStateAbilitySelectedに変更します。最後にCellGridStateBlockInputメソッドは他のメソッドを実装しておらず、基本的にユーザーインタラクションを無効にします。これはAIのターンになった時、ゲームが終了した時に使われます。

7.2 ターン遷移

ターンはCellGrid .EndTurnメソッドが呼ばれたときに終了します。本プロジェクトで提供している例ではAIはCellGridオブジェクトへの参照を通して直接このメソッドを呼び出します。人間のプレイヤーはGUIボタンを使ってターンを終了します。
フレームワークのバージョン2.1ではターン遷移をカスタマイズするメカニズム、turn resolverが導入されました。このメカニズムにより、与えられたターンで使用できる次のプレイヤーとユニットを選択することができます。resolverを使うにはシンプルにスクリプトをCellGridに追加します。
TurnResolverクラスを実装して独自のResolverを作成することも、すでに実装されているResolverを使用することもできます。

● SubsequentTurnResolver

プレイヤーはプレイヤー番号に従ってターンをこなします。これはGridHelperによってCellGridに追加されたデフォルトのResolverです。

● SpeedTurnResolver

プレイヤーは自分の速度に従ってターンが回ります。ユニットが移動できるのは各ターンが各ターンごとです。ターンが変わると以下のことが起きます。
OnTurnEndメソッドが呼ばれ、次のターン遷移先のプレイヤーが選択され、その際にアクティブになる全てのユニットに対してOnTurnStartが呼び出されます。最後に、現在のプレイヤーオブジェクトに対してPlayメソッドが呼ばれます。プレイヤーが人間の場合はCellGridStateWaitingForInputがグリッド状態として割り当てられ、ゲームとインタラクトできます。

7.3 ゲームの終了

フレームワークのバージョン2.1からゲームの終了条件をカスタマイズできるようになりました。
そのためにはGameEndConditionクラスを実装するか、すでに実装されているResolverを使用します。

● DominationCondition

これまで通りのベーシックな勝利条件です。敵ユニットを全滅させれば勝利となります。この条件はGridHelperによってデフォルトでCellGridに追加されます。

● PositionCondition

特定のセルに到達すれば勝利です。

● ObjectiveDestroyCondition

特定のユニットを破壊すると勝利です。

● TurnLimitCondition

特定のターン数経過で勝利です。

この勝利条件を扱うにはCellGridゲームオブジェクトにスクリプトを追加するだけです。一度に複数の異なるResolverをアクティブにすることができ、それぞれの条件を異なるプレイヤーに適用することができます。
例えば、あるプレイヤーは敵の増援が到着する前にXターン(TurnLimitCondition)以内にヒーローユニットを安全(PositionCondition)に誤送する必要があります。
別のプレイヤーの目的はヒーローを倒すか(ObjectiveDestroyCondition)、ヒーローが逃げるのを阻止するのに十分な時間稼ぎをすることです。
この勝利条件のチェックは以下のイベント飲みで実行されます。
ユニットの移動、ユニットの死亡、ターン終了、

それ以外のタイミングで実行したい場合は手動でCellGrid .CheckGameFinishedを呼び出す必要があります。ゲームが終了するとCellGrid .GameOverイベントが呼び出されます。引数には勝利したプレイヤーのリストと負けたプレイヤーのリストが含まれます。

8.オンラインマルチプレイ

本フレームワークにはオンラインプレイ機能が含まれています。マルチプレイヤー機能をゲームに統合することができます。
この章ではクイックスタートガイドを提供します。重要な点はNetworkConnectionの設定、サーバー接続の管理、全てのクライアントインスタンスで一貫したゲーム状態を確保することなどが含まれます。

8.1 アーキテクチャ

フレームワークにおけるオンラインプレイの中心的なコンポーネントは抽象クラスであるNetworkConnectionクラスです。このクラスはサーバー接続をオーケストレーションし、クライアント間の通信の促進を担当しています。アビリティの軌道やターンの終了など、ゲーム内の重要なアクションを全てインターセプトします。これらのアクションはシリアライズされ、他のクライアントにブロードキャストされます。受信すると、アクションはでシリアライズされ、ゲームに適用されます。このプロセスにより、全てのクライアントで一貫したゲーム状態が保証されます。
NetworkConnectionは特定のオンラインバックエンドサービスプロバイダで実装されるように設計された抽象クラスです。
このクラスはこれらのサービスが処理すべき基本的なネットワーク機能を定義しています。

・Server Connection
マルチプレイヤーゲームサーバーへの接続と確立と管理。

・Room Management
ルームの作成と参加を処理します。

・Player Managemant
プレイヤーの入退室に関するイベントの管理とプレイヤー情報の受付などをします。

・Match State Communication
対戦相手の行動やゲーム状態の変化など対戦状態に関する情報をネットワーク上で送受信します。

・Random Number Generator Initialization
乱数発生の初期化を特定のシードで行います。UnityEngine .Randomはゲーム内の全ての乱数タスクに使用する必要があります。Nakamaサービスに基づくNetworkConnectionの実装はGithubで提供されています。特定のバックエンドをフレームワークに統合する方法を示しています。

8.2 シーンセットアップ

オンラインプレイ用にシーンを準備するには以下の手順に従ってください。

・Immediate Game Startを無効にする
CellGridスクリプトのShouldStartGameImmediatelyのチェックを外しましょう。この変更により、シーン起動時ではなくマッチアップ完了後にのみゲーム開始されます。

・Network GYU Prefabを追加する
Prefab \NetworkGUIをシーンに投入します。このPrefabはサーバー接続、ルーム管理、ゲーム開始の処理を行います。

・ネットワークの接続を実装する
空のGameObjectをシーンに追加し、NetworkConnectionクラスの実装をアタッチします。実装には独自の実装を使用するか、Githubで入手できるNakamaに基づく実装を選択します。

・Network GUIを設定する
Network GUIオブジェクトのフィールドに必要なパラメータ「CellGrid」「Network Connection」「PlayerParent」を入力します。

□オプション設定

・プレイヤーの切断設定
Player Disconnected ConditionスクリプトをCellGridに追加しNetworkConnectionフィールドを埋めます。このスクリプトはゲームの終了をトリガーします。

・ホストの切断処理
HostDiconnectionConditionスクリプトをCellGridに追加し、Network Connectionフィールドを埋めます。これにより、ゲームホストが切断した場合にゲームが終了するようにします。

本フレームワーク内の各例にはマルチプレイヤーテンプレートシーンが含まれておりシーンをミラーリングします。これらのテンプレートシーンは基本的なセットアップが完了しており、必要なのはNetworkConnectionの実装と参照フィールド設定を追加するだけです。

8.3 NetworkGUI

本プロジェクトには初歩的なユーザーインターフェースである「Network GUI」スクリプトとそれに対応するPrefabがあります。スクリプトはNetwork Connectionを利用して以下の機能を実装します。

・サーバー接続
プレイヤーが指定したユーザー名でサーバーに接続できるようにします。

・ルーム作成
指定した名前で新しいルームを作成できます。ルームは公開・非公開を設定できます。

・ルームリスト
参加可能なパブリックリームのリストを表示します。

・ルーム参加
プレイヤーが既存のルームに参加するための機能を提供します。

・プレイヤーの選択と準備
対戦相手が自分の番号を選んでルームの準備状況を表示します。

8.4 アビリティセットアップ

全てのクライアントインスタンスで一貫したゲーム状態を維持するにはアビリティの実行を同期させる必要があります。
この同期はAbilityクラスから派生したスクリプトに二つの仮想メソッドを実装することによってできます。フレームワークに含まれる全てのアビリティはこれらの実装をすでに備えています。必要なメソッドは以下の通りです。

- IDictionary<string, string> Encapsulate()

これはアビリティのパラメータをキーと値として返します。ネットワーク伝達のためにアビリティのデータをカプセル化します。

- IEnumerator Apply(CellGrid cellGrid, IDictionary<string,
string> actionParams, bool isNetworkInvoked)

このメソッドはEncapsulateメソッドによって生成されたディクショナリを受け取りパラメータをデコードして、アビリティの実行に進みます。

8.5 その他のアクション

アビリティだけでなく、他のタイプのデータもシリアライズして他のクライアントにブロードキャストする必要があるかもしれません。
そのようなデータにはゲームルームで選択されたプレイヤー番号やプレイヤーの準備状況、選択されたマップ、その他のカスタマイズパラメータが含まれます。それらを扱うには以下の2つのステップがあります。

・ハンドラーメソッドの登録
メソッドを使用して特定のイベントのハンドラ関数を登録します。このメソッドにはハンドラ関数とイベントの識別子となるオペコードが必要です。このハンドラ関数は指定されたオペコードを持つメッセージを受信した時に呼び出されます。

・イベントのブロードキャスト
イベントを他のインスタンスにブロードキャストするにはNetworkConnection.SendMatchStateメソッドを使用します。これにはイベントのオペコードとイベントパラメータを送信の引数として指定します。

8.6 Nakamaの実装

Heroic LabsのNakamaはリアルタイムマルチプレイヤーゲーム用のオープンソースサーバーです。本フレームワークの開発者はTBSF用にカスタムNakamaクライアントとサーバーを実装しました。法的な理由からこれらはプロジェクトには含まれていませんが、代わりにGithubで入手できます。

8.6.1 Nakama server

カスタムNakamaサーバーはGithubのページにあります。セットアップ方法はGithubページを参照してください(外部リンク

8.6.2 Nakama クライアント

NakamaクライアントはカスタムUnityパッケージとして配布されています(外部ページ)。セットアップ方法はGithubページを参照してください。

8.6.3 免責事項

このプロジェクトはHeroic Labsによって承認されたものでも、提携しているものではありません。NakamaはHeroic Labsの商標であり、ここでは説明の目的のみに使用しています。本プロジェクトによるNakamaの名称の使用はHeroic Labsとの提携またはHeroic Labsによる推奨を意味するものではありません。

8.7 制限事項

現在のオンラインプレイの実装にはいくつかの制限があります。プロジェクト固有のものではなく、大幅なコードのリファクタリングなしに対処できるものです。制限は以下の通りです。

・ホスト転送なし
オンライン対戦を開始したプレイヤーが離脱した場合、その対戦はサーバー上で終了します。つまり、ホストの役割はプレイヤーに引き継がれません。

・ユーザー名ごとの単一ログイン
現在の認証方法は迅速なテストのために設計されています。現在の認証方法は同じユーザー名での複数ログインをサポートしていません。製品版での使用には適していません。

・NetworkGUIにおけるプレイヤー番号の欠如
提供されているNetworkGUIは初歩的なもので、プレイヤーが入力したプレイヤー番号を検証しません。無効な入力につながる可能性があります。

・GUIにおけるターン表示の制限
サンプルシーンには現在、ローカルプレイヤーのターンを示す視覚的な合図がありません。ターン終了ボタンの有効無効のみに依存しています。

9.チュートリアル

※Unity初心者でも使えるようなチュートリアル徹底解説記事を公開しました。

このセクションでは可能な限りシンプルなシーンをゼロから作成するプロセスを説明します。シーンはキューブセル、キューブユニット、キューブ障害物のグリッドで構成されます。
完成済みのチュートリアルシーンはExample/Tutorialフォルダにあります。

  1. まず最初にUnityエディタで新規シーンを作成します。

  2. UnityエディタでGameObject>3DObject>Cubeをクリックして立方体を作成します。これがセルのPrefabになります。キューブにはデフォルトでBoxColliderがアタッチされていることに注意してください。

  3. 次にコーディングです。新しいスクリプトを作成して名前をつけましょう。ここでは例えとして、SampleSquareとします。

  4. SampleSquareはSquareクラスを継承し、セルの外観に関わるいくつかのメソッドをオーバーライドします。ハイライトされると灰色になり、到達可能な場合黄色になり、緑色はパス(経路)を示します。コードは下の画像のようになります(見えにくい場合は公式チュートリアルを参照してください)。

SampleSquareのコード。Squareをオーバーライドしていく。

5.スクリプトを先ほどのキューブにアタッチして、移動コストパラメータを1に設定し、Prefabを作成するためにプロジェクトエクスプローラにドラッグしてPrefabを作成します。
6.Window>Grid Helperを選択してGrid Helperを開きます。
7.Grid Helperのウィンドウでパラメータを入力します。入力するパラメータは画像24をご覧ください。

画像24。Grid Helperのウィンドウ。

8.パラメータを入力したら、GridHelperウィンドウの「Generate Scene」ボタンをクリックしてください。この時点でのシーンのヒエラルキーを画像25に示します。またシーンビューを画像26に示します。

画像25。シーンのヒエラルキー。
画像26。シーンビュー。

9.いよいよユニットをシーンに追加します。新しいスクリプトを作成し、名前をSampleUnitと名付け、Unitを継承させます。味方キャラユニットは薄緑色になるようにしましょう。
ユニットが選択されると、緑色に点灯し、攻撃可能になると赤色に点灯します。ターンが終了すると灰色になります。
子オブジェクトのRendererコンポーネントにアクセスしていることに注意してください。これについては後ほど説明します。

SampleUnit。Unitクラスをオーバーライドする。

10.新しいマテリアルを二つ作成し、二つの異なる色にします。

11.空のゲームオブジェクトを二つ作成し、SampleUnitをそれにアタッチします。ゲームオブジェクトにキューブを子として追加し、マテリアルをアタッチします。このユニットをPrefab化しましょう。

12.ユニットの子としてキューブを追加する理由はユニットがその上にあるセルの中心にスナップされるからです。立方体の位置をオフセットして、セルの内側ではなく、上に表示させるためです。そのためにキューブの位置をY軸の0.9に設定します。

13.最後に親ゲームオブジェクトにコライダーをつけます。BoxColliderを追加し、中心フィールドのY値を0.9にオフセットします。

14.SampleUnitスクリプトにパラメータを入力します。選択した値は画像27の通りですが、自由に試してみてください。両ユニットのLeading Colorパラメータを異なる値に設定してください。

画像27。SampleUnit。

15.Unit Painterを使ってユニットをゲームに追加します。Grid HelperをWindow>Grid Helperから開きます。Unit Prefabフィールドにユニットをドラッグアンドドロップします。
Player Numberを0にして、Enter Unit Edit Modeボタンをクリックします。インターフェイスは画像28の通りです。

画像28。Unit Painterのインターフェース。

16.Unit Edit Modeではシーンビューのセルをクリックすることで、ユニットをグリッド上に配置することができます。
いくつかのユニットを作成しましょう。ユニットのPrefabとプレイヤー番号を変更し、両チームのユニットを作成します。画像29はこの時点でのシーンセットアップです。

画像29。シーンセットアップ。

17.シーンに障害物を追加してみましょう。そのために別のセルPrefabを作成します。新しいキューブを作成し、黒いマテリアルを貼り付けます。既存のPrefabを複製し、キューブに貼り付けます。このPrefabを画像30に示します。新しいPrefabのIsTakenフィールドをTrueに設定することを忘れないようにしましょう。

画像30。黒いマテリアルを貼り付けたキューブ。

18.Tile Painterを使って用意したセルをグリッドに追加します。Tile PainterはUnit Painterと同様にGrid Helperからアクセスできます。セルPrefabをTile Prefabフィールドにドラッグアンドドロップし、Enter Tile Edit Modeボタンをクリックします。シーンビューを使って新しいセルを配置します。画像31にTile Painterのインターフェースを示します。

画像31。Tile Painterインターフェース。

Grid Helperスクリプトは非常にシンプルなGUIコントローラースクリプトをシーンにアタッチします。このスクリプトはキーボードの「mキー」を押すことによって行われるターントランジションに飲み関係しています。コードは次のようになります。

画像32。コード。

これでチュートリアルは終わりです。画像33は最後のステップの後のシーンセットアップです。
画像34はレベル(ステージ)を実行した時の状態です。作成されたシーンはプレイ可能ですが、特に面白いものではありません。それをカスタマイズするのはあなたです。

10.ライセンス

ライセンスについては翻訳も原文も掲載しますが、あくまでも原文の方に準拠していただければ幸いです。

Turn Based Strategy Framework is covered by the same license as all the other assets on Unity Asset Store. Please refer to https://unity3d.com/legal/as_terms for full text, I will
quote only relevant fragment here: “2.2.1 Non-Restricted Assets. The following concerns only Assets that are not Restricted Assets:
Licensor grants to the END-USER a non-exclusive, worldwide, and perpetual license to the Asset to integrate Assets only as incorporated and embedded components of electronic games and interactive media and distribute such electronic game and interactive media.
Except for game services software development kits (“Services SDKs”), END-USERS may modify Assets. END-USER may otherwise not reproduce, distribute, sublicense, rent, lease or lend the Assets. It is emphasized that the END-USERS shall not be entitled to distribute or transfer in any way (including, without, limitation by way of sublicense) the Assets in any
other way than as integrated components of electronic games and interactive media.
Without limitation of the foregoing it is emphasized that END-USER shall not be entitled to share the costs related to purchasing an Asset and then let any third party that has contributed to such purchase use such Asset (forum pooling).”

ターンベースストラテジーフレームワークは、Unityアセットストアの他のすべてのアセットと同じライセンスでカバーされています。全文は https://unity3d.com/legal/as_terms を参照してください。ここでは関連する部分のみを引用します: 「2.2.1 非制限アセット。ライセンサーは、エンドユーザーに対し、アセットを電子ゲームおよびインタラクティブメディアの組み込みコンポーネントおよび埋め込みコンポーネントとしてのみ統合し、当該電子ゲームおよびインタラクティブメディアを配布するための、アセットに対する非独占的、全世界的かつ永続的なライセンスを付与します。エンドユーザーは、本資産を複製、頒布、サブライセンス、レンタル、リースまたは貸与することはできません。エンド ユーザーは、電子ゲームおよびインタラクティブ メディアの統合コンポーネントとして以外の方法で、資産を配布または譲渡する権利(サブライセンスによる制限を含む)を有しないことが強調されます。"上記の制限なしに、エンド ユーザーは、資産の購入に関連する費用を分担し、当該購入に貢献した第三者に当該資産を使用させる権利(フォーラム プール)を有しないことが強調されます。

11.サポート

本フレームワークに関して何か質問があればcrook@outlook.comまで問い合わせください。開発者がサポートするUnityフォーラムぼスレッドはこちら(外部リンク)。
また、Discordサーバーもあるようですが、現在招待リンクが切れているため、後日正しいURLが分かりましたらそちらを貼ります。
Unityストアに本フレームワークがある限りはサポート対応いたします。

12.まとめ

このドキュメントでは本フレームワークを使って自分のゲームを作り始めるのに十分な説明をしました。もし、これで十分でなければコードとサンプルシーンのコメントを読んでみてください。コードについての意見や提案、新機能のアイディアなどフィードバックは上記のメールアドレスまでお知らせください。

13.参考文献

  1. References
    [1] Kenney, 1 bit pack, https://kenney.nl/assets/bit-pack
    [2] Kenney, Roguelike Characters, http://www.kenney.nl/assets/roguelike-characters
    [3] Kenney, Roguelike/RPG Pack, http://www.kenney.nl/assets/roguelike-rpg-pack
    [4] Kenney, Alien UFO Pack, http://www.kenney.nl/assets/alien-ufo-pack
    [5] Kenney, Hexagon Tiles, http://www.kenney.nl/assets/hexagon-tiles
    [6] Kenney, UI Pack, http://www.kenney.nl/assets/ui-pack
    [7] Kenney, Kenney Fonts, http://kenney.nl/assets/kenney-fonts
    [8] Kronbits, Backgrounds, https://kronbits.itch.io/backgrounds
    [9] Aekashics, Librarium Bundle, https://aekashics.itch.io/

この記事が気に入ったらサポートをしてみませんか?