【バイオハザード風のゲームを作ってみよう。その11】

今回も下記動画を参考にやっていきます。
youtu.be

今回はダメージを受けた時のゾンビの動作を追加していきます。

・ゾンビが当たり判定可能なようにCapsule Colliderを付けていきます。

・ゾンビアニメーターコントローラーにoverrideレイヤーを追加し、被弾時のアクションを設定します。
私は、mixamoの「Zombie Reaction Hit」を使用しました。
なお、動画内では頭部と体でアニメーションは異なりますが、mixamoに適当なアニメーションが無かったので、私は前述のアニメーションのスピードを変更して頭部と体それぞれの被弾時のアニメーションに対応させました。


・ゾンビは被弾時に動きを止めるようにします。

public class ZombieManager : MonoBehaviour //EP8追加 ゾンビオブジェクトにアタッチ
{
   (省略)
    [Header("Flags")]
    public bool isPerformingAction; //EP11追加
}
public class AttackState : State //EP10追加 ゾンビ直下のstatesオブジェクトにアタッチ
{
    public override State Tick(ZombieManager zombieManager)
    {
        //if the zombie is being hurt, or is in some action, pause the state
        if (zombieManager.isPerformingAction) //EP11追加
        {
            zombieManager.animator.SetFloat("Vertical", 0f, 0.2f, Time.deltaTime);
            return this;
        }

        //Debug.Log("ATTACK");
        //Idleアニメーションに切り替え
        zombieManager.animator.SetFloat("Vertical", 0f, 0.2f, Time.deltaTime);
        return this;
}
public class PurseTargetState : State //EP8追加 ゾンビ直下のstatesオブジェクトにアタッチ
{
    AttackState attackState; //EP10追加

    private void Awake()
    {
        attackState = GetComponent<AttackState>(); //EP10追加
    }

    public override State Tick(ZombieManager zombieManager)
    {
        //if the zombie is being hurt, or is in some action, pause the state
        if (zombieManager.isPerformingAction) //EP11追加
        {
            zombieManager.animator.SetFloat("Vertical", 0f, 0.2f, Time.deltaTime);
            return this;
        }

 Debug.Log("Running pursue target state");
        MoveTowardsCurrentTarget(zombieManager); //EP10追加
        RotateTowardsTarget(zombieManager); //EP10追加
}


・被弾時のアニメーション終了(=false)を変数:isPerformingActionに設定します。 ゾンビアニメータのoverrideレイヤーEmptyに下記スクリプトをアタッチ。

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

public class ResetAnimatorBoolZombie : StateMachineBehaviour //EP11追加 ゾンビアニメータのoverrideレイヤーEmptyにアタッチ
{
    // OnStateEnter is called when a transition starts and the state machine starts to evaluate this state
    override public void OnStateEnter(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
    {
        ZombieManager zombie = animator.GetComponent<ZombieManager>();

        if (zombie != null)
        {
            zombie.isPerformingAction = false;
        }
    }
}

・被弾時にアニメーションを動作させます。

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

public class ZombieEffectManager : MonoBehaviour //EP11追加 ゾンビにアタッチ
{
    ZombieManager zombie;

    private void Awake()
    {
        zombie = GetComponent<ZombieManager>();
    }

    public void DamageZombieHead()
    {
        //We ALWAYS stagger for a headshot
        //Play proper animation depending on where zombie is shot from
        //Ex, if zombie is shot from behind, the head should move forward
        //if the zombie is shot from the front,the head should move back
        //Play blend/FX at the contact point of the bullet
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_head", 0.2f);
    }

    public void DamageZombieTorso()
    {
        //STAGGER DEPENDING ON WEAPONS POWER
        //Play proper animation depending on where zombie is shot from
        //Play blend/FX at the contact point of the bullet
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_Torso", 0.2f);
    }

    public void DamageZombieRightArm()
    {
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_Torso", 0.2f);
    }

    public void DamageZombieLeftArm()
    {
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_Torso", 0.2f);
    }

    public void DamageZombieRightLeg()
    {
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_Torso", 0.2f);
    }

    public void DamageZombieLeftLeg()
    {
        zombie.isPerformingAction = true;
        zombie.animator.CrossFade("Zombie Reaction Hit_Torso", 0.2f);
    }
}
public class WeaponAnimatorManager : MonoBehaviour //EP7追加 武器にアタッチ
{
    Animator weaponAnimator;

    [Header("weapon FX")]
    public GameObject weaponMuzzleFlashFX; //The muzzle flash FX that is instantiated when the weapon is fired.
    public GameObject weaponBulletCaseFX; //The bullet case FX that is ejected from the weapon, when the weapon is fired.

    [Header("weapon FX Transform")]
    public Transform weaponMuzzleFlashTransform; //The location the muzzle flash FX will instantiate
    public Transform weaponBulletCaseTransform; //The location the bullet case will instantiate

    [Header("Weapon Bullet Range")]
    public float bulletRange = 100f; //EP11追加

    [Header("Shootable Layers")]
    public LayerMask shootableLayers; //EP11追加

    private void Awake()
    {
        weaponAnimator = GetComponentInChildren<Animator>();
    }

    public void ShootWeapon(PlayerCamera playerCamera)
    {
        //ANIMATE THE WEAPON
        weaponAnimator.Play("Shoot");

        //INSTANTIATE MUZZLE FLASH FX
        GameObject muzzleFlash = Instantiate(weaponMuzzleFlashFX.gameObject, weaponMuzzleFlashTransform);
        muzzleFlash.transform.parent = null;


        //INSTANTIATE EMPTY BULLET CASE
        //  GameObject bulletCase = Instantiate(weaponBulletCaseFX, weaponBulletCaseTransform);
        //  bulletCase.transform.parent = null;

        //SHOOT SOMETHING
        // public static bool Raycast(Vector3 origin, Vector3 direction, out RaycastHit hitInfo)
        // origin:ワールド座標でのレイの開始地点, direction:レイの方向, hitInfo:衝突した相手オブジェクトの情報
        RaycastHit hit;
        if(Physics.Raycast(playerCamera.cameraObject.transform.position, playerCamera.cameraObject.transform.forward,out hit,
            bulletRange,shootableLayers)) //EP11追加
        {
            Debug.Log(hit.collider.gameObject.layer); //EP11変更

            ZombieEffectManager zombie = hit.collider.gameObject.GetComponentInParent<ZombieEffectManager>(); //EP11追加

            //EP11追加
            if (zombie != null)
            {
                if (hit.collider.gameObject.layer == 8)
                {
                    zombie.DamageZombieHead();
                }
                else if (hit.collider.gameObject.layer == 9)
                {
                   zombie.DamageZombieTorso();
                }
                else if (hit.collider.gameObject.layer == 10)
                {
                    zombie.DamageZombieRightArm();
                }
                else if (hit.collider.gameObject.layer == 11)
                {
                    zombie.DamageZombieLeftArm();
                }
                else if (hit.collider.gameObject.layer == 12)
                {
                    zombie.DamageZombieRightLeg();
                }
                else if (hit.collider.gameObject.layer == 13)
                {
                    zombie.DamageZombieLeftLeg();
                }
            }
        }
    }
}

プレイするとこんな感じです。
youtu.be

今回は以上です。