慣性のある移動
コントローラーはQuakeやTitanfallの系譜です。毎フレーム速度を直接設定するのではなく、行きたい方向へ加速し、速度を奪うのは摩擦だけ。ジャンプしても速度が保たれるので、エアストレイフ、ウォールラン、スライドホップで速度を稼げます。
小さなステートマシン(接地、空中、ウォールラン、スライディング、よじ登り)がリジッドボディを管理し、カメラはコントローラーの信号に合わせて傾いたり視野角を変えたりします。中心となる計算は純粋関数なので、プレイモードの外でユニットテストできます。
// Only adds speed along the wish direction, and only up to
// wishSpeed along that axis. Total speed is never clamped,
// which is what makes air-strafing build speed.
public static Vector3 Accelerate(Vector3 vel, Vector3 wishDir,
float wishSpeed, float accel, float dt)
{
if (wishDir == Vector3.zero) return vel;
float current = Vector3.Dot(vel, wishDir);
float add = wishSpeed - current;
if (add <= 0f) return vel;
float accelSpeed = Mathf.Min(accel * wishSpeed * dt, add);
return vel + wishDir * accelSpeed;
}
ブロックを組み合わせて作る敵
ゲームジャムでは、デザイナーはプログラマーが書くより速く新しい敵を必要とします。そこで敵のコンポーネントは一つだけ。ターゲティングとアグロを担当し、それ以外はインスペクターのドロップダウンから選びます。移動(静止、地上追跡、浮遊追跡)を一つと、能力(射撃、自爆)をいくつでも。弾のパターン(単発、バースト、拡散、放射、ウェーブ、シーケンス)は差し替え可能なアセットです。
飛んでくる自爆兵も、らせん状に撃つ砲台も、ブロックの組み合わせが違うだけの同じコンポーネント。コードを一行も書かずに作れます。
public sealed class EnemyBrain : MonoBehaviour
{
public FloatReference AggroRange = new(14f);
[SerializeReference] // pick one from a dropdown
public EnemyMovement Movement = new GroundChaseMovement();
[SerializeReference] // stack as many as you like
public List<EnemyAbility> Abilities = new();
}
[Serializable]
public abstract class EnemyMovement
{
public abstract void Tick(in EnemyContext ctx);
}
Canozalez、Chaos-1001(アート)、Pierre-Henri Barralis(音楽・サウンド)と制作。