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

今回も下記を参考にやっていきましょう。
youtu.be

今回は、ゾンビがプレイヤーを探知する仕組みを作っていきます。

・ゾンビはプレイヤーが一定範囲内にいて、壁等の後ろにいない場合、つまりゾンビからプレイヤーが視認できる場合にプレイヤーを探知したことにします。

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

public class IdleState : State //EP8追加 ゾンビ直下のstatesオブジェクトにアタッチ
{
    PurseTargetState purseTargetState;

    //The layer used to detect potential attack taeget
    [Header("Detection Layer")]
    [SerializeField] LayerMask detectionLayer; //EP9追加

    //How far away can detect a target
    [Header("Detection Radius")]
    [SerializeField] float detectionRadius = 5f; //EP9追加

    //How wide can see a target within our FIELD OF VIEW
    [Header("Detection Angle Radius")]
    [SerializeField] float minimumDetectionRadiusAngle = -50f; //EP9追加
    [SerializeField] float maximumDetectionRadiusAngle = 50f; //EP9追加

    //we make our character idle until they find a potential target
    //if a target is found we proceed to the "PursueTarget" state
    //if no target is found we remain in the idle position

    private void Awake()
    {
        purseTargetState = GetComponent<PurseTargetState>();
    }


    public override State Tick(ZombieManager zombieManager)
    {
        //LOGIC TO FIND A TARGET GOES HERE.

        if (zombieManager.currentTarget!=null)//EP9変更
        {
           // Debug.Log("we have found a target!");
            return purseTargetState;
        }
        else
        {
            FindATargetViaLineOfSight(zombieManager); //EP9追加
           // Debug.Log("We have no target yet.");
            return this;
        }
        
    }

    //EP9追加
    private void FindATargetViaLineOfSight(ZombieManager zombieManager)
    {
        //We are searching ALL colliders on the layer of PLAYER within a certain radius
        //Physics.OverlapSphere戻り値: Collider[] 球体の内部や触れたすべてのコライダーの配列を取得します.
        Collider[] colliders = Physics.OverlapSphere(transform.position, detectionRadius, detectionLayer);
       // Debug.Log(colliders.Length);

        Debug.Log("we are checking for colliders");

        //For every collider that we find, that is on the same layer pf the player, we try and serch it for PlayerManager script
        for(int i = 0; i < colliders.Length; i++)
        {
            PlayerManager player = colliders[i].transform.GetComponent<PlayerManager>();

            //If rhe playerManager is detected, we then check for line of sight
            if (player != null)
            {
                Debug.Log("we have found the player collider");

                //The target mudt be infront of us
                Vector3 targetDirection = transform.position - player.transform.position;
                float viewableAngle = Vector3.Angle(targetDirection, transform.forward);
              //  Debug.Log("VIEWABLE ANGLE=" + viewableAngle);

                if(viewableAngle>minimumDetectionRadiusAngle && viewableAngle < maximumDetectionRadiusAngle) 
                {
                    Debug.Log("we have passed the field of view check");

                    RaycastHit hit;
                    //This just makes it so our raycast does not start from the floor
                    float characterHeight = 2f;
                    Vector3 playerStartPoint = new Vector3(player.transform.position.x, characterHeight, player.transform.position.z);
                    Vector3 zombieStartPoint = new Vector3(transform.position.x, characterHeight, transform.position.z);

                    Debug.DrawLine(playerStartPoint, zombieStartPoint,Color.yellow);

                    //CHECK ONE LAST TIME OUR
                    //Linecast:始点と終点を設定してそこに線を張り、コライダーがヒットした場合 true を返します.
                    if (Physics.Linecast(playerStartPoint,zombieStartPoint,out hit))
                    {
                        Debug.Log("There is something iin the way");
                        //Cannot find the target, there is an object in the way
                                            }
                    else
                    {
                        Debug.Log("We have a target, switching states");
                        zombieManager.currentTarget = player;
                    }
                }
            }
        }
    }
}

今回は以上です。