Unityでゾンビゲームを作る #4 アニメーションをスクリプトで制御する

投稿者: | 2020-01-13

頭以外の部分を撃たれた時に、立ち止まってゾンビのアニメーションを変更します。

アニメーターコントローラーをみると、歩くアニメーションと他のアニメーションのステートが同じレイヤーで管理されています。

整数型のパラメータがあり、「animBaseInt」が1~9だと左側のステートに遷移して、「animOtherInt」が1だと右側の歩いているステートに移ります。

例えば、左側の2番めの「Idle_angry」というステートへの遷移の矢印を選択してみます。

インスペクタを見ると、「animBaseInt」が2のときに遷移するようになっています。

このステートから元のステートに戻る矢印を確認します。

遷移の条件を見ると、同じパラメータが2でないときには戻ることがわかります。

ゾンビはデフォルトで歩いている状態からスタートさせているので、animOtherIntだけが1になっています。

同じレイヤーで管理されているので、このままanimBaseIntを変えても、左側のステートには遷移しません。その前にanimOtherIntを0にする必要があります。

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

public class ZombieScript : MonoBehaviour
{
    public GameObject player;
    NavMeshAgent agent;

    public bool stopZombie = false;
    public bool RestartWalkingOn = false;

    Animator animator;

    // Start is called before the first frame update
    void Start()
    {
        agent = GetComponent<NavMeshAgent>();
        animator = GetComponent<Animator>();
    }

    // Update is called once per frame
    void Update()
    {
        if (!RestartWalkingOn)
        {
            if (stopZombie)
            {
                RestartWalkingOn = true;
                //agent.speed = 0f; // ゾンビの動きを止める
                agent.isStopped = true; // ゾンビの動きを止める
                Invoke("RestartWalking", 2); // 2秒後に再び歩きはじめる
                animator.SetInteger("animOtherInt", 0); // 歩いている状態を解除
                animator.SetInteger("animBaseInt", 2); // 撃たれたときの状態に遷移
            }
            else
            {
                agent.destination = player.transform.position;
            }
        }
    }

    void RestartWalking()
    {
        //agent.speed = 3.5f; // ゾンビを再び歩かせる
        agent.isStopped = false; // ゾンビを再び歩かせる

        RestartWalkingOn = false;
        stopZombie = false;

        animator.SetInteger("animBaseInt", 0); // 撃たれたときの状態を解除
        animator.SetInteger("animOtherInt", 1); // 歩いている状態に遷移

    }
}

ゾンビに付けたスクリプトで、ゾンビの頭以外が撃たれてstopZombieがtrueになると、ゾンビが立ち止まって、animOtherIntを0にしてからanimBaseIntを2にしています。

そして、再度ゾンビを歩かせるときは、animBaseIntを0にしてからanimOtherIntを1に戻します。再度ゾンビを歩かせる関数をInvoke()を使って、ゾンビを立ち止まらせた2秒後に実行しています。

Idle_angtyステートでのアニメーションはループするようになっています。

また、遷移の矢印のHas Exit Time(時間による遷移の条件)がオフになっていて、Transition Duration(遷移にかかる時間)が0になっているので、スクリプトから瞬時にアニメーションを制御できます。

stopZombieをtureにするのは、銃弾に付けたスクリプトで行っています。

private void OnCollisionEnter(Collision collision)
{

    if (collision.gameObject.tag == "Agent") // ゾンビの頭以外に銃弾が当たった時
    {
        GameObject parent = collision.gameObject.transform.root.gameObject; // 階層の一番上のオブジェクト
        ZombieScript sc_zombie = parent.GetComponent<ZombieScript>();

        sc_zombie.stopZombie = true;

    }
    else if (collision.gameObject.tag == "AgentHead") // ゾンビの頭にあたった時
    {

        GameObject parent = collision.gameObject.transform.root.gameObject; // 階層の一番上のオブジェクト

        // 撃たれたゾンビと同じ場所にラグドールを生成
        GameObject ragdollIns = Instantiate(GunScript.girlRagdoll, parent.transform.position, parent.transform.rotation); 
        ragdollIns.GetComponent<ragDollScript>().impact = -collision.impulse; // ラグドールに力を伝える
        Destroy(parent); // 撃たれたゾンビを削除

    }

    Destroy(gameObject); // 銃弾を削除

}

タグによって、頭と頭以外が撃たれたときの処理を分けています。

コメントを残す

メールアドレスが公開されることはありません。