UnityでFPSゲームを作ってみました その2

今回はUnityでFPSゲームを作成してみました。完成したゲームはこちらです。https://ma510884.com/FPS_Game

その1はこちらです

参考にした記事、使用したアセットは以下になります。

では続いて敵キャラクターを作成していきます。記事にならってZombieをインポートし、Prefabの中のZombie01オブジェクトをHierarchyにドラッグ&ドロップします。

次にAnimator Controllerを新たに作成します。初期状態では3つステートが表示されていますので、他に必要なものを追加していきます。

Z_Idleをデフォルトのステートにしますので最初にドラッグ&ドロップし、続いてZ_Walk、Z_Attack、Z_FallingBackと追加していきます。そしてそれらを図のように繋ぎます。

繋いだ矢印をクリックし、InspecterでHas Exit Time(終了時間)とConditionsを設定します。設定が終わったらZombie01のControllerを今作成したものに変更します。

続いてRigidbodyとBox Colliderを追加し、記事のように数値を設定します。同様に、ナビメッシュのベイクも行います。地面をまとめて選択し(ShiftキーまたはCtrlキーを押しながら、もしくはHierarchyから選択できます)、ベイクすると道路が青くなると思います。

次にスクリプトをアタッチします。この際、スクリプトを少し書き換えて一緒にゾンビの声も追加します。ゾンビの声はYouTubeクリエイターキットのフリー素材を使用しました。また、1種類だけではゲームが単調になってしまいますので、ゾンビのPrefabをコピーし、ターゲットをプレイヤーではなくゲームオーバー地点に変更した物も用意しました。 やり方は後述するゲームオーバー地点にタグを設定し、ゾンビのターゲットをその地点に変更するだけです。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;

[RequireComponent(typeof(Animator))]
[RequireComponent(typeof(Rigidbody))]
[RequireComponent(typeof(NavMeshAgent))]
public class EnemyController : MonoBehaviour
{

    public bool moveEnabled = true;

    [SerializeField]
    int maxHp = 3;
    [SerializeField]
    int ammoDamage = 5;
    [SerializeField]
    int attackInterval = 1;
    [SerializeField]
    int score = 100;
    [SerializeField]
    string targetTag = "Player";
    [SerializeField]
    float deadTime = 3;

    bool attacking = false;
    int hp;
    float moveSpeed;
    Animator animator;
    BoxCollider boxCollider;
    Rigidbody rigidBody;
    NavMeshAgent agent;
    Transform target;
    GameManager gameManager;
    FirstPersonGunController player;
    private AudioSource audioSource;

    public int Hp
    {
        set
        {
            hp = Mathf.Clamp(value, 0, maxHp);

            if (hp <= 0)
            {
                StartCoroutine(Dead());
            }
        }
        get
        {
            return hp;
        }
    }

    void Start()
    {
        animator = GetComponent<Animator>();
        boxCollider = GetComponent<BoxCollider>();
        rigidBody = GetComponent<Rigidbody>();
        agent = GetComponent<NavMeshAgent>();

        target = GameObject.FindGameObjectWithTag(targetTag).transform;
        gameManager = GameObject.FindGameObjectWithTag("GameController").GetComponent<GameManager>();
        player = GameObject.FindGameObjectWithTag("Player").GetComponentInChildren<FirstPersonGunController>();

        InitCharacter();
        audioSource = GetComponent<AudioSource>();
    }

    void Update()
    {
        if (moveEnabled)
        {
            Move();
            audioSource.Play();
        }
        else
        {
            Stop();
        }
    }

    void InitCharacter()
    {
        Hp = maxHp;
        moveSpeed = agent.speed;
    }

    void Move()
    {
        agent.speed = moveSpeed;
        animator.SetFloat("Speed", agent.speed, 0.1f, Time.deltaTime);

        agent.SetDestination(target.position);
        rigidBody.velocity = agent.desiredVelocity;
    }

    void Stop()
    {
        agent.speed = 0;
        animator.SetFloat("Speed", agent.speed, 0.1f, Time.deltaTime);
    }

    IEnumerator Dead()
    {
        moveEnabled = false;
        Stop();
        gameManager.Score += score;
        animator.SetTrigger("Dead");
        boxCollider.enabled = false;
        rigidBody.isKinematic = true;
        yield return new WaitForSeconds(deadTime);
        Destroy(gameObject);
    }

    private void OnCollisionEnter(Collision collision)
    {
        if (collision.gameObject.tag == "Player")
        {
            StartCoroutine(AttackTimer());
        }
    }

    IEnumerator AttackTimer()
    {
        if (!attacking)
        {
            attacking = true;
            moveEnabled = false;

            animator.SetTrigger("Attack");
            player.Ammo -= ammoDamage;
            yield return new WaitForSeconds(attackInterval);

            attacking = false;
            moveEnabled = true;
        }

        yield return null;
    }
}

では次の記事にならって敵生成オブジェクトとスクリプトを追加します。1ヶ所では物足りなかったので、車の陰にそれぞれ配置し2ヶ所としました。

次はゲームシステムと効果音を追加していきます。

その3に続きます

  • 2
  • 0
  • 1

おすすめのタグ

Laffey(ラフェィ)

色々な物・もの・モノを作って記事にしています

作者のページを見る

関連記事

寄付について

「novalue」は、‟一人ひとりが自分らしく働ける社会”の実現を目指す、
就労継続支援B型事業所manabyCREATORSが運営するWebメディアです。

当メディアの運営は、活動に賛同してくださる寄付者様の協賛によって成り立っており、
広告記事の掲載先をお探しの企業様や寄付者様を随時、募集しております。

寄付についてのご案内