VR开发实战HTC Vive项目之星球大战

一、框架视图

3600969-968022ddbb55a668.png

二、主要代码

Indoor

AnimatorSetup

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

public class AnimatorSetup  {
    public float speedDampTime=0.1f;  //缓冲时间
    public float angularSpeedDampTime = 0.7f;
    public float angleResponseTime = 1f;
    private Animator anim;
    private HashIDs hash;

    /// <summary>
    /// 构造函数
    /// </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>
    /// 进入场景
    /// </summary>
    public void StartScene() {

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


    /// <summary>
    /// 结束场景
    /// </summary>
    public void EndScene() {
      
        sceneStarting = true;
        FadeToBlack();
        if (tex.color.a>=0.95f)
        {
            //SceneManager.LoadScene("Indoor");
            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);

        }
    }


    /// <summary>
    /// 进入下一个场景
    /// </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>
/// 武器设置以及准星绘制
/// </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>
    /// 绘制准星
    /// </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>
/// 静态滑动门设置-1
/// </summary>
public class fps_DoorControl : MonoBehaviour {

    public int doorId;  //门的id号
    public Vector3 from; //原始位置
    public Vector3 to;//滑动位置
    public float fadeSpeed=5; //滑动速度
    public bool requireKey = false; //通过钥匙打开
    public AudioClip doorSwitchClip; //开门声效
    public AudioClip accessDeniedClip; //进入声效


    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>
    /// 进入触发器
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {

        Debug.Log("进入门的触发器");

        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>
    /// 离开触发器
    /// </summary>
    void OnTriggerExit(Collider other) {

        Debug.Log("离开门的触发器");
        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; //巡逻时间
    public float chaseSpeed = 5f;   //追击时间
    public float chaseWaitTime = 5f;
    public float patrolWaitTime = 1f;
    public Transform[] patrolWayPoint;//寻路点

    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>
    /// 设置寻路点
    /// </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); //设置权重
        anim.SetLayerWeight(2, 1f);

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


    void Update() {
        NavAnimSetup();
    }

    //动画内置函数
    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>
    /// 如果被枪打中的话调用此方法
    /// </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; //闪烁强度
    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)  //不断监听 符合条件调用射击的方法
        {
            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);

        //调用枪的特效
        ShotEffects();

    }

    /// <summary>
    /// 枪的特效
    /// </summary>
    private void ShotEffects() {
        laserShotLine.SetPosition(0,laserShotLine.transform.position);
        laserShotLine.SetPosition(1,player.position+Vector3.up*1.5f); //射击的第二个位置点
        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("进入视野范围之内");

        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("进入范围");
                    }
                }

            }


            //判断如果玩家处于行走或者跑步状态  哪就监听玩家  调用监听玩家的函数
            if (playerControl.State==PlayerState.Walk||playerControl.State==PlayerState.Run)
            {
                ListenPlayer();
            }
            

        }
    }

    /// <summary>
    /// 退出触发器
    /// </summary>
    void OnTriggerExit(Collider other) {

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

    }



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


    /// <summary>
    /// 销毁时调用的函数
    /// </summary>
    void OnDestroy() {

        //注销监听的方法 -=ListenPlayer
        fps_GunScripts.PlayerShootEvent -= ListenPlayer;
        Debug.Log("销毁--注销监听");
    }
}


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>
    /// 进入出口范围
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {

        //Debug.Log("进入触发器");

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

    }


    /// <summary>
    /// 离开触发范围
    /// </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>
/// 控制相机的旋转逻辑  鼠标和按键
/// </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>
    /// 鼠标的观看角度
    /// </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>
    /// 监听输入
    /// </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>
/// 武器动画
/// </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;

    //动画片段名称
    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>
    /// 换枪动画
    /// </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) //机器人
            {
                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 )  //无人机
            {
                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)  //无人机
            {
                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>
    /// 动画状态控制
    /// </summary>
    /// <param name="animName"></param>
    private void PlayerStateAnim(string animName) {

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


    /// <summary>
    /// 动画状态
    /// </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;
    }


    //字典 键值对  按键 鼠标 水平 垂直
    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>();

    //执行配置
    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>
    /// 进入触发范围
    /// </summary>
    /// <param name="other"></param>
    void OnTriggerEnter(Collider other) {
        Debug.Log("进入钥匙触发范围--准备执起钥匙卡");
        if (other.gameObject==player)
        {
            AudioSource.PlayClipAtPoint(keyGrab,transform.position);  //播放执起声效
            playerInventory.AddKey(keyId);  //设置的id号对应 钥匙  跟 门 是配对
            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>
    /// 触发器逗留
    /// </summary>
    void OnTriggerStay(Collider other) {
       // Debug.Log("进入激光墙触发");
        if (other.gameObject==player&&Time.time>lastDamageTime+damageDelay)
        {
            player.GetComponent<fps_PlayerHealth>().TakeDamage(damage); //执行玩家受伤害的方法
            lastDamageTime = Time.time; //确认当前时间
        }
    }

}

fps_PlayerControl

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

/// <summary>
/// 玩家4种状态
/// </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>
    /// 更新有移动
    /// </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>
    /// 玩家当前速度管理
    /// </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>
    /// 更新蹲伏状态
    /// </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; //设置为0  没有显示红色的区域
    }
    
    
    void Update () {
        if (!isDead)
        {
            hp += recoverSpeed * Time.deltaTime; //恢复时间
            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>
    /// 不能继续输入
    /// </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号
/// </summary>
public class fps_PlayerInventory : MonoBehaviour {

    private List<int> keyArr;

    void Start () {

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

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

    }


    /// <summary>
    /// 对应门ID号确认是否可以打开
    /// </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>
/// 玩家输入参数的封装
/// </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>
/// 动画哈希值 
/// </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>
/// 无人机攻击脚本
/// </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 ; //间隔计时器 冷却时间
    private bool canAttack = false; //是否到达攻击范围
    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); //重置冷却时间
            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>
/// 无人机移动
/// </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; //回退系数
    public float oriantationMultiplier = 2.5f;   //旋转系数
    public Vector3 moveTarget; //追踪目标

    private Transform player;
    private Rigidbody rigi;
    private Vector3 smoothDirection = Vector3.zero;  //使移动更平滑


    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(); //平滑归零 避免越来越大
        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>
    /// 旋转角度
    /// </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>
    /// 无人机受到攻击
    /// </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>
    /// 进入视野范围
    /// </summary>
    void OnTriggerEnter(Collider collider) {

        Debug.Log("进入无人机视野范围");
        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;//爆炸预制体
    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;
        //达到指定距离后就不在播放动画 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; //移动速度

    [HideInInspector]
    public Vector3 moveDirection;  //移动方向
    [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>
    /// 旋转角度
    /// </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);

    }
}

三、效果图

3600969-920797dfd446baeb.png
3600969-f0b22d611ecad53a.png
3600969-88739cd73856af18.png
3600969-eb10cbf43931a99a.png
3600969-663107b30da90e72.png
3600969-ad4a9339c82dc03f.png
3600969-1c5695853730f902.png

猜你喜欢

转载自blog.csdn.net/weixin_34101229/article/details/87517853