【Unity】追跡と発砲をするFPSの敵キャラ作ってみた

unity

FPSで追いかけてて発砲してくる敵キャラを作ってみました。

無料のアセットだけを使って実装しました。

アセットはToon Soldiers Demoというのを使っています。

https://assetstore.unity.com/packages/3d/characters/toon-soldiers-demo-69684

このアセットを使って似たようなFPSゲーの敵キャラを使った動画があったのですが、

有料のアセット(UFPS?)に含まれるスクリプトが必要だったりして、再現できない感じだったので自分で作りました。

作り方はシンプルで、以下の通りです。

  1. 追跡用コライダ内に入ったら追いかける
  2. 射程用コライダ内に入ったら撃つ
  3. ダメージ判定用コライダ内に入ったらダメージを与える

というふうにしています。

コライダを3つ用意してそれぞれで処理を分けて実装しました。

それぞれのコードは以下の通りです。

追いかける

    // プレイヤーの位置を追跡します。
    public void onDetectObject(Collider collider)
    {
        if (!_status.IsMovable)
        {
            _agent.isStopped = true;
            return;
        }

        if (collider.CompareTag("Player"))
        {
            _agent.isStopped = false;
            _agent.destination = collider.transform.position;
        }

    }

このコードはonTriggerStayの中で呼び出しています。(追跡用コライダのisTriggerはチェックを入れています。)

プレイヤーが追跡用コライダの中に入ったら上記のコードで追いかけるようにしています。

Window→AI→Navigationでベイクして追いかけるルートを計算しておきましょう。

発砲する

射程用コライダはプレイヤーが射程圏内にいるかどうか判別するためのコライダです。

    public void OnAttackRangeEnter(Collider collider)
    {

        if (collider.CompareTag("Player"))
        {

            var positionDiff = collider.transform.position - transform.position;
            var distance = positionDiff.magnitude;
            var direction = positionDiff.normalized;

            var hitCount = Physics.RaycastNonAlloc(transform.position, direction, _raycastHits, distance, raycastLayerMask);

            // プレイヤーとの間に障害物がないかチェックする。
            if (hitCount == 0)
            {
                if (!_status.IsAttackable) return; // ステータスと衝突したオブジェクトで攻撃可否を判断

                _status.GoToAttackStateIfPossible();

                //プレイヤーの方向を向く(y軸)
                Vector3 target = collider.transform.position;
                target.y = this.transform.position.y;
                this.transform.LookAt(target);
            }
        }

    }

このコードもonTriggerStayの中で呼び出しています。

追跡用コライダのisTriggerはチェックを入れています。

追いかける時とは違い、レイキャストを飛ばして、障害物がない時だけ、発砲しています。

敵が壁などの障害物があるのに発砲してきたら、強すぎ&怖すぎですからね。

ダメージを与える

ダメージ判定用コライダは、発砲開始時にオンして終わったらオフにしておきます。

コライダのオン・オフを切り替えるにはアニメーションで設定します。

ソルジャーのアセットに、assult_combat_shootが含まれていますので、CTRL + D で複製して_customをつけて名前を変更し、編集可能な状態にします。

OnAttackStart,OnAttackFinishをそれぞれアニメの開始、終了時にセットしました。

    public void OnAttackStart()
    {
        attackCollider.enabled = true;
    }

    public void OnHitAttack(Collider collider)
    {
        var player = collider.GetComponent<PlayerStatus>();
        if (null == player) return;

        player.Damage(1);
    }

    public void OnAttackFinished()
    {
        attackCollider.enabled = false;
        StartCoroutine(CooldownCoroutine());
    }

ダメージ判定用コライダのonTriggerEnterの中でOnHitAttackを呼び出します。

OnTriggerEnterはコライダに入った時の一回のみしか呼ばれませんので、連続してダメージを与えてしまうことはありません。

参考

作って学べる Unity本格入門 (日本語) 単行本(ソフトカバー) – 2020/1/22

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog