【バイオハザード風のゲームを作ってみよう。その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
今回は以上です。