VR開發(fā)實(shí)戰(zhàn)HTC Vive項(xiàng)目之星球大戰(zhàn)

一、框架視圖

二宋彼、主要代碼

Indoor

AnimatorSetup

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

public class AnimatorSetup  {
    public float speedDampTime=0.1f;  //緩沖時(shí)間
    public float angularSpeedDampTime = 0.7f;
    public float angleResponseTime = 1f;
    private Animator anim;
    private HashIDs hash;

    /// <summary>
    /// 構(gòu)造函數(shù)
    /// </summary>
    public  AnimatorSetup(Animator anim,HashIDs hash) {
        this.anim = anim;
        this.hash = hash;
    }


    public void Setup(float speed, float angle) {
        float angularSpeed = angle / angleResponseTime;
        anim.SetFloat(hash.speedFloat,speed,speedDampTime,Time.deltaTime);
        anim.SetFloat(hash.angularSpeedFloat,angularSpeed,angularSpeedDampTime,Time.deltaTime);
    }
}

FadeInOut

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
/// <summary>
/// 屏幕淡入淡出效果
/// </summary>
public class FadeInOut : MonoBehaviour {

    public  float fadeSpeed=0.2f;
    private bool sceneStarting = true;
     //private GUITexture tex;
    private RawImage tex;
    void Start () {

        //tex = this.GetComponent<GUITexture>();
        tex = this.GetComponent<RawImage>();
        //tex.pixelInset = new Rect(0,0,Screen.width,Screen.height);
    }
    void Update () {
        if (sceneStarting)
        {
            StartScene();
        }
    }

    //漸入
    private void FadeToClear() {

        tex.color = Color.Lerp(tex.color,Color.clear,fadeSpeed*Time.deltaTime);

    }

    //漸出
    private void FadeToBlack() {

        tex.color = Color.Lerp(tex.color,Color.black,fadeSpeed*Time.deltaTime);
    }

    /// <summary>
    /// 進(jìn)入場(chǎng)景
    /// </summary>
    public void StartScene() {

        FadeToClear();
        if (tex.color.a<=0.05f)
        {
            tex.color = Color.clear;
            //tex.enabled = false;
            sceneStarting = false;
        }
    }


    /// <summary>
    /// 結(jié)束場(chǎng)景
    /// </summary>
    public void EndScene() {
      
        sceneStarting = true;
        FadeToBlack();
        if (tex.color.a>=0.95f)
        {
            //SceneManager.LoadScene("Indoor");
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

        }
    }


    /// <summary>
    /// 進(jìn)入下一個(gè)場(chǎng)景
    /// </summary>
    public void NextScene() {
        sceneStarting = true;
        FadeToBlack();
        if (tex.color.a >= 0.95f)
        {
            SceneManager.LoadScene("Outdoor");
        }
    }
}

fps_Crosshair

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

/// <summary>
/// 武器設(shè)置以及準(zhǔn)星繪制
/// </summary>
public class fps_Crosshair : MonoBehaviour {


    public float length;
    public float width;
    public float distance;
    public Texture2D crosshairTexture;



    public GUIStyle lineStyle;
    private Texture tex;

    void Start () {

        lineStyle = new GUIStyle();
        lineStyle.normal.background = crosshairTexture;
    }
    
    
    void Update () {
        
    }


    /// <summary>
    /// 繪制準(zhǔn)星
    /// </summary>
    void OnGUI() {

        GUI.Box(new Rect((Screen.width-distance)/2-length,(Screen.height-width)/2,length,width),tex,lineStyle);
        GUI.Box(new Rect((Screen.width+distance)/2,(Screen.height-width)/2,length,width),tex,lineStyle);
        GUI.Box(new Rect((Screen.width-width)/2,(Screen.height-distance)/2 - length, width,length),tex,lineStyle);
        GUI.Box(new Rect((Screen.width- width) /2,(Screen.height+distance)/2, width,length),tex,lineStyle);

    }

}

fps_DoorControl

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

/// <summary>
/// 靜態(tài)滑動(dòng)門設(shè)置-1
/// </summary>
public class fps_DoorControl : MonoBehaviour {

    public int doorId;  //門的id號(hào)
    public Vector3 from; //原始位置
    public Vector3 to;//滑動(dòng)位置
    public float fadeSpeed=5; //滑動(dòng)速度
    public bool requireKey = false; //通過鑰匙打開
    public AudioClip doorSwitchClip; //開門聲效
    public AudioClip accessDeniedClip; //進(jìn)入聲效


    private Transform door; //獲取門
    private GameObject player;  //玩家
    private AudioSource audioSource; //聲效
    private fps_PlayerInventory playerInventory;  
    private int count;
    public int Count {
        get { return count; }
        set {
            if (count == 0 && value == 1 || count == 1 && value == 0)
            {
                audioSource.clip = doorSwitchClip;
                audioSource.Play();
            }
            count = value;
        }
    }


    void Start() {

        if (transform.childCount > 0)
        {
            door = transform.GetChild(0);
        }
        player = GameObject.FindGameObjectWithTag(Tags.player);
        audioSource = this.GetComponent<AudioSource>();
        playerInventory = player.GetComponent<fps_PlayerInventory>();
        door.localPosition = from;
    }


    void Update() {

        if (Count>0)
        {
            door.localPosition = Vector3.Lerp(door.localPosition, to, fadeSpeed * Time.deltaTime);
           // Debug.Log("Count++" + Count);
        }
        else
        {
            door.localPosition = Vector3.Lerp(door.localPosition, from, fadeSpeed * Time.deltaTime);
        }


    }


    /// <summary>
    /// 進(jìn)入觸發(fā)器
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {

        Debug.Log("進(jìn)入門的觸發(fā)器");

        if (other.gameObject == player)
        {
            if (requireKey)
            {

                if (playerInventory.HasKey(doorId))
                {
                    Count++;
                }
                else
                {
                    audioSource.clip = accessDeniedClip;
                    audioSource.Play();
                }
            }
            else
            {
                Count++;
            }
        }
        else if (other.gameObject.tag == Tags.enemy && other is CapsuleCollider)
        {
            Count++;
        }

     
    }

    /// <summary>
    /// 離開觸發(fā)器
    /// </summary>
    void OnTriggerExit(Collider other) {

        Debug.Log("離開門的觸發(fā)器");
        if (other.gameObject == player||other.gameObject.tag==Tags.enemy&&other is CapsuleCollider)
        {
            Count = Mathf.Max(0,Count-1);
        }
    }


}

fps_EnemyAI

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

public class fps_EnemyAI : MonoBehaviour {

    public float patrolSpeed = 2f; //巡邏時(shí)間
    public float chaseSpeed = 5f;   //追擊時(shí)間
    public float chaseWaitTime = 5f;
    public float patrolWaitTime = 1f;
    public Transform[] patrolWayPoint;//尋路點(diǎn)

    private fps_EnemySight enemySight;
    private NavMeshAgent nav;
    private Transform player;
    private fps_PlayerHealth playHealth ; //玩家血量  
    private float chaseTimer;
    private float patrolTimer;
    private int wayPointIndex;

    void Start() {

        enemySight = this.GetComponent<fps_EnemySight>();
        nav = this.GetComponent<NavMeshAgent>();
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        playHealth = player.GetComponent<fps_PlayerHealth>();

    }


    void Update() {

        if (enemySight.playerInSight && playHealth.hp > 0)
        {
            Shooting();
        }
        else if (enemySight.playerPosition != enemySight.resetPosition && playHealth.hp > 0)
        {
            Chasing();
        }
        else
        {
            Patrolling();
        }




    }

    /// <summary>
    /// 設(shè)置尋路點(diǎn)
    /// </summary>
    private void Shooting() {
        nav.SetDestination(transform.position);
    }

    /// <summary>
    /// 追擊
    /// </summary>
    private void Chasing() {
        Vector3 sightingDeltaPos = enemySight.playerPosition - transform.position;

        if (sightingDeltaPos.sqrMagnitude > 4f)
        {
            nav.destination = enemySight.playerPosition;
        }

        nav.speed = chaseSpeed;

        if (nav.remainingDistance < nav.stoppingDistance)
        {
            chaseTimer += Time.deltaTime;
            if (chaseTimer >= chaseWaitTime)
            {
                enemySight.playerPosition = enemySight.resetPosition;
                chaseTimer = 0;
            }
        }
        else
        {
            chaseTimer = 0;
        }


    }

    /// <summary>
    /// 巡邏
    /// </summary>
    private void Patrolling() {

        nav.speed = patrolSpeed;
        if (nav.destination == enemySight.resetPosition||nav.remainingDistance<nav.stoppingDistance)
        {
            patrolTimer += Time.deltaTime;

            if (patrolTimer>=patrolWaitTime)
            {
                if (wayPointIndex==patrolWayPoint.Length-1)
                {
                    wayPointIndex = 0;
                }
                else
                {
                    wayPointIndex++;
                }
                patrolTimer = 0;
            }
        }
        else
        {
            patrolTimer = 0;
        }

        nav.destination = patrolWayPoint[wayPointIndex].position;
    }


}

fps_EnemyAnimation

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

public class fps_EnemyAnimation : MonoBehaviour {

    public float deadZone = 5f;

    private Transform player;
    private fps_EnemySight enemySight;
    private NavMeshAgent nav;
    private Animator anim;
    private HashIDs hash;
    private AnimatorSetup animSetup;

    void Start() {

        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        enemySight = this.GetComponent<fps_EnemySight>();
        nav = this.GetComponent<NavMeshAgent>();
        anim = this.GetComponent<Animator>();
        hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<HashIDs>();
        animSetup = new AnimatorSetup(anim, hash);

        nav.updateRotation = false;
        anim.SetLayerWeight(1, 1f); //設(shè)置權(quán)重
        anim.SetLayerWeight(2, 1f);

        deadZone *= Mathf.Deg2Rad;  //弧度
    }


    void Update() {
        NavAnimSetup();
    }

    //動(dòng)畫內(nèi)置函數(shù)
    void OnAnimatorMove() {
        nav.velocity = anim.deltaPosition / Time.deltaTime;
        transform.rotation = anim.rootRotation;

    }


    void NavAnimSetup() {
        float speed;
        float angle;

        if (enemySight.playerInSight)
        {
            speed = 0;
            angle = FindAngle(transform.forward,player.position-transform.position,transform.up);
        }
        else
        {
            speed = Vector3.Project(nav.desiredVelocity,transform.forward).magnitude;
            angle = FindAngle(transform.forward,nav.desiredVelocity,transform.up);

            if (Mathf.Abs(angle)<deadZone)
            {
                transform.LookAt(transform.position+nav.desiredVelocity);
                angle = 0;
            }
        }

        animSetup.Setup(speed,angle);
    }

    private float FindAngle(Vector3 formVector,Vector3 toVector,Vector3 upVector){
        if (toVector==Vector3.zero)
            return 0f;
        float angle = Vector3.Angle(formVector,toVector);
        Vector3 nomal = Vector3.Cross(formVector,toVector);
        angle *= Mathf.Sign(Vector3.Dot(nomal,upVector));
        angle *= Mathf.Deg2Rad;
        return angle;

    }
}

fps_EnemyHealth

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

public class fps_EnemyHealth : MonoBehaviour {

    public float hp = 100;
    private Animator anim;
    private HashIDs hash;
    private bool isDead=false;


    void Start () {

        anim = this.GetComponent<Animator>();
        hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<HashIDs>();


    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 如果被槍打中的話調(diào)用此方法
    /// </summary>
    /// <param name="damage"></param>
    public void TakeDamage(float damage) {

        hp -= damage;
        if (hp<=0&&!isDead)
        {
            isDead = true;
            GetComponent<CapsuleCollider>().enabled=false;
            GetComponent<fps_EnemyAnimation>().enabled=false;
            GetComponent<fps_EnemyAI>().enabled=false;
            GetComponent<fps_EnemySight>().enabled=false;
            GetComponent<fps_EnemyShoot>().enabled=false;
            GetComponent<UnityEngine.AI.NavMeshAgent>().enabled=false;
            GetComponentInChildren<Light>().enabled = false;
            GetComponentInChildren<LineRenderer>().enabled = false;

            anim.SetBool(hash.playerInSightBool,false);
            anim.SetBool(hash.deadBool,true);

            //銷毀
            Destroy(gameObject,2f);
        }

    }

}


fps_EnemyShoot

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

public class fps_EnemyShoot : MonoBehaviour {

    public float maximumDamage = 120;
    public float minimumDamage=45;
    public AudioClip shotClip;
    public float flashIntensity = 3f; //閃爍強(qiáng)度
    public float fadeSpeed = 10f;

    private Animator anim;
    private HashIDs hash;
    private LineRenderer laserShotLine;
    private Light laserShotLight; //光的特效
    private SphereCollider col;
    private Transform player;
    private fps_PlayerHealth playerHealth; //玩家血量
    private bool shooting;
    private float scaleDamage;


    void Start () {

        anim = this.GetComponent<Animator>();
        laserShotLine = this.GetComponentInChildren<LineRenderer>();
        laserShotLight = laserShotLine.gameObject.GetComponent<Light>();

        col = this.GetComponentInChildren<SphereCollider>();
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        playerHealth = player.GetComponent<fps_PlayerHealth>();
        hash = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<HashIDs>();

        laserShotLine.enabled = false;
        laserShotLight.intensity = 0;

        scaleDamage = maximumDamage - minimumDamage;
       

    }
    
    
    void Update () {
        
        float shot=anim.GetFloat(hash.shotFloat);
       // Debug.Log("射擊:::"+shot);
        
        if (shot>0.05f&&!shooting)  //不斷監(jiān)聽 符合條件調(diào)用射擊的方法
        {
            Shoot();
        }
        if (shot<0.05f)
        {
            shooting = false;
            laserShotLine.enabled = false;
        }

        laserShotLight.intensity = Mathf.Lerp(laserShotLight.intensity,0f,fadeSpeed*Time.deltaTime);
    }

    void OnAnimatorIK(int layerIndex) {
        float aimWeight = anim.GetFloat(hash.aimWeightFloat);
        anim.SetIKPosition(AvatarIKGoal.RightHand,player.position+Vector3.up*1.5f);
        anim.SetIKPositionWeight(AvatarIKGoal.RightHand,aimWeight);
    }


    /// <summary>
    /// 射擊
    /// </summary>
    public void Shoot() {

        shooting = true;
        float fractionalDitance = (col.radius - Vector3.Distance(transform.position, player.position)) / col.radius;
        float damage = scaleDamage * fractionalDitance + minimumDamage;
        playerHealth.TakeDamage(damage);

        //調(diào)用槍的特效
        ShotEffects();

    }

    /// <summary>
    /// 槍的特效
    /// </summary>
    private void ShotEffects() {
        laserShotLine.SetPosition(0,laserShotLine.transform.position);
        laserShotLine.SetPosition(1,player.position+Vector3.up*1.5f); //射擊的第二個(gè)位置點(diǎn)
        laserShotLine.enabled = true;
        laserShotLight.intensity = flashIntensity;
        // AudioSource.PlayClipAtPoint(shotClip,laserShotLight.transform.position);
        AudioSource.PlayClipAtPoint(shotClip, transform.position);
    }



}

fps_EnemySight

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


public class fps_EnemySight : MonoBehaviour {

    public float fieldOfViewAngle = 110f;

    public bool playerInSight;

    public Vector3 playerPosition;

    public Vector3 resetPosition=Vector3.zero;

  

    private NavMeshAgent nav;
    private SphereCollider col;
    private Animator anim;
    private  GameObject player;
    private fps_PlayerHealth playerHealth;
    private HashIDs hash;
    private fps_PlayerControl playerControl;


    

    void Start () {

        nav = this.GetComponent<NavMeshAgent>();
        col = GetComponentInChildren<SphereCollider>();
        anim = this.GetComponent<Animator>();
        player = GameObject.FindGameObjectWithTag(Tags.player);
        playerHealth = player.GetComponent<fps_PlayerHealth>();
        playerControl = player.GetComponent<fps_PlayerControl>();

        hash =GameObject.FindGameObjectWithTag("GameController").GetComponent<HashIDs>();

        fps_GunScripts.PlayerShootEvent += ListenPlayer;
    }
    
    
    void Update () {

        //判斷如果玩家的血量大于0
        if (playerHealth.hp>0)
        {
            anim.SetBool(hash.playerInSightBool,playerInSight);//1205
            //anim.SetBool("PlayerInSight", playerInSight); //靠近玩家范圍開始攻打
           // anim.SetBool(hash.playerInSightBool, true);
        }
        else
        {
            anim.SetBool(hash.playerInSightBool,false);
        }

    }


    void OnTriggerStay(Collider other) {
       // Debug.Log("進(jìn)入視野范圍之內(nèi)");

        if (other.gameObject.tag == "Player")
        {
            playerInSight = false;

            Vector3 direction = other.transform.position - transform.position;
            float angle = Vector3.Angle(direction,transform.forward);

            if (angle<fieldOfViewAngle*0.5f)
            {
                RaycastHit hit;
                if (Physics.Raycast(transform.position+transform.up,direction,out hit))  //1204
                {
                    if (hit.collider.gameObject==player)
                    {
                        playerInSight = true;
                        playerPosition = player.transform.position;
                       // Debug.Log("進(jìn)入范圍");
                    }
                }

            }


            //判斷如果玩家處于行走或者跑步狀態(tài)  哪就監(jiān)聽玩家  調(diào)用監(jiān)聽玩家的函數(shù)
            if (playerControl.State==PlayerState.Walk||playerControl.State==PlayerState.Run)
            {
                ListenPlayer();
            }
            

        }
    }

    /// <summary>
    /// 退出觸發(fā)器
    /// </summary>
    void OnTriggerExit(Collider other) {

       // Debug.Log("退出視野范圍");
        if (other.gameObject == player)
        {
            playerInSight = false;
        }

    }



    /// <summary>
    /// 監(jiān)聽玩家的方法
    /// </summary>
    private void ListenPlayer()
    {
        if (Vector3.Distance(player.transform.position,transform.position)<=col.radius)
        {
            playerPosition = player.transform.position;
        }
    }


    /// <summary>
    /// 銷毀時(shí)調(diào)用的函數(shù)
    /// </summary>
    void OnDestroy() {

        //注銷監(jiān)聽的方法 -=ListenPlayer
        fps_GunScripts.PlayerShootEvent -= ListenPlayer;
        Debug.Log("銷毀--注銷監(jiān)聽");
    }
}


fps_ExitTrigger

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


/// <summary>
/// 出口制作
/// </summary>
public class fps_ExitTrigger : MonoBehaviour {

    public float timeToInactivePlayer=2.0f;
    public float timeToRestart = 2.0f;

    private GameObject player;
    private bool playerInExit;
    private float timer;
    private FadeInOut fader;


    void Start () {

        player = GameObject.FindGameObjectWithTag(Tags.player);
        fader = GameObject.FindGameObjectWithTag(Tags.fader).GetComponent<FadeInOut>();

    }
    
    
    void Update () {
        if (playerInExit)
        {
            InExitActivation();
        }
    }

    /// <summary>
    /// 進(jìn)入出口范圍
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {

        //Debug.Log("進(jìn)入觸發(fā)器");

        if (other.gameObject==player)
        {
            playerInExit = true;
            timer = 0;
        }

    }


    /// <summary>
    /// 離開觸發(fā)范圍
    /// </summary>
    void OnTriggerExit(Collider other) {

        Debug.Log("退出 離開范圍");
        if (other.gameObject==player)
        {
            playerInExit = false;
            timer = 0;
        }


    }


    /// <summary>
    /// 激活出口
    /// </summary>
    private void InExitActivation() {

        timer += Time.deltaTime;
        if (timer>=timeToInactivePlayer)
        {
            player.GetComponent<fps_PlayerHealth>().DisableInput();
        }

        if (timer>=timeToRestart)
        {
            //fader.EndScene();
            fader.NextScene();

        }

    }


}


fps_FPCamera

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

/// <summary>
/// 控制相機(jī)的旋轉(zhuǎn)邏輯  鼠標(biāo)和按鍵
/// </summary>
[RequireComponent(typeof(Camera))]
public class fps_FPCamera : MonoBehaviour {

    public Vector2 mouseLookSensitivity = new Vector2(5,5);
    public Vector2 rotationXLimit = new Vector2(87,-87);
    public Vector2 rotationYLimit = new Vector2(-360,360);
    public Vector3 positionOffset = new Vector3(0,2,-0.2f);


    private Vector2 currentMouseLook = Vector2.zero;
    private float x_Angle = 0;
    private float y_Angle = 0;
    private fps_PlayerParemeter paremeter;
    private Transform m_Transform;
    
    void Start () {
        paremeter = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<fps_PlayerParemeter>();
        m_Transform= transform;
        m_Transform.localPosition = positionOffset;

    }
    
    
    void Update () {
        UpdateInput();

    }

    void LateUpdate() {
        Quaternion xQuaternion = Quaternion.AngleAxis(y_Angle,Vector3.up);
        Quaternion yQuaternion = Quaternion.AngleAxis(0,Vector3.left);
        m_Transform.parent.rotation = xQuaternion * yQuaternion;

        yQuaternion = Quaternion.AngleAxis(-x_Angle,Vector3.left);
        m_Transform.rotation = xQuaternion * yQuaternion;
    }


    private void UpdateInput() {

        if (paremeter.inputSmoothLook==Vector2.zero)
        {
            return;
        }
        GetMouseLook();
        y_Angle += currentMouseLook.x;
        x_Angle += currentMouseLook.y;

        y_Angle = y_Angle < -360 ? y_Angle += 360 : y_Angle;
        y_Angle = y_Angle > 360 ? y_Angle -= 360 : y_Angle;
        y_Angle = Mathf.Clamp(y_Angle,rotationYLimit.x,rotationYLimit.y);

        x_Angle = x_Angle < -360 ? x_Angle += 360 : x_Angle;
        x_Angle = x_Angle > 360 ? x_Angle -= 360 : x_Angle;
        x_Angle = Mathf.Clamp(x_Angle, -rotationXLimit.x, -rotationXLimit.y);

    }

    /// <summary>
    /// 鼠標(biāo)的觀看角度
    /// </summary>
    private void GetMouseLook() {

        currentMouseLook.x = paremeter.inputSmoothLook.x;
        currentMouseLook.y = paremeter.inputSmoothLook.y;

        currentMouseLook.x *= mouseLookSensitivity.x;
        currentMouseLook.y *= mouseLookSensitivity.y;

        currentMouseLook.y *= -1;

    }



}

fps_FPInput

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


/// <summary>
/// 玩家輸入
/// </summary>
public class fps_FPInput : MonoBehaviour {

    public bool LockCursor {
        get { return Cursor.lockState == CursorLockMode.Locked ? true : false; }
        set {
            Cursor.visible = value;
            Cursor.lockState = value ? CursorLockMode.Locked : CursorLockMode.None;
        }
    }

    private fps_PlayerParemeter paremeter;
    private fps_Input input;

    void Start() {

        LockCursor = true;
        paremeter = this.GetComponent<fps_PlayerParemeter>();
        input = GameObject.FindGameObjectWithTag(Tags.gameController).GetComponent<fps_Input>();
    }

    void Update() {
        InitialInput();
    }

    /// <summary>
    /// 監(jiān)聽輸入
    /// </summary>
    private void InitialInput() {
        paremeter.inputMoveVector = new Vector2(input.GetAxis("Horizontal"),input.GetAxis("Vertical"));
        paremeter.inputSmoothLook = new Vector2(input.GetAxisRaw("Mouse X"), input.GetAxisRaw("Mouse Y"));
        paremeter.inputCrouch = input.GetButton("Crouch");
        paremeter.inputJump = input.GetButton("Jump");
        paremeter.inputSprint = input.GetButton("Sprint");
        paremeter.inputFire = input.GetButton("Fire");
        paremeter.inputReload = input.GetButton("Reload");
    }


}


fps_GunScripts

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

public delegate void PlayerShoot(); 

/// <summary>
/// 武器動(dòng)畫
/// </summary>
public class fps_GunScripts : MonoBehaviour {

    public static event PlayerShoot PlayerShootEvent;
    public float fireRate = 0.1f;
    public float damage = 40;
    public float reloadTime = 1.5f;
    public float flashRate = 0.02f;
    public AudioClip fireAudio;
    public AudioClip reloadAudio;
    public AudioClip damageAudio;
    public AudioClip dryFireAudio;
    public GameObject explosion;
    public int bulletCount=30;
    public int chargeBulletCount = 60;
    public Text bulletText;

    //動(dòng)畫片段名稱
    private string reloadAnim = "Reload";
    private string fireAnim = "Single_Shot";
    private string walkAnim = "Walk";
    private string runAnim = "Run";
    private string jumpAnim = "Jump";
    private string idledAnim = "Idle";


    private Animation anim;
    private float nextFireTime = 0.0f;
    private MeshRenderer flash;
    private int currentBullet;
    private int currentChargeBullet;
    private fps_PlayerParemeter paremeter;
    private fps_PlayerControl playerControl;



    void Start () {

        paremeter = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<fps_PlayerParemeter>();
        playerControl = GameObject.FindGameObjectWithTag(Tags.player).GetComponent<fps_PlayerControl>();
        anim = this.GetComponent<Animation>();
      //  flash = this.transform.FindChild("muzzle_flash").GetComponent<MeshRenderer>();
        flash = this.transform.Find("muzzle_flash").GetComponent<MeshRenderer>();
        flash.enabled = false;
        currentBullet = bulletCount;
        currentChargeBullet = chargeBulletCount;
        bulletText.text = currentBullet + "/" + currentChargeBullet;

    }
    
    
    void Update () {
        if (paremeter.inputReload&&currentBullet<bulletCount)
        {
            Reload();
        }
        else if (paremeter.inputFire&&!anim.IsPlaying(reloadAnim))
        {
            Fire();
        }
        else if (!anim.IsPlaying(reloadAnim))
        {
            StateAnim(playerControl.State);
        }




    }


    /// <summary>
    /// 換槍動(dòng)畫
    /// </summary>
    private void ReloadAnim() {

        anim.Stop(reloadAnim);
        anim[reloadAnim].speed = (anim[reloadAnim].clip.length/reloadTime);
        anim.Rewind(reloadAnim);
        anim.Play(reloadAnim);

    }

    private IEnumerator ReloadFinish() {

        yield return new WaitForSeconds(reloadTime);
        if (currentChargeBullet>=bulletCount-currentBullet)
        {
            currentChargeBullet -= (bulletCount-currentBullet);
            currentBullet = bulletCount;
        }
        else
        {
            currentBullet += currentChargeBullet;
            currentChargeBullet = 0;
        }
        bulletText.text = currentBullet + "/" + currentChargeBullet;
    }



    /// <summary>
    /// 重裝子彈
    /// </summary>
    private void Reload() {

        if (!anim.IsPlaying(reloadAnim))
        {
            if (currentChargeBullet>0)
            {
                StartCoroutine(ReloadFinish());
            }
            else
            {
                anim.Rewind(fireAnim);
                anim.Play(fireAnim);
                AudioSource.PlayClipAtPoint(dryFireAudio,transform.position);
                return;
            }

            AudioSource.PlayClipAtPoint(reloadAudio,transform.position);
            ReloadAnim();
        }
    }

    /// <summary>
    /// 開火特效
    /// </summary>
    /// <returns></returns>
    private IEnumerator Flash() {

        flash.enabled = true;
        yield return new WaitForSeconds(flashRate);
        flash.enabled = false;
    }

    /// <summary>
    /// 射擊
    /// </summary>
    private void Fire() {
        if (Time.time>nextFireTime)
        {
            if (currentBullet<=0)
            {
                Reload();
                nextFireTime = Time.time + fireRate;
                return;
            }
            currentBullet--;
            bulletText.text = currentBullet + "/" + currentChargeBullet;
            DamageEnemy();
            if (PlayerShootEvent!=null)
            {
                PlayerShootEvent();
            }
            AudioSource.PlayClipAtPoint(fireAudio,transform.position);
            nextFireTime = Time.time + fireRate;
            anim.Rewind(fireAnim);
            anim.Play(fireAnim);
            StartCoroutine(Flash());
        }
    }



    /// <summary>
    /// 敵人收到攻擊
    /// </summary>
    private void DamageEnemy() {

        Ray ray = Camera.main.ScreenPointToRay(new Vector3(Screen.width/2,Screen.height/2,0));
        RaycastHit hit;

        if (Physics.Raycast(ray,out hit))
        {
            if (hit.transform.tag==Tags.enemy&&hit.collider is CapsuleCollider) //機(jī)器人
            {
                AudioSource.PlayClipAtPoint(damageAudio,hit.transform.position);
                GameObject go = Instantiate(explosion,hit.point,Quaternion.identity);
                Destroy(go,3f);
                hit.transform.GetComponent<fps_EnemyHealth>().TakeDamage(damage);

            }else if (hit.transform.tag == Tags.buzzer )  //無(wú)人機(jī)
            {
                AudioSource.PlayClipAtPoint(damageAudio, hit.transform.position);
                GameObject go = Instantiate(explosion, hit.point, Quaternion.identity);
                Destroy(go, 3f);
                hit.transform.GetComponent<fps_BuzzerHealth>().TakeDamage(damage);

            }
            else if (hit.transform.tag == Tags.spider)  //無(wú)人機(jī)
            {
                AudioSource.PlayClipAtPoint(damageAudio, hit.transform.position);
                GameObject go = Instantiate(explosion, hit.point, Quaternion.identity);
                Destroy(go, 3f);
                hit.transform.GetComponent<fps_SpiderHealth>().TakeDamage(damage);

            }



        }


    }

    /// <summary>
    /// 動(dòng)畫狀態(tài)控制
    /// </summary>
    /// <param name="animName"></param>
    private void PlayerStateAnim(string animName) {

        if (!anim.IsPlaying(animName))
        {
            anim.Rewind(animName);
            anim.Play(animName);
        }
    }


    /// <summary>
    /// 動(dòng)畫狀態(tài)
    /// </summary>
    /// <param name="state"></param>
    private void StateAnim(PlayerState state) {

        switch (state)
        {
          
            case PlayerState.Idle:
                PlayerStateAnim(idledAnim);
                break;
            case PlayerState.Walk:
                PlayerStateAnim(walkAnim);
                break;
            case PlayerState.Coruch:
                PlayerStateAnim(walkAnim);
                break;
            case PlayerState.Run:
                PlayerStateAnim(runAnim);
                break;
          
        }

    }

}


fps_Input

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

/// <summary>
/// 輸入按鍵控制控制
/// </summary>
public class fps_Input : MonoBehaviour {

    public class fps_InputAxis {

        public KeyCode positive;
        public KeyCode negative;
    }


    //字典 鍵值對(duì)  按鍵 鼠標(biāo) 水平 垂直
    public Dictionary<string, KeyCode> buttons = new Dictionary<string, KeyCode>();

    public Dictionary<string, fps_InputAxis> axis = new Dictionary<string, fps_InputAxis>();

    public List<string> unityAxis = new List<string>();

    //執(zhí)行配置
    void Start() {
        SetupDefaults();
    }



    /// <summary>
    /// 按鍵配置
    /// </summary>
    /// <param name="type"></param>
    private void SetupDefaults(string type ="") {
        if (type==""||type=="buttons")
        {
            if (buttons.Count==0)
            {
                AddButton("Fire",KeyCode.Mouse0);
                AddButton("Reload",KeyCode.R);
                AddButton("Jump",KeyCode.Space);
                AddButton("Crouch",KeyCode.C);
                AddButton("Sprint",KeyCode.LeftShift);

            }
        }


        if (type == "" || type == "Axis")
        {
            if (axis.Count == 0)
            {
                AddAxis("Horizontal", KeyCode.W,KeyCode.S);
                AddAxis("Vertical", KeyCode.A,KeyCode.D);

            }
        }

        if (type == "" || type == "UnityAxis")
        {
            if (unityAxis.Count == 0)
            {

                AddUnityAxis("Mouse X");
                AddUnityAxis("Mouse Y");
                AddUnityAxis("Horizontal");
                AddUnityAxis("Vertical");
            }
        }
    }


    private void AddButton(string n,KeyCode k) {
        if (buttons.ContainsKey(n))
        {
            buttons[n] = k;
        }
        else
        {
            buttons.Add(n,k);
        }
    }


    private void AddAxis(string n,KeyCode pk,KeyCode nk) {

        if (axis.ContainsKey(n))
        {
            axis[n] = new fps_InputAxis() { positive=pk,negative=nk};
        }
        else
        {
            axis.Add(n,new fps_InputAxis() { positive = pk, negative = nk });
        }
    }



    private void AddUnityAxis(string n) {
        if (!unityAxis.Contains(n))
        {
            unityAxis.Add(n);
        }
    }

    /// <summary>
    /// 判斷是否有按鍵輸入
    /// </summary>
    /// <returns></returns>
    public bool GetButton(string button) {
        if (buttons.ContainsKey(button))
        {
            return Input.GetKey(buttons[button]);
        }
        return false;
    }

    /// <summary>
    /// 是否有按下
    /// </summary>
    /// <param name="button"></param>
    /// <returns></returns>
    public bool GetButtonDown(string button)
    {
        if (buttons.ContainsKey(button))
        {
            return Input.GetKeyDown(buttons[button]);
        }
        return false;
    }

    /// <summary>
    /// 是否有值輸入
    /// </summary>
    /// <param name="axis"></param>
    /// <returns></returns>
    public float GetAxis(string axis) {

        if (this.unityAxis.Contains(axis))
        {
            return Input.GetAxis(axis);
        }

        return 0;
    }


    public float GetAxisRaw(string axis) {

        if (this.axis.ContainsKey(axis))
        {
            float val = 0;
            if (Input.GetKey(this.axis[axis].positive))
            {
                return 1;
            }
            if (Input.GetKey(this.axis[axis].negative))
            {
                return -1;
            }
            return val;
        }
        else if (unityAxis.Contains(axis))
        {
            return Input.GetAxisRaw(axis);
        }
        else
        {
            return 0;
        }



    }


}

fps_KeyPickUp

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

/// <summary>
/// 鑰匙卡
/// </summary>
public class fps_KeyPickUp : MonoBehaviour {

    public AudioClip keyGrab;
    public int keyId;

    private GameObject player;
    private fps_PlayerInventory playerInventory;



    void Start () {

        player = GameObject.FindGameObjectWithTag(Tags.player);
        playerInventory = player.GetComponent<fps_PlayerInventory>();

    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 進(jìn)入觸發(fā)范圍
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {
        Debug.Log("進(jìn)入鑰匙觸發(fā)范圍--準(zhǔn)備執(zhí)起鑰匙卡");
        if (other.gameObject==player)
        {
            AudioSource.PlayClipAtPoint(keyGrab,transform.position);  //播放執(zhí)起聲效
            playerInventory.AddKey(keyId);  //設(shè)置的id號(hào)對(duì)應(yīng) 鑰匙  跟 門 是配對(duì)
            Destroy(this.gameObject);

        }
    }


}

fps_LaserDamage

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


/// <summary>
/// 激光墻
/// </summary>
public class fps_LaserDamage : MonoBehaviour {

    public int damage = 30;
    public float damageDelay = 1; //1秒傷害1次

    private float lastDamageTime = 0;
    private GameObject player;

    void Start () {
        player = GameObject.FindGameObjectWithTag(Tags.player); //獲取玩家的引用
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 觸發(fā)器逗留
    /// </summary>
    void OnTriggerStay(Collider other) {
       // Debug.Log("進(jìn)入激光墻觸發(fā)");
        if (other.gameObject==player&&Time.time>lastDamageTime+damageDelay)
        {
            player.GetComponent<fps_PlayerHealth>().TakeDamage(damage); //執(zhí)行玩家受傷害的方法
            lastDamageTime = Time.time; //確認(rèn)當(dāng)前時(shí)間
        }
    }

}

fps_PlayerControl

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

/// <summary>
/// 玩家4種狀態(tài)
/// </summary>
public enum PlayerState
{

    None,
    Idle,
    Walk,
    Coruch,
    Run,
}
/// <summary>
/// 玩家控制
/// </summary>
public class fps_PlayerControl : MonoBehaviour {

    private PlayerState state = PlayerState.None;
    public PlayerState State {
        get {
            if (running)
                state = PlayerState.Run;
            else if (walking)
                state = PlayerState.Walk;
            else if (crouching)
                state = PlayerState.Coruch;
            else
                state = PlayerState.Idle;

            return state;
        }
    }

    public float sprintSpeed = 10.0f;
    public float sprintJumpSpeed = 8.0f;
    public float normalSpeed = 6.0f;
    public float normalJumpSpeed = 7.0f;
    public float crouchSpeed = 2.0f;
    public float crouchJumpSpeed = 5.0f;
    public float crouchDeltaHeight = 0.5f;


    public float gravity = 20.0f;
    public float cameraMoveSpeed = 8.0f;
    public AudioClip jumpAudio;


    private float speed;
    private float jumpSpeed;
    private Transform mainCamera;
    private float standardCamHeight;
    private float crouchingCamHeight;
    private bool grounded = false;
    private bool walking = false;
    private bool crouching = false;
    private bool stopCrouching = false;
    private bool running = false;
    private Vector3 normalControllerCenter = Vector3.zero;
    private float normalControllerHeight = 0.0f;
    private float timer = 0;
    private CharacterController controller;
    private AudioSource audioSource;
    private fps_PlayerParemeter paremeter;
    private Vector3 moveDirection = Vector3.zero;


    void Start() {
        crouching = false;
        walking = false;
        running = false;
        speed = normalSpeed;
        jumpSpeed = normalJumpSpeed;
        mainCamera = GameObject.FindGameObjectWithTag(Tags.mainCamera).transform;
        standardCamHeight = mainCamera.localPosition.y;
        crouchingCamHeight = standardCamHeight - crouchDeltaHeight;
        audioSource = this.GetComponent<AudioSource>();
        controller = this.GetComponent<CharacterController>();
        paremeter = this.GetComponent<fps_PlayerParemeter>();
        normalControllerCenter = controller.center;
        normalControllerHeight = controller.height;
    }


  

    void FixedUpdate() {
        UpdateMove();
        AudioManager();
    }


    /// <summary>
    /// 更新有移動(dòng)
    /// </summary>

    void UpdateMove(){
        if (grounded)
        {
            moveDirection = new Vector3(paremeter.inputMoveVector.x, 0, paremeter.inputMoveVector.y);
            moveDirection = transform.TransformDirection(moveDirection);
            moveDirection *= speed;

            if (paremeter.inputJump)
            {
                moveDirection.y = jumpSpeed;
                AudioSource.PlayClipAtPoint(jumpAudio, transform.position);
                CurrentSpeed();
            }
        }

        moveDirection.y -= gravity * Time.deltaTime;
        CollisionFlags flags = controller.Move(moveDirection*Time.deltaTime);
        grounded = (flags&CollisionFlags.CollidedBelow) != 0;

        if (Mathf.Abs(moveDirection.x)>0&&grounded||Mathf.Abs(moveDirection.z)>0&&grounded)
        {
            if (paremeter.inputSprint)
            {
                walking = false;
                running = true;
                crouching = false;
            }
            else if (paremeter.inputCrouch)
            {
                walking = false;
                running = false;
                crouching = true;

            }
            else
            {
                walking = true ;
                running = false;
                crouching = false;
            }


        }
        else
        {
            if (walking)
                walking = false;
            if (running)
                running = false;
            if (paremeter.inputCrouch)
                crouching = true;
            else
                crouching = false;

        }

        if (crouching)
        {
            controller.height = normalControllerHeight - crouchDeltaHeight;
            controller.center = normalControllerCenter - new Vector3(0, crouchDeltaHeight/2,0);
        }
        else
        {
            controller.height = normalControllerHeight ;
            controller.center = normalControllerCenter;

        }
        UpdateCrouch();
        CurrentSpeed();
    }


    /// <summary>
    /// 玩家當(dāng)前速度管理
    /// </summary>
    private void CurrentSpeed() {
        switch (State)
        {
            
            case PlayerState.Idle:
                speed = normalSpeed;
                jumpSpeed = normalJumpSpeed;
                break;
            case PlayerState.Walk:
                speed = normalSpeed;
                jumpSpeed = normalJumpSpeed;
                break;
            case PlayerState.Coruch:
                speed = crouchSpeed;
                jumpSpeed = crouchJumpSpeed;
                break;
            case PlayerState.Run:
                speed = sprintSpeed;
                jumpSpeed = sprintJumpSpeed;
                break;
           
        }


    }


    /// <summary>
    /// 聲效管理器
    /// </summary>
    private void AudioManager() {

        if (State == PlayerState.Walk)
        {
            audioSource.pitch = 1.0f;
            if (!audioSource.isPlaying)
            {
                audioSource.Play();
            }
        }
        else if (State == PlayerState.Run)
        {
            audioSource.pitch = 1.3f;
            if (!audioSource.isPlaying)
            {
                audioSource.Play();
            }
        }
        else
            audioSource.Stop();
    }


    /// <summary>
    /// 更新蹲伏狀態(tài)
    /// </summary>
    private void UpdateCrouch() {

        if (crouching)
        {
            if (mainCamera.localPosition.y > crouchingCamHeight)
            {
                if (mainCamera.localPosition.y - (crouchDeltaHeight * Time.deltaTime * cameraMoveSpeed) < crouchingCamHeight)
                    mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, crouchingCamHeight, mainCamera.localPosition.z);
                else
                    mainCamera.localPosition -= new Vector3(0, crouchDeltaHeight * Time.deltaTime * cameraMoveSpeed, 0);
            }
            else
                mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, crouchingCamHeight, mainCamera.localPosition.z);
        }
        else
        {
            if (mainCamera.localPosition.y < standardCamHeight)
            {
                if (mainCamera.localPosition.y + (crouchDeltaHeight * Time.deltaTime * cameraMoveSpeed) > standardCamHeight)
                    mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, standardCamHeight, mainCamera.localPosition.z);
                else
                    mainCamera.localPosition += new Vector3(0, crouchDeltaHeight * Time.deltaTime * cameraMoveSpeed, 0);
            }
            else
                mainCamera.localPosition = new Vector3(mainCamera.localPosition.x, standardCamHeight, mainCamera.localPosition.z);

        }

    }

}

fps_PlayerHealth

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityStandardAssets.ImageEffects;


/// <summary>
/// 玩家生命值
/// </summary>
public class fps_PlayerHealth : MonoBehaviour {

    public bool isDead;
    public float resetAfterDeathTime = 0;
    public AudioClip deadClip;
    public AudioClip damageClip;
    public float maxHP = 100;
    public float hp = 100;
    public float recoverSpeed = 1;

    private float timer = 0;
    private FadeInOut fader;
    private ColorCorrectionCurves colorCurves;  //屏幕特效

    void Start () {

        hp = maxHP;
        fader = GameObject.FindGameObjectWithTag(Tags.fader).GetComponent<FadeInOut>();
        colorCurves = GameObject.FindGameObjectWithTag(Tags.mainCamera).GetComponent<ColorCorrectionCurves>();
        BleedBehavior.BloodAmount = 0; //設(shè)置為0  沒有顯示紅色的區(qū)域
    }
    
    
    void Update () {
        if (!isDead)
        {
            hp += recoverSpeed * Time.deltaTime; //恢復(fù)時(shí)間
            if (hp>maxHP)
            {
                hp = maxHP;
            }
        }

        if (hp<0)
        {
            if (!isDead)
            {
                PlayerDead();
            }
            else
            {
                LevelReset();
            }
        }


    }

    /// <summary>
    /// 玩家受到攻擊
    /// </summary>
    public void TakeDamage(float damage) {
        if (isDead)
        {
            return;
        }
        AudioSource.PlayClipAtPoint(damageClip,transform.position);
        float damage01 = damage;
        if (damage01<40)
        {
            damage01 *= 30;
        }
        //BleedBehavior.BloodAmount += Mathf.Clamp01(damage/hp);
        BleedBehavior.BloodAmount += Mathf.Clamp01(damage01 / hp);
        hp -= damage;
    }


    /// <summary>
    /// 不能繼續(xù)輸入
    /// </summary>
    public void DisableInput() {

        transform.Find("FP_Camera/Weapon_Camera").gameObject.SetActive(false);
        this.GetComponent<AudioSource>().enabled = false;
        this.GetComponent<fps_PlayerControl>().enabled = false;
        this.GetComponent<fps_FPInput>().enabled = false;
        if (GameObject.Find("Canvas") !=null) //注意畫布的隱藏和顯示
        {
            GameObject.Find("Canvas").SetActive (false);
        }
        colorCurves.gameObject.GetComponent<fps_FPCamera>().enabled = false;
    }


    /// <summary>
    /// 玩家掛掉
    /// </summary>
    public void PlayerDead() {

        isDead = true;
        colorCurves.enabled = true;
        DisableInput();
        AudioSource.PlayClipAtPoint(deadClip,transform.position);
    }


    /// <summary>
    /// 重置
    /// </summary>
    public void LevelReset() {
        timer += Time.deltaTime;
        colorCurves.saturation -= (Time.deltaTime / 2);
        colorCurves.saturation = Mathf.Max(0,colorCurves.saturation);
        if (timer>=resetAfterDeathTime)
        {
            fader.EndScene(); //播放漸暗的效果
        }

    }

}

fps_PlayerInventory

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

/// <summary>
/// 控制id號(hào)
/// </summary>
public class fps_PlayerInventory : MonoBehaviour {

    private List<int> keyArr;

    void Start () {

        keyArr = new List<int>();
    }
    
    
    void Update () {
        
    }

    /// <summary>
    /// 加入Id號(hào)
    /// </summary>
    /// <param name="keyId"></param>
    public void AddKey(int keyId) {
        if (!keyArr.Contains(keyId))
        {
            keyArr.Add(keyId);
        }

    }


    /// <summary>
    /// 對(duì)應(yīng)門ID號(hào)確認(rèn)是否可以打開
    /// </summary>
    /// <param name="doorId"></param>
    /// <returns></returns>
    public bool HasKey(int doorId) {
        if (keyArr.Contains(doorId))
        {
            return true;
        }
        return false;

    }


}

fps_PlayerParemeter

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

/// <summary>
/// 玩家輸入?yún)?shù)的封裝
/// </summary>
[RequireComponent(typeof(CharacterController))]
public class fps_PlayerParemeter : MonoBehaviour {
    [HideInInspector]
    public Vector2 inputSmoothLook;
    [HideInInspector]
    public Vector2 inputMoveVector;
    [HideInInspector]
    public bool inputCrouch;
    [HideInInspector]
    public bool inputJump;
    [HideInInspector]
    public bool inputSprint;
    [HideInInspector]
    public bool inputFire;
    [HideInInspector]
    public bool inputReload;



    
    void Start () {
        
    }
    
    
    void Update () {
        
    }
}

HashIDs

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

/// <summary>
/// 動(dòng)畫哈希值 
/// </summary>
public class HashIDs : MonoBehaviour {

    public int deadBool;

    public int speedFloat;

    public int playerInSightBool;

    public int shotFloat;

    public int aimWeightFloat;

    public int angularSpeedFloat;


    void Awake() {

        deadBool = Animator.StringToHash("Dead");

        speedFloat = Animator.StringToHash("Speed");

        playerInSightBool = Animator.StringToHash("PlayerInSight");

        shotFloat = Animator.StringToHash("Shot");

        aimWeightFloat = Animator.StringToHash("AimWeight");

        angularSpeedFloat = Animator.StringToHash("AngularSpeed");
    }


    void Start () {
        
    }
    
    
    void Update () {
        
    }
}

Outdoor

BuzzerAttack

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


/// <summary>
/// 無(wú)人機(jī)攻擊腳本
/// </summary>
public class BuzzerAttack : MonoBehaviour
{

    public LineRenderer electricArc;//攻擊閃電特效
    public float coldTime = 1.0f;
    public BuzzerMove move;
    public  float damage=40;//攻擊力


    private Transform player;
    private Vector3 zapNoise = Vector3.zero;
    private AudioSource audioSource;
    private float rechargeTimer ; //間隔計(jì)時(shí)器 冷卻時(shí)間
    private bool canAttack = false; //是否到達(dá)攻擊范圍
    private fps_PlayerHealth playerHealth;

    void Awake()
    {
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        playerHealth = player.GetComponent<fps_PlayerHealth>();
        audioSource = GetComponent<AudioSource>();
        rechargeTimer = coldTime;
    }


    void Update()
    {
        move.moveTarget = player.position;
        //Vector3.Distance(transform.position, player.position);
        Vector3 dir = player.position - transform.position;
        // canAttack = dir.magnitude < 2.0f; //布爾值賦值
        canAttack = false;
        if (dir.magnitude < 3.8f)
        {
            canAttack = true;
            move.moveTarget = Vector3.zero; //注意位置信息1213
        }
         rechargeTimer -= Time.deltaTime; //冷卻中
        
        if (rechargeTimer < 0&&canAttack)
        {
            zapNoise = new Vector3(Random.Range(-1.0f, 1.0f), 0.0f, Random.Range(-1.0f, 1.0f)) * 0.5f;
            StartCoroutine(DoElectricArc());
            // rechargeTimer = coldTime;
            rechargeTimer = Random.Range(1.0f,2.0f); //重置冷卻時(shí)間
            playerHealth.TakeDamage(damage);//玩家受到攻擊

        }
    }



    /// <summary>
    /// 開啟雷電攻擊功能
    /// </summary>
    /// <returns></returns>
    IEnumerator DoElectricArc()
    {

        if (electricArc.enabled)
        {
            yield return 0;
        }
        //播放閃電音效
        audioSource.Play();


        electricArc.enabled = true;

        zapNoise = transform.rotation * zapNoise;

        float stopTime = Time.time + 0.2f;
        while (Time.time < stopTime)
        {
            electricArc.SetPosition(0, electricArc.transform.position);
            electricArc.SetPosition(1, player.position + zapNoise);
            yield return 0;
        }

        electricArc.enabled = false;



    }


}

BuzzerMove

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

/// <summary>
/// 無(wú)人機(jī)移動(dòng)
/// </summary>
public class BuzzerMove : MonoBehaviour {

    public float flyingSpeed = 5.0f; //飛行速度
    public float zigZagness = 3.0f; //范圍
    public float zigZagSpeed = 2.5f;//速度
    public float backtrackIntensity = 0.5f; //回退系數(shù)
    public float oriantationMultiplier = 2.5f;   //旋轉(zhuǎn)系數(shù)
    public Vector3 moveTarget; //追蹤目標(biāo)

    private Transform player;
    private Rigidbody rigi;
    private Vector3 smoothDirection = Vector3.zero;  //使移動(dòng)更平滑


    void Awake() {
        player = GameObject.FindGameObjectWithTag("Player").transform;
        rigi = transform.GetComponent<Rigidbody>();
    }


    
    
    void FixedUpdate () {
        //Vector3 direction = player.position - transform.position;
        Vector3 direction = moveTarget - transform.position;
        direction.Normalize(); //平滑歸零 避免越來(lái)越大
        smoothDirection = Vector3.Lerp(smoothDirection,direction,Time.deltaTime*3.0f);

        Vector3 zigzag = transform.right * (Mathf.PingPong(Time.time* zigZagSpeed, 2.0f)-1.0f)* zigZagness;
        float orientationSpeed = 1.0f;
            
        Vector3 deltaVelocity = (smoothDirection * flyingSpeed+zigzag)- rigi.velocity;

        if (Vector3.Dot(direction,transform.forward)>0.8f)
        {
            rigi.AddForce(deltaVelocity, ForceMode.Force);
        }
        else
        {
            rigi.AddForce(-deltaVelocity*backtrackIntensity, ForceMode.Force);
            orientationSpeed = oriantationMultiplier;
        }
       

        float rotationAngle = AngleAroundAxis(transform.forward,direction,Vector3.up);
        rigi.angularVelocity = Vector3.up * rotationAngle * 0.2f*orientationSpeed;
    }


    /// <summary>
    /// 旋轉(zhuǎn)角度
    /// </summary>
    /// <returns></returns>
    static float AngleAroundAxis(Vector3 dirA,Vector3 dirB, Vector3 axis) {

        dirA = dirA - Vector3.Project(dirA,axis);
        dirB = dirB - Vector3.Project(dirB,axis);

        float angle=Vector3.Angle(dirA,dirB);

        return angle * (Vector3.Dot(axis,Vector3.Cross(dirA,dirB))<0?-1:1);

    }

}

fps_BuzzerHealth

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

public class fps_BuzzerHealth : MonoBehaviour {

    public float hp = 100;
    public GameObject explosion;

    private bool isDead = false;

    /// <summary>
    /// 無(wú)人機(jī)受到攻擊
    /// </summary>
    public void TakeDamage(float damage) {

        hp -= damage;
        if (hp<=0&&!isDead)
        {
            isDead = true;
            transform.GetComponent<BuzzerMove>().enabled = false;
            transform.GetComponent<BuzzerAttack>().enabled = false;
            transform.GetComponent<fps_BuzzerHealth>().enabled = false;
            GameObject go = Instantiate(explosion, transform.position, Quaternion.identity);
            Destroy(go, 2f);
            Destroy(gameObject);
        }

    }



}

fps_BuzzerSight

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

public class fps_BuzzerSight : MonoBehaviour {

    

    void Start () {
        transform.GetComponent<BuzzerMove>().enabled = false;
        transform.GetComponent<BuzzerAttack>().enabled = false;
        transform.GetComponent<fps_BuzzerHealth>().enabled = false;
    }
    

    /// <summary>
    /// 進(jìn)入視野范圍
    /// </summary>
    void OnTriggerEnter(Collider collider) {

        Debug.Log("進(jìn)入無(wú)人機(jī)視野范圍");
        if (collider.gameObject.tag==Tags.player)
        {
            transform.GetComponent<BuzzerMove>().enabled = true;
            transform.GetComponent<BuzzerAttack>().enabled = true;
            transform.GetComponent<fps_BuzzerHealth>().enabled = true;
           
        }

    }


}

SpiderAttack

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

public class SpiderAttack : MonoBehaviour
{

    public GameObject bot; //子物體
    public GameObject explosionPrefab;//爆炸預(yù)制體
    public float damageRadius = 5.0f;   //破壞范圍
    public SpiderMove move;
    public float damage = 40;//攻擊力

   public  Transform player;
    private bool canAttack = false;
    private Animation anim;
    private fps_PlayerHealth playerHealth;

    void Awake()
    {
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        playerHealth = player.GetComponent<fps_PlayerHealth>();
        anim = bot.GetComponent<Animation>();
    }

    void Start()
    {

    }


    void Update()
    {

        Vector3 playerDirection = (player.position - transform.position);
        float playerDis = playerDirection.magnitude;
        playerDirection /= playerDis;



        Vector3 dir = player.position - transform.position;
       // canAttack = false;
        //達(dá)到指定距離后就不在播放動(dòng)畫 1213
        if (dir.magnitude < 2.0f)
        {
            // canAttack = true;
            move.moveDirection = Vector3.zero;
            anim.Stop();
            StartCoroutine(Explode());
        }
        else
        {
            move.moveDirection = playerDirection;
            anim.Play("forward");

        }
        //anim.Play("forward");
    }


    /// <summary>
    /// 爆炸
    /// </summary>
    IEnumerator Explode()
    {
        yield return new WaitForSeconds(1f);
        float damageFraction = 1 - (Vector3.Distance(player.position,transform.position)/damageRadius);
        // player.GetComponent<Rigidbody>().AddExplosionForce(10,transform.position,damageRadius,0.0f,ForceMode.Impulse);
        playerHealth.TakeDamage(damage);//玩家受到攻擊
        GameObject go=Instantiate(explosionPrefab,transform.position,Quaternion.identity);
        Destroy(go,2f);
        Destroy(gameObject);

    }
}

SpiderMove

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

public class SpiderMove : MonoBehaviour {

 
    public float walkingSpeed = 5.0f; //移動(dòng)速度

    [HideInInspector]
    public Vector3 moveDirection;  //移動(dòng)方向
    [HideInInspector]
    public Vector3 facingDirection; //面向方向

    private Transform player; //玩家
    private Rigidbody rigi;
    private float orientationSpeed = 0.3f;
    void Awake(){
        player = GameObject.FindGameObjectWithTag(Tags.player).transform;
        rigi = this.GetComponent<Rigidbody>();
    }
    void Start () {

    }
    
    
    /// <summary>
    /// 追蹤玩家
    /// </summary>
    void FixedUpdate () {


        Vector3 targetVeloctiy = moveDirection;// (player.position-transform.position) ;
       // targetVeloctiy.Normalize();
        Vector3 detalVeloctiy = targetVeloctiy * walkingSpeed - rigi.velocity;
        rigi.AddForce(detalVeloctiy,ForceMode.Acceleration);

        Vector3 faceDir = targetVeloctiy;
        if (faceDir==Vector3.zero)
        {
            rigi.angularVelocity = Vector3.zero;
        }
        else
        {
            float rotationAngle = AngleAroundAxis(transform.forward, faceDir, Vector3.up);
            rigi.angularVelocity = Vector3.up * rotationAngle * 0.2f * orientationSpeed;
        }

       

    }


    /// <summary>
    /// 旋轉(zhuǎn)角度
    /// </summary>
    /// <returns></returns>
    static float AngleAroundAxis(Vector3 dirA, Vector3 dirB, Vector3 axis)
    {

        dirA = dirA - Vector3.Project(dirA, axis);
        dirB = dirB - Vector3.Project(dirB, axis);

        float angle = Vector3.Angle(dirA, dirB);

        return angle * (Vector3.Dot(axis, Vector3.Cross(dirA, dirB)) < 0 ? -1 : 1);

    }
}

三、效果圖

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末授翻,一起剝皮案震驚了整個(gè)濱河市乎婿,隨后出現(xiàn)的幾起案子今阳,更是在濱河造成了極大的恐慌,老刑警劉巖逊躁,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件似踱,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡稽煤,警方通過查閱死者的電腦和手機(jī)核芽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)酵熙,“玉大人轧简,你說(shuō)我怎么就攤上這事∝叶” “怎么了哮独?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵拳芙,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我皮璧,道長(zhǎng)舟扎,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任悴务,我火速辦了婚禮睹限,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘讯檐。我一直安慰自己邦泄,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布裂垦。 她就那樣靜靜地躺著,像睡著了一般肌索。 火紅的嫁衣襯著肌膚如雪蕉拢。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天诚亚,我揣著相機(jī)與錄音晕换,去河邊找鬼。 笑死站宗,一個(gè)胖子當(dāng)著我的面吹牛闸准,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梢灭,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼夷家,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了敏释?” 一聲冷哼從身側(cè)響起库快,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎钥顽,沒想到半個(gè)月后义屏,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜂大,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年闽铐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片奶浦。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡兄墅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出财喳,到底是詐尸還是另有隱情察迟,我是刑警寧澤斩狱,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站扎瓶,受9級(jí)特大地震影響所踊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜概荷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一秕岛、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧误证,春花似錦继薛、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至蓝谨,卻和暖如春灌具,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背譬巫。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工咖楣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芦昔。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓诱贿,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親咕缎。 傳聞我的和親對(duì)象是個(gè)殘疾皇子珠十,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容