2

私は現在、いくつかのゲームを作るために団結して働いています。私はC#を使用しています。私は通常、ゲームのコードに満足しており、いわば「エレガント」にする方法を知っています。私は個々の要素のコーディングが非常に得意です(たとえば、小惑星の宇宙船)。しかし、あるオブジェクトが別のオブジェクトと相互作用する必要があるポイントに到達するまで、コードに満足しているだけです。それはその時点以降のコードのスパゲッティになり、私は常にプロジェクトをドロップします。私は物事を処理する優雅な方法をまだ見つけていません。インターネットのあちこちで聞いたことがあると思いますが、これからも戻ってきそうです。

オブジェクト間の相互作用を処理する一般的な方法はありますか?ハッキーを感じないものはありますか?この問題は、私の最新のプロジェクトで再び発生しました。これはUnityプロジェクトであり、2D横スクロールです。キャラクターで「スパイク」をヒットしたかどうかを検出するには、衝突オブジェクトタグをチェックし、それが「スパイク」であるかどうかを確認する必要があります。しかし、私の「死」コードはすべて、スパイクではなく、プレーヤー内に含まれています。スパイクは、実際にはタグ付きのメッシュコライダー以外のものではありません。そしてこれは間違っていると感じます。

では、stackoverflowで、これをどのように処理しますか?

4

3 に答える 3

3

それは通常、大きなプロジェクトに起こることです。彼らは非常に素晴らしく始まり、大きなモンスターになってしまいます。オブジェクト指向アプリケーションを作成するときに興味深いと思ったいくつかの便利な原則を次に示します。

  1. ドメイン図からクラス図まで掘り下げて、トップダウン方式でOOAD分析を実行します
  2. アプリケーションは常にレイヤー(ユーティリティ、データアクセス、ビジネスオブジェクト、UI ...)に分割してください
  3. そして最も重要なことは、GRASPパターンを実装して、オブジェクトが適切な責任を持ち、自然な方法で相互作用し、高度に結合されていないことを確認することです。
于 2012-07-04T06:28:07.700 に答える
3

常に検討するのが良いデザインパターンに加えて、
タグを使用する代わりに、そのようなもののためにコンポーネントを作成することをお勧めします。これらはUnity3dのコアコンセプトの1つであり、より再利用可能です。

たとえば、タイプDamageVolumeなどの新しいコンポーネントを作成できます。それはそれをより一般的にし、あなたはあなたのプレーヤーに損害を与える他のもののためにそれを再利用することができます。InstantKillまた、、DamageType(プレイヤーがどのように死ぬか、どのエフェクトをプレイするかを決定できるようにする)や。などのプロパティを使用して構成することもできますDamageAmount。プレーヤーの衝突イベントでは、次のようなことを行うことができます。

var damager = collision.gameobject.GetComponent<DamageVolume>();
if (damager != null) {
    if (damager.InstantKill) {
        this.Kill(damager.DamageType);
    }
    else {
        this.Damage(damager.DamageAmount, damager.DamageType);
    }
}
于 2012-07-04T07:28:33.850 に答える
2

Johnn Bladeが質問にコメントを残したように、オブザーバーパターンを使用することは、アプリケーションのさまざまな部分の間で状態の変化を伝達するための優れたアプローチです。

具体的な例として、プレーヤーの動きを、アプリケーションの他の部分で観察できるいくつかの個別のステップ(またはイベント)に分割できる場合があります。

たとえば、プレーヤーに次のイベントを追加した場合:

  • BeforeMove(Coordinate oldCoordinate、Coordinate newCoordinate、out bool canMove)
  • 移動(座標oldCoordinate、座標newCoordinate)
  • HealthChanged(int newHealth)

また、シーン内の他のオブジェクトには、次のようなイベントが含まれる場合があります。

  • DamagePlayer(intdamage)
  • HealPlayer(int heal)

プレーヤーを移動しようとすると、BeforeMovedイベントがトリガーされます。何も応答しない場合canMove = false(ドアがロックされているなど)、移動は許可されます。次に、プレーヤーの位置を更新し、移動を呼び出します。

したがって、スパイクはプレーヤーの移動イベントをリッスンする可能性があります。

void Moved(Coordinate oldCoordinate, Coordinate newCoordinate) 
{ 
  if (newCoordinate.Intersects(this.Location))
  {
    DamagePlayer(50); 
  }
} 

これに対応して、プレーヤーはDamagePlayerイベントをリッスンします。

void DamagePlayer(int damage)
 {
    this.Health -= damage;
    HealthChanged(this.Health);  
 }

何か(おそらくプレーヤー自体)がHealthChangedイベントをリッスンし、それがゼロ以下に達すると、プレーヤーを強制終了します。

このパターンを使用すると、落下の検出などの新しい機能を追加するのは比較的簡単です。Movedイベントの新しいオブザーバーを作成するだけです。

void Moved(Coordinate oldCoordinate, Coordinate newCoordinate) 
{ 
  decimal deltaY = oldCoordinate.Y - newCoordinate.Y; 
  if (deltaY  < -100) // If fell 100 units or more, take 10 damage per unit. 
  {
    DamagePlayer(10 * Math.Abs(deltaY)); 
  }
} 
于 2012-07-04T06:55:27.300 に答える