ゲーム内の攻撃および攻撃タイプのプログラミング設計に関する洞察を探しています


14

そのため、2DスペースRTSに攻撃を導入し始めています(これはUnityに含まれているため、コンポーネント駆動型です)。当初は、「範囲内の敵、ダメージが与えられた」という単純なものでした。ただし、特定の船または構造物に関連付けられた複数の「タイプ」の武器/攻撃があります。損傷の種類など、過去の生の損傷だけでなく、将来の慣性も関係する他の要因と同様に。

各ユニットと構造タイプに独自の攻撃タイプがありますか?つまり、攻撃の種類、ダメージ、効果、範囲、パーティクル、スプライトなどを定義する各ユニット/構造のスクリプトを作成し、それをコンポーネントとして添付しますか?

または、攻撃タイプを定義するスクリプト、それに関連付けられた発射物タイプのスクリプトなどを作成します。次に、それらを拡張し、ユニットごとに変更して、各スクリプトをユニット/構造にアタッチします。


私はある程度意味があることを願っています、私はこれを長い間熟考してきたので、問題を解決するのか、それとも自分の問題を作り上げて穴に掘るのか分からない

特定のユニット/構造に限定される場合とそうでない場合がある多数の攻撃タイプを持つことができるゲームがある場合、コンポーネント駆動設計環境でそれを特定のユニット/構造に結び付けるフレームワークをどのように設計しますか?

これが十分に明確でない場合はお知らせください。

編集:素晴らしい答え、ありがとう。

拡張質問:

答えは、「各オブジェクトが独自の攻撃スクリプトを持つことができる」から「攻撃タイプを独自のスクリプトとして使用し、それを各オブジェクトに割り当ててより再利用可能なソリューションにする」までさまざまです。「ブラスター」攻撃があるとしましょう。それは特定の速度で赤い発射体を発射します。ダメージ、発射速度、および発射物のサイズは、発射するユニットに依存します。そのユニットの攻撃スクリプトを作成するだけの方が良いでしょうか、それとも、それを使用したい各ユニットの目的に合うように「ブラスター攻撃」を試して修正する方が良いでしょうか?


1
一般的なゲームプログラミングのアイデアについては、RPG FFVの完全な仕様を参照したいと思います-gamefaqs.com/snes/588331-final-fantasy-v/faqs/30040
Code Whisperer

回答:


12

正直なところ、私はこれに関する専門家ではありませんが...攻撃がどの程度複雑で多様であると思うかによります。RTSなので、10〜50個程度のユニットまたは構造があり、独自の攻撃タイプがあると思います。

オプション1:攻撃が多少似ているユニットが比較的少ない場合、すべてを1つの大きなスクリプトに入れ、インスペクターで使用するパラメーターを定義します。

オプション2:一方、異なる動作を伴う多数の攻撃タイプを想定している場合、各ユニットと建物が独自の攻撃スクリプトを取得できるようにすべてを分割できます。これを行うと、個々のスクリプトの多くが取得できる一般的に使用されるコードのチャンクを定義する「ヘルパー」スクリプトを作成する必要があると考えています。これにより、すべてを書き換える必要がなくなり、すべてがどこにあるかがわかります。

オプション3:おそらくすべきでないことは、ユニットの特定のグループがスクリプトを共有していることです。これは混乱を招く可能性があり、攻撃に必要なコードが10種類のスクリプトにある場合は混乱になります。

ここで、私はあなたに絵を描きました。

ここに画像の説明を入力してください


2
返信ありがとうございます。何らかの理由でオプション3に傾倒し始め、それを正当化する方法を見つけるのに苦労していました。おそらく2番目のルートに進みます。各ユニットは独自のカスタム攻撃スクリプトを取得し、各ユニット/建物のコンポーネントとして共通コードを攻撃することで共通コードを共有します。私がオプション3に導いた一連の思考でどこに行ったのか分かりません、ありがとう。私は場合にはAMに起床まで私がでチャイムにしたい他のポスターがあるオープンこれを残している。
ダグラスガスケル

問題ありません。決定的な答えではありませんが、役立つことを願っています。
ミール

1
同様の攻撃を1つの大きなスクリプトに入れて、異なる攻撃を分離することで1と2をハイブリッド化できます
ラチェットフリーク

4
#3が推奨されていることに驚いていますか?各ユニットが独自のタイプを定義する必要がないように、モジュラー/ジェネリッククラスのポイント全体ではありませんか?ゲームがRTSであり、Siegeダメージ(通常は「長距離」)がダメージタイプである場合、一度定義して、ダメージ計算を実行するときに複数の砲兵スタイルユニットがそれを参照するようにします。弱体化(リバランス)する必要があった場合、1つのクラスを更新するだけで済みますか?
HC_

1
"Here, I drew you a picture."ことを思い出し、この
FreeAsInBeer

4

私はUnityについてあまりよく知りませんし、ゲーム開発もしばらくしていないので、この質問に対する一般的なプログラミングの答えを教えてください。私は、エンティティがN個の多くのコンポーネントに関連付けられた数字であり、コンポーネントがデータのみを含み、システムが関連付けられたコンポーネントのセットで動作する、一般的なエンティティコンポーネントシステムに関する知識に基づいて答えを出しました。同じエンティティ。

あなたの問題空間はこれです:

  • ゲーム全体で敵を攻撃する方法は複数あります。
  • 各船、構造などには、複数の攻撃方法があります(それぞれが何らかの方法で決定されます)
  • 各攻撃には、独自のパーティクル効果があります。
  • 攻撃は、ターゲットやユーザーに存在するいくつかの要因(慣性や鎧など)を考慮しなければなりません。

ソリューションを次のように構成します。

  • 攻撃には識別子があります-これは文字列です。
  • エンティティは、(攻撃の識別子に基づいて)攻撃を使用できることを「知っています」。
  • エンティティが攻撃を使用すると、対応する表示コンポーネントがシーンに追加されます。
  • 攻撃のターゲット、攻撃者、使用されている攻撃について知っているロジックがあります-このロジックは、あなたがどれだけのダメージを与えるかを決定する必要があります(そして、慣性または両方のエンティティにアクセスできます)。

攻撃とエンティティ間の接点ができるだけ薄いことが重要です-これによりコードが再利用可能になり、同じタイプの攻撃を使用する異なるタイプのエンティティごとに重複コードを作成する必要がなくなります。言い換えれば、アイデアを提供するためのJavaScript擬似コードを次に示します。

// components
var bulletStrength = { strength: 50 };
var inertia = { inertia: 100 };
var target = { entityId: 0 };
var bullets = {};
var entity = entityManager.create([bulletStrength, inertia, target, bullets]);

var bulletSystem = function() {
  this.update = function(deltaTime, entityId) {
    var bulletStrength = this.getComponentForEntity('bulletStrength', entityId);
    var targetComponent = this.getComponentForEntity('target', entityId);
    // you may instead elect to have the target object contain properties for the target, rather than expose the entity id
    var target = this.getComponentForEntity('inertia', targetComponent.entityId);

    // do some calculations based on the target and the bullet strength to determine what damage to deal
    target.health -= ....;
  }
};

register(bulletSystem).for(entities.with(['bullets']));

申し訳ありませんが、この答えは少し「水っぽい」です。昼休みは30分しかありませんが、Unityについて完全に知らずに何かを考え出すのは難しいです:(


3

ユニット/構造/武器が攻撃するとき、私はおそらく攻撃者と防御者(または防御者)を連れて行く攻撃(あなたのすべての楽しい詳細でサブクラス化された)を作成するでしょう。その後、攻撃はターゲット/ディフェンダーと相互作用し(スロー、ポイズン、ダメージ、状態の変更)、自分自身を引き(ビーム、光線、弾丸)、完了したら自分自身を破棄します。複数のポイズン攻撃などの問題を予見できるため、ターゲットが攻撃と相互作用するダメージ可能なインターフェイスを実装する可能性がありますが、モジュラーで柔軟に変更できる実用的なアプローチだと思います。

拡張回答
これは、このアプローチでブラスター攻撃にアプローチする方法です。他の人に自分で答えさせます。

基本的な攻撃の統計/方法を使用して、IAttackerインターフェイスまたはクラスをユニットに実装します。IAttackerがIDamageableを攻撃すると、それ自体とそのターゲット(IAttackerとIDamageable、またはIDamageableのコレクション)を通過させる特定の攻撃を作成します。攻撃は、IAttackerから必要な統計情報を取得します(アップグレード時などの変更を避けるために、既に起動された後に攻撃の統計情報を変更しないようにします)。特殊な統計情報が必要な場合は、IAttackerをキャストしますその必要なタイプ(例:IBlasterAttacker)とその方法で特殊な統計を取得します。

このアプローチを採用すると、BlasterAttackerはBlasterAttackを作成するだけで済み、残りはBlasterAttackが処理します。BlasterAttackをサブクラス化するか、個別のFastBlasterAttacker、MegaBlasterAttacker、SniperBlasterAttackerなどを作成できます。それぞれの攻撃コードは同じです(BlasterAttackから継承される可能性があります)。 。


基本的に、ユニットはIAttackerインターフェースを継承し(既にこれを持っています)、「敵」用のIDamageableインターフェースがあります(これもあります)。攻撃者が攻撃すると、BlasterAttack(または派生クラス)が呼び出されます。この「攻撃」は、IAttackerから必要なデータを取得し、発射物がヒットしたときにIDamageableに適用しますか?発射物自体にBlasterAttackクラスが含まれているため、発射されるとIAttackerの変更による影響を受けなくなり、発射物が実際に衝突した場合にのみIDamageableにダメージ/効果を適用できます。
ダグラスガスケル

「BlasterAttack(または派生クラス)が呼び出された」と言うとき、私はBlasterAttackが作成されたと言います。BlasterAttackのこの新しく作成されたインスタンスは、ビーム(又は弾丸または光線または任意)を表すので、ある発射。BlasterAttackは、IAttackerおよびIDamageableオブジェクトから必要なすべての統計(位置、攻撃者の統計など)をコピーします。BlasterAttackは、自身の位置を追跡し、該当する場合、「接触」にダメージを適用します。目的地(ターゲットの古い位置)を逃した場合または到達した場合の対処方法を理解する必要があります。地面を燃やす?姿を消す?あなたの電話。
ricksmt

影響範囲の攻撃では、射程と射程の間で誰が射程と射程を変えることができるため、(敵)ユニットのグローバルコレクションにアクセスしたい場合があります。もちろん、BlasterAttackについても同様の議論を行うことができます。最初のターゲットを逃しますが、彼の後ろの男を攻撃します。私が唯一心配しているのは、多くの敵が攻撃するかどうか、また何がヒットするかを把握しようとする攻撃を何度も繰り返す可能性があることです。これはパフォーマンスの問題です。
ricksmt

ああ、それは理にかなっています。攻撃を逃した場合、発射物は事前に設定された範囲/ライフタイムを持ちます。そのライフタイムが終了する前に他の何かにヒットすると、衝突する剛体を所有するオブジェクトへの参照を受け取り、その方法でダメージが適用されます。実際、それはすべての発射体の動作方法であり、彼らは移動している「何」を知らず、ただ移動しているだけです(ミサイルのようなホーミングのような発射体を除く)。AEOエフェクトは、目的地でスフィアコライダーを有効にし、その内部にあるすべてのオブジェクトを取得できます。助けてくれてありがとう。
ダグラスガスケル

問題ない。喜んで。Unityがこれらすべての衝突を簡単にすることを忘れていました。
ricksmt
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.