消灭病毒gamedemo

 

DestoryVirus

一、AudioSourceManager 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class AudioSourceManager : MonoBehaviour
{public  static AudioSourceManager Instance { get; private set; }public SoundPlayer soundPlayer;// Start is called before the first frame updatevoid Start(){Instance = this;PoolManager.Instance.InitPool(soundPlayer,20);}public void playSound(AudioClip audioClip,float pitchMin=1,float pitchMax=1){PoolManager.Instance.GetInstance<SoundPlayer>(soundPlayer).PlayClip(audioClip,pitchMin,pitchMax);}
}

二、BloodCell 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BloodCell : Enemy
{public int addValue;//加血public AudioClip audioClip;protected override void OnCollisionEnter(Collision collision){base.OnCollisionEnter(collision);if (collision.transform.tag=="Player"){AudioSourceManager.Instance.playSound(audioClip);playerTrans.GetComponent<DoctorController>().TakeDamage(-addValue);gameObject.SetActive(false);}}public override void TakeDamage(float damageValue){base.TakeDamage(damageValue);if (currentHealth<=0){AudioSourceManager.Instance.playSound(audioClip);playerTrans.GetComponent<DoctorController>().TakeDamage(-addValue);}}
}

三、Boss 

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Boss : Enemy
{protected Animator animator;protected bool isWaking;protected bool isDead;//是否死亡public Light pointLight;private bool isAngryState;public bool hasSkill;//是否有技能public AnimationClip attackAnimationClip;public float attackSpeed;public GameObject keyGo;public float takeDamageTime;private float takeDamageTimer;public AudioClip deadClip;// public Transform targetTrans;protected override void Start(){base.Start();animator = GetComponentInChildren<Animator>();animator.SetFloat("Born", -0.5f);currentState = ENEMYSTATE.IDLE;//float result= Vector3.Dot(transform.forward, targetTrans.position - transform.position);//if (result>0)//{//    Debug.Log("在前方");//}//else//{//    Debug.Log("在后方");//}//float result = Vector3.Cross(transform.forward, targetTrans.position).y;//float result = Vector3.Dot(transform.right, targetTrans.position);//if (result<0)//{//    Debug.Log("在左方");//}//else//{//    Debug.Log("在右方");//}currentMoveSpeed = moveSpeed;       if (attackAnimationClip!=null){animator.SetFloat("AttackSpeed",attackSpeed);actRestTime = attackAnimationClip.length / attackSpeed;}else{animator.SetFloat("AttackSpeed", 1);}takeDamageTimer = takeDamageTime;}protected override void Update(){if (isDead){transform.Translate(-Vector3.up * Time.deltaTime * moveSpeed);pointLight.intensity -= Time.deltaTime*2;if (transform.position.y<=-10){Destroy(gameObject);}return;}takeDamageTimer -= Time.deltaTime;base.Update();}protected override void EnemyAct(){if (isWaking||isDead){return;}base.EnemyAct();switch (currentState){case ENEMYSTATE.PATROL:break;case ENEMYSTATE.CHASE://animator.ResetTrigger("Hit");animator.ResetTrigger("Attack");if (hasSkill){animator.ResetTrigger("UseSkill");}animator.SetBool("Moving", true);if (isAngryState){animator.SetFloat("MoveSpeed", 1);currentMoveSpeed=moveSpeed*3;}break;case ENEMYSTATE.ATTACK:animator.SetBool("Moving", false);animator.ResetTrigger("Hit");if (isAngryState&&hasSkill){animator.SetTrigger("UseSkill");}else{animator.SetTrigger("Attack");}break;case ENEMYSTATE.RETURN:animator.SetBool("Moving", true);animator.ResetTrigger("Hit");break;case ENEMYSTATE.IDLE:animator.SetBool("Moving", false);break;case ENEMYSTATE.WARN://  animator.ResetTrigger("Hit");break;case ENEMYSTATE.USESKILL:break;default:break;}}/// <summary>/// 苏醒/// </summary>protected void Warn(){if (isWaking){return;}float wakeValue = animator.GetFloat("Born");if (wakeValue<0)//还没苏醒过{animator.SetFloat("Born",1);isWaking = true;Invoke("FinishWaking",9);animator.Play("Born", 0, 0);}else{animator.SetTrigger("Roar");transform.LookAt(new Vector3(playerTrans.position.x, transform.position.y, playerTrans.position.z));}}/// <summary>/// 完成苏醒/// </summary>private void FinishWaking(){animator.ResetTrigger("Hit");isWaking = false;}protected override void CheckDistance(){if (currentState == ENEMYSTATE.RETURN||isWaking||isDead){return;}float distance = Vector3.Distance(playerTrans.position, transform.position);if (distance<1.5*chaseRange&&currentState!=ENEMYSTATE.WARN&&currentState!=ENEMYSTATE.ATTACK&&currentState!=ENEMYSTATE.CHASE){Warn();currentState = ENEMYSTATE.WARN;}if (distance <= attackRange && enemyFunction.canAttack){currentState = ENEMYSTATE.ATTACK;}else if (distance <= chaseRange && enemyFunction.canChase){currentState = ENEMYSTATE.CHASE;}else if (distance >= safeRange && enemyFunction.canReturn){if (currentState == ENEMYSTATE.CHASE&&enemyFunction.canChase){currentState = ENEMYSTATE.RETURN;}}}protected override void ReturnToInitPos(){if (!CanMove()){return;}currentHealth = initHealth;if (Vector3.Distance(transform.position,initPos)<=2){currentState = ENEMYSTATE.IDLE;isAngryState = false;transform.eulerAngles = new Vector3(0, 180, 0);currentMoveSpeed = moveSpeed;chaseRange = initChaseRange;safeRange = initSafeRange;return;}transform.Translate(transform.forward * Time.deltaTime * currentMoveSpeed,Space.World);transform.LookAt(new Vector3(initPos.x,transform.position.y,initPos.z));}public void TakeDamage(float damageValue,Vector3 hitPos){if (isWaking||isDead){return;}currentHealth -= damageValue;base.RecoverAttackRangeValue();if (currentState==ENEMYSTATE.IDLE||currentState==ENEMYSTATE.WARN){chaseRange = initChaseRange * 2;safeRange = initSafeRange * 1.5f;}if (currentHealth<=initHealth/3&&!isAngryState){isAngryState = true;}if (takeDamageTimer<=0){if (soundPlayer != null){soundPlayer.PlayRandomSound();}else{AudioSourceManager.Instance.playSound(hurtClip);}animator.SetTrigger("Hit");animator.SetFloat("HitY", 0);animator.SetFloat("HitX", 0);float y = Vector3.Dot(transform.forward, hitPos - transform.position);float x = Vector3.Dot(transform.right, hitPos);Debug.Log("x:" + x);Debug.Log("y:" + y);if (ForwardBehindOrLeftRight(hitPos)){if (y > 0){Debug.Log("在前方");animator.SetFloat("HitY", 1);}else{Debug.Log("在后方");animator.SetFloat("HitY", -1);}}else{if (x > 0){Debug.Log("在右方");animator.SetFloat("HitX", 1);}else{Debug.Log("在左方");animator.SetFloat("HitX", -1);}}takeDamageTimer = takeDamageTime;}if (currentHealth>0){return;}AudioSourceManager.Instance.playSound(deadClip);animator.SetTrigger("Die");isDead = true;keyGo.SetActive(true);keyGo.transform.position = transform.position+new Vector3(0,2,0);rigid.isKinematic = true;rigid.constraints = RigidbodyConstraints.FreezeAll;}/// <summary>/// 判断前后或者左右影响度(true前后优先级更高,false左右优先级更高)/// </summary>/// <param name="targetPos"></param>/// <returns></returns>private bool ForwardBehindOrLeftRight(Vector3 targetPos){float ZDistance =Mathf.Abs(transform.position.z - targetPos.z);float XDistance = Mathf.Abs(transform.position.x - targetPos.x);if (ZDistance>=XDistance){return true;}else{return false;}}protected override void Attack(){if (Time.time-lastActTime<attackRange){return;}lastActTime = Time.time;transform.LookAt(new Vector3(playerTrans.position.x, playerTrans.position.y,playerTrans.position.z));}protected bool CanMove(){return animator.GetCurrentAnimatorStateInfo(0).shortNameHash != Animator.StringToHash("Attack") &&animator.GetCurrentAnimatorStateInfo(0).shortNameHash != Animator.StringToHash("Hit") &&animator.GetCurrentAnimatorStateInfo(0).shortNameHash != Animator.StringToHash("Boar")&&animator.GetCurrentAnimatorStateInfo(0).shortNameHash != Animator.StringToHash("UseSkill");}protected override void Chase(){if (!CanMove()){return;}transform.LookAt(new Vector3(playerTrans.position.x, playerTrans.position.y, playerTrans.position.z));transform.Translate(transform.forward * Time.deltaTime * currentMoveSpeed, Space.World);}
}

四、BossBehavior

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BossBehavior : MonoBehaviour
{public GameObject bossWeaponViewGo;//Boss武器的显示private Transform playerTrans;public GameObject skillWeapon;//Boss技能的武器 (具体与玩家交互的各种技能游戏物体)public Transform attackTrans;//攻击位置public AudioClip skillClip;// Start is called before the first frame updatevoid Start(){playerTrans = GameObject.FindGameObjectWithTag("Player").transform;if (skillWeapon!=null){PoolManager.Instance.InitPool(skillWeapon, 10);}}private void ShowWeapon(){bossWeaponViewGo.SetActive(true);}private void HideWeapon(){bossWeaponViewGo.SetActive(false);}/// <summary>/// 隐藏/// </summary>private void CreatSkillBall(){bossWeaponViewGo.SetActive(false);GameObject go= PoolManager.Instance.GetInstance<GameObject>(skillWeapon);go.SetActive(true);go.transform.SetParent(null);go.transform.position = attackTrans.position;go.transform.LookAt(playerTrans.position);transform.parent.LookAt(playerTrans.position);AudioSourceManager.Instance.playSound(skillClip);}
}

五、BossWeapon

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class BossWeapon : MonoBehaviour
{public int damageValue=10;//伤害值private DoctorController doctorController;public float moveSpeed = 5;//public Vector3 targetPos;private float destoryTime=10;//销毁计时器private float timeVal;public ParticleSystem destoryEffect; //特效引用public bool canMove;//是否可以移动private bool canTakeDamage;//开关private float damageTimeVal;public float initDamageTime = 2;public bool isSmoke;//烟雾// Start is called before the first frame updatevoid Start(){doctorController =GameObject.FindGameObjectWithTag("Player").GetComponent<DoctorController>();if (destoryEffect!=null){PoolManager.Instance.InitPool(destoryEffect, 10);}damageTimeVal = initDamageTime;// transform.LookAt(targetPos);}// Update is called once per framevoid Update(){//技能型武器if (damageTimeVal<=0){canTakeDamage = true;damageTimeVal = initDamageTime;}else{damageTimeVal -= Time.deltaTime;}//近战武器if (canMove){return;}//远程武器transform.Translate(transform.forward * moveSpeed * Time.deltaTime, Space.World);if (timeVal>=destoryTime){gameObject.SetActive(false);//隐藏gameObject.transform.SetParent(PoolManager.Instance.transform);timeVal = 0;}else{timeVal += Time.deltaTime;}}private void OnTriggerEnter(Collider other){if (other.tag=="Player"){doctorController.TakeDamage(damageValue);if (destoryEffect!=null){ParticleSystem particleSystem= PoolManager.Instance.GetInstance<ParticleSystem>(destoryEffect);particleSystem.gameObject.SetActive(true);particleSystem.transform.position = transform.position;particleSystem.time = 0;particleSystem.Play();} if (canMove){gameObject.transform.SetParent(PoolManager.Instance.transform);timeVal = 0;}if (isSmoke){if (canTakeDamage){doctorController.TakeDamage(damageValue);canTakeDamage = false;damageTimeVal = initDamageTime;}}else{doctorController.TakeDamage(damageValue);gameObject.SetActive(false);//隐藏}}}private void OnTriggerStay(Collider other){if (other.tag == "Player"){if (canTakeDamage){doctorController.TakeDamage(damageValue);canTakeDamage = false;damageTimeVal = initDamageTime;}}}private void OnTriggerExit(Collider other){if (other.tag=="Player"){canTakeDamage = true;damageTimeVal = initDamageTime;}     }
}

 六、CameraShaker

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class CameraShaker : MonoBehaviour
{private Vector3 initPosition;private float remainingShakeTime;private float shakeStrength;// Start is called before the first frame updatevoid Start(){initPosition = transform.localPosition;}// Update is called once per framevoid Update(){if (remainingShakeTime>0){remainingShakeTime -= Time.deltaTime;if (remainingShakeTime<=0){transform.localPosition = initPosition;}else{Vector3 randomDir = Random.insideUnitSphere;transform.localPosition = initPosition + shakeStrength*randomDir;}}}public void SetShakeValue(float shakeTime,float strength){remainingShakeTime = shakeTime;shakeStrength = strength;}
}

七、DoctorController

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;public class DoctorController : MonoBehaviour
{private CharacterController characterController;public float moveSpeed;public float mouseSensitivity;//角度值private float angleY;private float angleX;private Transform cameraTrans;public float runningSpeed;private bool isGrounded;public float jumpSpeed;private CollisionFlags collisionFlags;public int currentWeaponID;private Dictionary<int,Weapon> weaponsDict;private Transform weaponPlaceTrans;private Dictionary<int, int> ammoInventory;//玩家的装备库(背包,当前玩家剩余某个武器以及其剩余的子弹数量)public int currentHP;//当前HPpublic int initHP;//初始HPpublic float decreaseSpeed;public float actualSpeed;public CameraShaker cameraShaker;public bool dead;public Transform deadPositionTrans;public AudioClip jumoClip;public AudioClip landClip;private bool canPlayLandClip;public AudioClip deadClip;public AudioClip hurtClip;public Weapon[] weapons;public GameObject gameOverPanel;// Start is called before the first frame updatevoid Start(){characterController= GetComponent<CharacterController>();moveSpeed = 5;mouseSensitivity = 2.4f;angleY = transform.eulerAngles.y;cameraTrans = Camera.main.transform;angleX = cameraTrans.eulerAngles.x;//Cursor.visible = false;//Cursor.lockState = CursorLockMode.Locked;runningSpeed = 10;jumpSpeed = 0;isGrounded = true;currentWeaponID = -1;weaponPlaceTrans = cameraTrans.Find("WeaponPlace");//weapons = new List<Weapon>()//{//        weaponPlaceTrans.GetChild(0).GetComponent<Weapon>(),//        weaponPlaceTrans.GetChild(1).GetComponent<Weapon>(),//        weaponPlaceTrans.GetChild(2).GetComponent<Weapon>(),//};weaponsDict = new Dictionary<int, Weapon>();ammoInventory = new Dictionary<int, int>();currentHP = initHP;UIManager.Instance.ShowOrHideWeaponUIView(false);for (int i = 0; i < weapons.Length; i++){weapons[i].gameObject.SetActive(false);weapons[i].PickUp(this);}}// Update is called once per framevoid Update(){if (dead){return;}Move();TurnAndLook();Jump();ChangeCurrentWeapon();}/// <summary>/// 移动/// </summary>private void Move(){actualSpeed = Input.GetButton("Run") ? runningSpeed - decreaseSpeed : moveSpeed - decreaseSpeed;Vector3 move = Vector3.zero;float h = Input.GetAxis("Horizontal");float v = Input.GetAxis("Vertical");move = new Vector3(h, 0, v);move.Normalize();move = move * actualSpeed * Time.deltaTime;move = transform.TransformDirection(move);collisionFlags = characterController.Move(move);if (h < -0.1f && v <= 0.1f){actualSpeed = 0;}}/// <summary>/// 转向和上下看/// </summary>private void TurnAndLook(){if (GameManager.Instance.isGameing == true){float turnAngle = Input.GetAxis("Mouse X") * mouseSensitivity;angleY = angleY + turnAngle;transform.eulerAngles = new Vector3(transform.eulerAngles.x, angleY, transform.eulerAngles.z);float lookAngle = -Input.GetAxis("Mouse Y") * mouseSensitivity;angleX = Mathf.Clamp(angleX + lookAngle, -90f, 90f);cameraTrans.eulerAngles = new Vector3(angleX, cameraTrans.eulerAngles.y, cameraTrans.eulerAngles.z);}}/// <summary>/// 跳跃方法/// </summary>private void Jump(){if (Input.GetButton("Jump")){isGrounded = false;jumpSpeed = 5;AudioSourceManager.Instance.playSound(jumoClip,0.8f,1.1f);canPlayLandClip = true;}if (!isGrounded)//跳起来了,不在地面上{jumpSpeed  = jumpSpeed - 10 * Time.deltaTime;Vector3 jump = new Vector3(0, jumpSpeed * Time.deltaTime, 0);collisionFlags= characterController.Move(jump);if (collisionFlags==CollisionFlags.Below){jumpSpeed = 0;isGrounded = true;}}if (isGrounded&&collisionFlags==CollisionFlags.None){if (canPlayLandClip){canPlayLandClip = false;AudioSourceManager.Instance.playSound(landClip, 0.8f, 1.1f);}isGrounded = false;}}/// <summary>/// 具体切换武器/// </summary>/// <param name="id"></param>private void ChangeWeapon(int id){if (weaponsDict.Count==0){return;}处理索引的上下边界//if (id>= weaponsDict.Count)//{//    id = 0;//}//else if (id<=-1)//{//    id = weaponsDict.Count - 1;//}if (id>weaponsDict.Keys.Max()){id = weaponsDict.Keys.Min();}else if (id<weaponsDict.Keys.Min()){id = weaponsDict.Keys.Max();}if (id==currentWeaponID)//只有一种武器时不切换,否则会出现颠簸颤抖的情况{return;}while (!weaponsDict.ContainsKey(id)){if (id>currentHP){id++;}else{id--;}}//隐藏上一把武器if (currentWeaponID!=-1)//排除第一次没有武器的情况{weaponsDict[currentWeaponID].PutAway();}//显示当前武器weaponsDict[id].Selected();currentWeaponID = id;}/// <summary>/// 切换当前武器/// </summary>public void ChangeCurrentWeapon(bool aut0Change=false){if (aut0Change){//切换到最新拿到的一把//ChangeWeapon(weaponsDict.Count-1);ChangeWeapon(weaponsDict.Keys.Last());}else{if (Input.GetAxis("Mouse ScrollWheel") < 0){ChangeWeapon(currentWeaponID + 1);}else if (Input.GetAxis("Mouse ScrollWheel") > 0){ChangeWeapon(currentWeaponID - 1);}for (int i = 0; i < 10; i++){if (Input.GetKeyDown(KeyCode.Alpha0 + i)){int num = 0;if (i == 0){num = 10;}else{num = i - 1;}if (weaponsDict.ContainsKey(num)){ChangeWeapon(num);}}}}}/// <summary>/// 拾取武器/// </summary>/// <param name="weaponName"></param>public void PickUpWeapon(int weaponID){if (weaponsDict.ContainsKey(weaponID)){//补充弹药Weapon weapon = weaponsDict[weaponID];ammoInventory[weapon.GetID()] = weapon.GetInitAmount();weapon.clipContent = weapon.clipSize;if (currentWeaponID==weaponID){UIManager.Instance.UpdateBulletNum(weapon.clipSize, weapon.GetInitAmount());}//if (!weapon.HasBullet())//{//    weapon.Reload();//}}else//当前这种名称的武器列表里没有{//GameObject weaponGo= Instantiate(Resources.Load<GameObject>("Prefabs/Weapons/"+weaponID.ToString()));// weaponGo.transform.SetParent(weaponPlaceTrans);// weaponGo.transform.localPosition = Vector3.zero;// weaponGo.transform.localRotation = Quaternion.identity;// weaponGo.gameObject.SetActive(false);// Weapon weapon = weaponGo.GetComponent<Weapon>();//weapon.PickUp(this);weapons[weaponID].clipContent = weapons[weaponID].clipSize;weaponsDict.Add(weaponID,weapons[weaponID]);ammoInventory.Add(weaponID, weapons[weaponID].GetInitAmount());ChangeWeapon(weaponID);}}/// <summary>/// 获取某一种武器在武器库中子弹的剩余数量/// </summary>/// <param name="id"></param>/// <returns></returns>public int GetAmmoAmount(int id){int value = 0;ammoInventory.TryGetValue(id, out value);return value;}/// <summary>/// 更新当前武器库中某一种武器装备剩余子弹的数量/// </summary>/// <param name="id"></param>/// <param name="value"></param>public void UpdateAmmoAmount(int id,int value){if (ammoInventory.ContainsKey(id)){ammoInventory[id] += value;}}/// <summary>/// 受伤害/// </summary>/// <param name="value"></param>public void TakeDamage(int value){if (dead){return;}        if (value<0){if (currentHP<initHP){currentHP -= value;if (currentHP>=initHP){currentHP = initHP;}}         }else{currentHP -= value;}if (currentHP<=0){dead = true;gameOverPanel.SetActive(true);cameraTrans.localPosition = deadPositionTrans.localPosition;cameraTrans.eulerAngles = deadPositionTrans.eulerAngles;weaponPlaceTrans.gameObject.SetActive(false);currentHP = 0;UIManager.Instance.ShowDeadUI();AudioSourceManager.Instance.playSound(deadClip);}else{if (value>0){AudioSourceManager.Instance.playSound(hurtClip);UIManager.Instance.ShowTakeDamageView();cameraShaker.SetShakeValue(0.2f, 0.5f);}}UIManager.Instance.UpdateHPValue(currentHP);}
}

八、Door

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Door : MonoBehaviour
{public GameObject keyGo;private bool unLocked;//是否打开public float moveSpeed;//public SoundPlayer soundPlayer;public AudioClip openDoorClip;public AudioClip cantOpenClip;public AudioClip doorClip;private void OnTriggerEnter(Collider other){if (other.transform.tag == "Player"){if (!unLocked){if (keyGo == null){unLocked = true;AudioSourceManager.Instance.playSound(openDoorClip);AudioSourceManager.Instance.playSound(doorClip);}else{AudioSourceManager.Instance.playSound(cantOpenClip);}}}}private void Update(){if (unLocked){//soundPlayer.PlaySound(true);transform.Translate(-Vector3.up * Time.deltaTime * moveSpeed * 0.3f);if (transform.position.y <= -1.4){Destroy(gameObject);}}}}

九、Enemy

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Enemy : MonoBehaviour
{public float initHealth = 10;public float currentHealth;//生命值Spublic ParticleSystem destoryEffect;public ENEMYSTATE currentState;//敌人状态public float moveSpeed;protected float lastActTime;public float actRestTime;//行为转换的CD,攻击时长private Quaternion targetRotation;protected Vector3 initPos;public EnemyFunction enemyFunction;protected Transform playerTrans;public float attackRange;//攻击距离public float chaseRange;//追逐距离public float safeRange;//安全距离protected Rigidbody rigid;protected float currentMoveSpeed;//目前移动速度protected float initChaseRange;//初始追赶范围protected float initSafeRange;protected float initAttackRange;public GameObject smokeColliderGo;public SoundPlayer soundPlayer;public AudioClip hurtClip;public AudioClip attackClip;private float canTurnTimer;// Start is called before the first frame updateprotected virtual void Start(){if (destoryEffect){PoolManager.Instance.InitPool(destoryEffect, 4);}currentHealth = initHealth;currentState = ENEMYSTATE.PATROL;initPos = transform.position;playerTrans = GameObject.FindGameObjectWithTag("Player").transform;//  playerTrans = GameObject.Find("Doctor").transform;rigid = GetComponent<Rigidbody>();initSafeRange = safeRange;initChaseRange = chaseRange;initAttackRange = attackRange;currentMoveSpeed = moveSpeed;canTurnTimer = Time.time;}// Update is called once per frameprotected virtual void Update(){EnemyAct();CheckDistance();}/// <summary>/// 受伤/// </summary>/// <param name="damageValue">伤害值</param>public virtual void TakeDamage(float damageValue){currentHealth -= damageValue;      RecoverAttackRangeValue();if (soundPlayer!=null){soundPlayer.PlayRandomSound();}else{AudioSourceManager.Instance.playSound(hurtClip);}if (currentHealth>0){return;}if (destoryEffect){ParticleSystem ps = PoolManager.Instance.GetInstance<ParticleSystem>(destoryEffect);ps.time = 0;ps.Play();ps.transform.position = transform.position+new Vector3(0,0.5f,0);}gameObject.SetActive(false);}/// <summary>/// 敌人动作/// </summary>protected virtual void EnemyAct(){switch (currentState){case ENEMYSTATE.PATROL:Move();if (Time.time-lastActTime>actRestTime){lastActTime = Time.time;targetRotation = Quaternion.Euler(GetRandomEuler());}break;case ENEMYSTATE.CHASE:Chase();break;case ENEMYSTATE.ATTACK:Attack();break;case ENEMYSTATE.RETURN:break;default:break;}}private void Move(){transform.Translate(transform.forward*Time.deltaTime*currentMoveSpeed,Space.World);transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation,0.01f);}protected virtual void OnCollisionEnter(Collision collision){if (currentState==ENEMYSTATE.PATROL&&collision.gameObject.layer!=11&&Time.time-canTurnTimer>5){canTurnTimer = Time.time;targetRotation = Quaternion.LookRotation(-transform.forward,transform.up);lastActTime = Time.time;}else if (currentState==ENEMYSTATE.CHASE||currentState==ENEMYSTATE.RETURN||currentState==ENEMYSTATE.ATTACK){rigid.isKinematic = true;Invoke("CloseIsKinematicState",1);}}private void CloseIsKinematicState(){rigid.isKinematic = false;}protected virtual void ReturnToInitPos(){transform.Translate(transform.forward * Time.deltaTime * currentMoveSpeed, Space.World);transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, 0.1f);if (Vector3.Distance(transform.position,initPos)<=1){currentState = ENEMYSTATE.PATROL;}}/// <summary>/// 检测与某一个对象的距离并转换敌人的状态/// </summary>protected virtual void CheckDistance(){if (currentState==ENEMYSTATE.RETURN){return;}float distance = Vector3.Distance(playerTrans.position, transform.position);if (distance <= attackRange&&enemyFunction.canAttack){currentState = ENEMYSTATE.ATTACK;}else if (distance <= chaseRange&&enemyFunction.canChase){currentState = ENEMYSTATE.CHASE;}else if (distance>=safeRange&&enemyFunction.canReturn){if (currentState==ENEMYSTATE.PATROL&&Vector3.Distance(transform.position, initPos) >= 8){currentState = ENEMYSTATE.RETURN;targetRotation = Quaternion.LookRotation(initPos - transform.position, transform.up);}else if (currentState==ENEMYSTATE.CHASE){currentState = ENEMYSTATE.RETURN;targetRotation = Quaternion.LookRotation(initPos - transform.position, transform.up);}}}private Vector3 GetRandomEuler(){float x = 0, y = 0, z = 0;if (enemyFunction.canRotateX){x = Random.Range(1, 5) * 90;}if (enemyFunction.canRotateY){y = Random.Range(1, 5) * 90;}if (enemyFunction.canRotateZ){z = Random.Range(1, 5) * 90;}return new Vector3(x, y, z);}/// <summary>/// 追逐方法/// </summary>protected virtual void Chase(){transform.LookAt(playerTrans);transform.Translate(transform.forward * Time.deltaTime * currentMoveSpeed, Space.World);}/// <summary>/// 攻击方法/// </summary>protected virtual void Attack(){Debug.Log(gameObject.name + "正在攻击!");}/// <summary>/// 设置烟雾距离/// </summary>public void SetRange(float value){attackRange = chaseRange = value;currentState = ENEMYSTATE.IDLE;}/// <summary>/// 恢复/// </summary>public void RecoverAttackRangeValue(){attackRange = initAttackRange;chaseRange = initChaseRange;if (enemyFunction.canPatrol){currentState = ENEMYSTATE.PATROL;}}/// <summary>/// 用于烟雾弹检测/// </summary>/// <param name="state"></param>public void SetSmokeCollierState(bool state){smokeColliderGo.SetActive(state);}
}public enum ENEMYSTATE
{PATROL,//巡逻CHASE,//追逐ATTACK,RETURN,//BOSSIDLE,WARN,//警戒状态(播放动画,看向玩家)// WAKE,//出生状态,觉醒状态(第一次遇到玩家)USESKILL//使用技能
}
[System.Serializable]
public struct EnemyFunction
{public bool canPatrol;public bool canChase;public bool canAttack;public bool canReturn;public bool canRotateX;public bool canRotateY;public bool canRotateZ;
}

十、GameManager

using System.Collections;
using System.Collections.Generic;
using UnityEditor.Timeline;
using UnityEngine;
using UnityEngine.SceneManagement;
using static UnityEditor.FilePathAttribute;public class GameManager : MonoBehaviour
{public static GameManager Instance { get; private set; }public bool isGameing = false;private void Awake(){Instance = this;Cursor.visible = true;Cursor.lockState = CursorLockMode.None;}// Start is called before the first frame updatevoid Start(){Time.timeScale = 0f;}// Update is called once per framevoid Update(){}public void StartGameBtn(){Cursor.visible = false;Cursor.lockState = CursorLockMode.Locked;Time.timeScale = 1.0f;isGameing = true;}public void ReStartBtn(){SceneManager.LoadScene(0);}public void ExitGameBtn(){UnityEditor.EditorApplication.isPlaying = false;Application.Quit();}public void ReTime() {}}

十一、GameSuccessTiger

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GameSuccessTiger : MonoBehaviour
{public GameObject gameScuessPanel;public void OnTriggerEnter(Collider other){Cursor.visible = true;Cursor.lockState = CursorLockMode.None;gameScuessPanel.SetActive(true);GameManager.Instance.isGameing = false;}
}

十二、GermSlime

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GermSlime : Enemy
{public int damageValue;protected override void Attack(){if (Time.time-lastActTime<actRestTime){return;}transform.LookAt(playerTrans);lastActTime = Time.time;playerTrans.GetComponent<DoctorController>().TakeDamage(damageValue);}
}

十三、GermSpike

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class GermSpike : Enemy
{public GameObject explosionEffect;//爆炸特效public int damageValue;//伤害值// Start is called before the first frame updateprotected override void Start(){base.Start();PoolManager.Instance.InitPool(explosionEffect,1);}// Update is called once per frameprotected override void Attack(){base.Attack();if (Time.time - lastActTime < actRestTime){return;}transform.LookAt(playerTrans);lastActTime = Time.time;playerTrans.GetComponent<DoctorController>().TakeDamage(damageValue);GameObject effect = PoolManager.Instance.GetInstance<GameObject>(explosionEffect);effect.transform.position = transform.position;effect.transform.localScale = Vector3.one * 3;effect.SetActive(true);}
}

十四、Key

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Key : MonoBehaviour
{public float rotateSpeed;public AudioClip pickupClip;//public Door door;// Start is called before the first frame updatevoid Start(){rotateSpeed = 50;}// Update is called once per framevoid Update(){transform.eulerAngles += new Vector3(0, rotateSpeed * Time.deltaTime, 0);}private void OnTriggerEnter(Collider other){if (other.tag=="Player"){// door.OpenDoor();AudioSourceManager.Instance.playSound(pickupClip);Destroy(gameObject);}}}

十五、PickUpItem

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PickUpItem : MonoBehaviour
{public float rotateSpeed;public int itemID=-1;public AudioClip pickupClip;// Start is called before the first frame updatevoid Start(){rotateSpeed = 50;}// Update is called once per framevoid Update(){transform.eulerAngles += new Vector3(0, rotateSpeed * Time.deltaTime, 0);}private void OnTriggerEnter(Collider other){if (other.name== "Doctor"){DoctorController doctorController = other.GetComponent<DoctorController>();doctorController.PickUpWeapon(itemID);//doctorController.ChangeCurrentWeapon(true);AudioSourceManager.Instance.playSound(pickupClip);Destroy(gameObject);}}
}

十六、PoolManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PoolManager : MonoBehaviour
{public static PoolManager Instance { get; private set; }//通过传入类型找到对应的池子private Dictionary<Object, Queue<Object>> poolsDict;private void Awake(){Instance = this;poolsDict = new Dictionary<Object, Queue<Object>>();}/// <summary>/// 初始化某一个对象池/// </summary>/// <param name="prefab">指定预制体的类型</param>/// <param name="size">当前对应类型的对象池的长度</param>public void InitPool(Object prefab,int size){if (poolsDict.ContainsKey(prefab)){return;}Queue<Object> queue = new Queue<Object>();for (int i = 0; i < size; i++){Object go=Instantiate(prefab);CreatGameObjectAndSetActive(go,false);queue.Enqueue(go);}poolsDict[prefab] = queue;}private void CreatGameObjectAndSetActive(Object obj,bool active){GameObject itemGo = null;if (obj is Component){Component component = obj as Component;itemGo = component.gameObject;}else{itemGo= obj as GameObject;}itemGo.transform.SetParent(transform);itemGo.SetActive(active);}public T GetInstance<T>(Object prefab)where T:Object{Queue<Object> queue;if (poolsDict.TryGetValue(prefab,out queue )){Object obj;if (queue.Count>0){obj= queue.Dequeue();}else{obj = Instantiate(prefab);}CreatGameObjectAndSetActive(obj, true);queue.Enqueue(obj);return obj as T;}Debug.LogError("还没有当前的资源池被实例化");return null;}
}

十七、Projectile

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Projectile : MonoBehaviour
{private Rigidbody rigid;public ParticleSystem explosionEffect;public float destoryTime;private float destoryTimer;public bool destoryOnHit;public float explosionRadius;//爆炸半径private Collider[] sphereCastPool;//当前检测到的爆炸范围内的敌人public float damageValue;//伤害值public ParticleSystem bulletTrailEffect;public ParticleSystem bulletSizeParticle;//如果子弹是粒子且需要变换大小public AudioClip hitWallClip;public AudioClip explosionClip;// Start is called before the first frame updatevoid Awake(){rigid = GetComponent<Rigidbody>();destoryTime = 3;PoolManager.Instance.InitPool(explosionEffect, 4);sphereCastPool = new Collider[10];if (bulletTrailEffect!=null){bulletTrailEffect.time = 0;bulletTrailEffect.Play();}}// Update is called once per framevoid Update(){destoryTimer += Time.deltaTime;if (destoryTimer>destoryTime){if (destoryOnHit){DestoryProjectile();}else{DestoryExplosionProjectile();}}}/// <summary>/// 子弹发射/// </summary>/// <param name="laucher">发射器</param>/// <param name="direction">发射方向</param>/// <param name="force">发射力的大小</param>public void Launch(Weapon laucher,Vector3 direction,float force){transform.position = laucher.GetShootPoint().position;transform.forward = laucher.GetShootPoint().forward;rigid.AddForce(direction * force);}private void DestoryExplosionProjectile(){if (explosionEffect!=null){ParticleSystem effect = PoolManager.Instance.GetInstance<ParticleSystem>(explosionEffect);effect.transform.position = transform.position;effect.gameObject.SetActive(true);effect.time = 0;effect.Play();}     gameObject.SetActive(false);rigid.velocity = Vector3.zero;rigid.angularVelocity = Vector3.zero;gameObject.transform.rotation = Quaternion.identity;destoryTimer = 0;if (damageValue>0){int count = Physics.OverlapSphereNonAlloc(transform.position, explosionRadius, sphereCastPool, 1 << 9);for (int i = 0; i < count; i++){sphereCastPool[i].GetComponent<Enemy>().TakeDamage(damageValue);}int bossCount = Physics.OverlapSphereNonAlloc(transform.position, explosionRadius, sphereCastPool, 1 << 10);if (bossCount > 0){sphereCastPool[0].GetComponentInParent<Boss>().TakeDamage(damageValue, transform.position);}}   AudioSourceManager.Instance.playSound(explosionClip);}private void DestoryProjectile(GameObject enemyGo=null){if (explosionEffect != null){ParticleSystem effect = PoolManager.Instance.GetInstance<ParticleSystem>(explosionEffect);effect.transform.position = transform.position;effect.gameObject.SetActive(true);effect.time = 0;effect.Play();}gameObject.SetActive(false);rigid.velocity = Vector3.zero;rigid.angularVelocity = Vector3.zero;gameObject.transform.rotation = Quaternion.identity;destoryTimer = 0;TakeDamage(enemyGo);}private void OnCollisionEnter(Collision collision){if (destoryOnHit){DestoryProjectile(collision.gameObject);}}private void OnTriggerEnter(Collider other){if (destoryOnHit){DestoryProjectile(other.gameObject);          }}/// <summary>/// 设置聚能枪子弹大小/// </summary>public void SetBulletSize(float size){bulletSizeParticle.startSize = size;}/// <summary>/// 设置伤害值/// </summary>public void SetBulletDamageValue(float value){damageValue = value;}/// <summary>/// 伤害/// </summary>private void TakeDamage(GameObject enemyGo=null){if (enemyGo!=null){if (enemyGo.layer==9){enemyGo.GetComponent<Enemy>().TakeDamage(damageValue);}else if (enemyGo.layer==10){enemyGo.GetComponentInParent<Boss>().TakeDamage(damageValue, transform.position);}else{AudioSourceManager.Instance.playSound(hitWallClip);}}       }
}

十八、Smoke

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Smoke : MonoBehaviour
{public ParticleSystem particleSystem;private List<GameObject> enemyList = new List<GameObject>();private void OnEnable(){particleSystem.time = 0;particleSystem.Play();Invoke("HideSelf",25);}private void HideSelf(){particleSystem.Stop();Invoke("HideGameObject", 7);}private void HideGameObject(){gameObject.SetActive(false);}private void OnDisable(){CancelInvoke();for (int i = 0; i < enemyList.Count; i++){if (enemyList[i]){Enemy enemy = enemyList[i].GetComponentInParent<Enemy>();if (enemy){enemy.RecoverAttackRangeValue();enemy.SetSmokeCollierState(true);}}     }enemyList.Clear();StopAllCoroutines();}private void OnTriggerExit(Collider other){if (other.tag == "Enemy"){if (enemyList.Contains(other.gameObject)){enemyList.Remove(other.gameObject);}}}private void OnTriggerEnter(Collider other){if (other.tag=="Enemy"){if (!enemyList.Contains(other.gameObject)){enemyList.Add(other.gameObject);}StartCoroutine(OutSmoke(other));Debug.Log("进入烟雾");}}IEnumerator OutSmoke(Collider other){//进入迷失状态yield return new WaitForSeconds(2);Enemy enemy = other.GetComponentInParent<Enemy>();if (enemy.enabled){enemy.SetRange(2);enemy.SetSmokeCollierState(false);}      //解除迷失状态yield return new WaitForSeconds(15);if (enemy.enabled){enemy.SetSmokeCollierState(true);}}
}

十九、SoundPlayer

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class SoundPlayer : MonoBehaviour
{public AudioSource audioSource;public AudioClip clipSource;public AudioClip[] audioClips;public float currentPitchMin=1;public float currentPitchMax=1;private void Awake(){audioSource = GetComponent<AudioSource>();if (clipSource){audioSource.clip = clipSource;}}/// <summary>/// 外部调用/// </summary>/// <param name="audioClip"></param>/// <param name="pitchMin"></param>/// <param name="pitchMax"></param>public void PlayClip(AudioClip audioClip,float pitchMin=1,float pitchMax=1){audioSource.pitch = Random.Range(pitchMin,pitchMax);audioSource.PlayOneShot(audioClip);}public void PlayRandomSound(){audioSource.pitch = Random.Range(currentPitchMin, currentPitchMax);audioSource.PlayOneShot(audioClips[Random.Range(0,audioClips.Length)]);}public void PlaySound(bool loop=false){if (audioSource.clip!=null){if (!audioSource.isPlaying){audioSource.loop = loop;audioSource.Play();}}      }
}

二十、TelesopicView    倍镜

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class TelesopicView : MonoBehaviour
{public float zoomLevel = 2;//倍镜缩放等级public float OpenSpeed=100;public float CloseSpeed=80;private float initFOV;private bool openTelesopicView;//倍镜开关// Start is called before the first frame updatevoid Start(){initFOV = Camera.main.fieldOfView;}// Update is called once per framevoid Update(){if (openTelesopicView){OpenTelesopicView();}else{CloseTelesopicView();}}/// <summary>/// 打开倍镜方法/// </summary>private void OpenTelesopicView(){if (Camera.main.fieldOfView!=initFOV/zoomLevel){if (Mathf.Abs(Camera.main.fieldOfView - initFOV / zoomLevel)<5){Camera.main.fieldOfView = initFOV / zoomLevel;}else{Camera.main.fieldOfView -= Time.deltaTime * OpenSpeed;}}UIManager.Instance.OpenOrCloseTelesopicView();}/// <summary>/// 关闭倍镜方法/// </summary>private void CloseTelesopicView(){if (Camera.main.fieldOfView != initFOV){if (Mathf.Abs(Camera.main.fieldOfView - initFOV ) < 5){Camera.main.fieldOfView = initFOV;}else{Camera.main.fieldOfView += Time.deltaTime * CloseSpeed;}}UIManager.Instance.OpenOrCloseTelesopicView(false);}public void OpenTheTelesopicView(bool open=true){openTelesopicView = open;}}

二十一、UIManager

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;public class UIManager : MonoBehaviour
{public GameObject imgSnipeRifle;public GameObject imgTakeDamage;public GameObject weaponUIViewGo;public GameObject[] weaponUIGos;public Text textHealth;public Text textBulletNum;public GameObject imgDaeaGo;public AudioClip lossClip;public static UIManager Instance { get; private set; }private void Awake(){Instance = this;}public void OpenOrCloseTelesopicView(bool open=true){imgSnipeRifle.SetActive(open);}public void ShowTakeDamageView(){imgTakeDamage.SetActive(true);CancelInvoke();Invoke("HideTakeDamageView", 2);}public void HideTakeDamageView(){imgTakeDamage.SetActive(false);}public void ShowOrHideWeaponUIView(bool show){weaponUIViewGo.SetActive(show);}public void ChangeWeaponUIView(int id){for (int i = 0; i < weaponUIGos.Length; i++){weaponUIGos[i].SetActive(false);}weaponUIGos[id].SetActive(true);}/// <summary>/// 血量更新/// </summary>public void UpdateHPValue(int value){textHealth.text = value.ToString();}/// <summary>/// 子弹更新/// </summary>public void UpdateBulletNum(int curretNum,int totalNum){textBulletNum.text = curretNum.ToString() + "/" + totalNum.ToString();}public void ShowDeadUI(){imgDaeaGo.SetActive(true);Invoke("PlayLossMusic", 2);}private void PlayLossMusic(){AudioSourceManager.Instance.playSound(lossClip);Invoke("LoadCurrentScence", 3);}public void LoadCurrentScence(){SceneManager.LoadScene(0);}
}

二十二、Weapon

using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Weapon : MonoBehaviour
{private DoctorController owner;public int itemID = -1;public int initAmount = -1;private Animator animator;public LineRenderer rayTrailPrefab;public Transform shootPoint;public WEAPONTYPE weaponType;private List<ActiveTrail> activeTrails;public Projectile projectilePrefab;public float projectilelauchForce=200;public AdvancedWeaponSettings advancedWeaponSettings;public int clipSize = 4;//弹夹里子弹数量(当前可以往里放的最大数量)public int clipContent;//当前弹夹里剩余子弹数private WEAPONSTATE currentWeaponState;//当前武器状态private int fireNameHash;private int reloadNameHash;public float reloadTime = 2.0f;//更换弹夹的速度public float fireRete = 0.5f;//攻击频率(CD)private float shotTimer = -1;//CD计时器public AnimationClip fireAnimatortionClip;public AnimationClip reloadAnimationClip;public float damageValue = 1;//初始伤害值public ParticleSystem raycastHitEffectPrefab;//粒子特效public WEAPONMOOD weaponMode;public bool hasTelesopicView;//有无倍镜功能private TelesopicView telesopicView;private float bulletSize;public ParticleSystem bulletViewEffect;private float currentDamageValue;//当前伤害值public float decreaseSpeed;//减少量public AudioClip shootClip;public AudioClip hitWallClip;public AudioClip reloadClip;//换弹夹public AudioClip cockClip;private float chargeTimer;public AudioSource chargeAudio;private float stopChargeTimer;//计时器public AudioSource cockAudio;private void Awake(){animator = GetComponentInChildren<Animator>();}// Start is called before the first frame updatevoid Start(){if (rayTrailPrefab!=null){//如果当前武器可以发射激光,那么需要先生成几个备用的预制体PoolManager.Instance.InitPool(rayTrailPrefab, 8);}activeTrails = new List<ActiveTrail>();if (projectilePrefab!=null){PoolManager.Instance.InitPool(projectilePrefab, 8);}currentWeaponState = WEAPONSTATE.IDLE;fireNameHash=Animator.StringToHash("fire");reloadNameHash = Animator.StringToHash("reload");clipContent = clipSize;if (raycastHitEffectPrefab!=null){PoolManager.Instance.InitPool(raycastHitEffectPrefab, 8);}if (hasTelesopicView){telesopicView = Camera.main.transform.GetComponent<TelesopicView>();}chargeTimer = 0;chargeAudio = GetComponent<AudioSource>();}// Update is called once per framevoid Update(){UpdateController();FireInput();if (Input.GetMouseButtonDown(0)){Fire();}if (Input.GetButtonDown("Reload")){Reload();}if (shotTimer>0){shotTimer -= Time.deltaTime;}UpdateTrailState();}/// <summary>/// 获取子弹数量/// </summary>/// <returns></returns>public int GetInitAmount(){return initAmount;}/// <summary>/// 获取武器的ID/// </summary>/// <returns></returns>public int GetID(){return itemID;}/// <summary>/// 选择当前武器/// </summary>public void Selected(){gameObject.SetActive(owner.GetAmmoAmount(itemID)!=0||clipContent!=0);animator.SetTrigger("selected");if (fireAnimatortionClip!=null){animator.SetFloat("fireSpeed",fireAnimatortionClip.length/fireRete);}if (reloadAnimationClip!=null){animator.SetFloat("reloadSpeed", reloadAnimationClip.length / reloadTime);}currentWeaponState = WEAPONSTATE.IDLE;owner.decreaseSpeed = decreaseSpeed;UIManager.Instance.ShowOrHideWeaponUIView(true);UIManager.Instance.ChangeWeaponUIView(itemID);UIManager.Instance.UpdateBulletNum(clipContent, owner.GetAmmoAmount(itemID));if (reloadClip != null){AudioSourceManager.Instance.playSound(reloadClip);}}/// <summary>/// 收起武器/// </summary>public void PutAway(){gameObject.SetActive(false);if (weaponMode == WEAPONMOOD.ACCUMULATION){InitAccumulationWeapon();}if (weaponType == WEAPONTYPE.RAYCAST){for (int i = 0; i < activeTrails.Count; i++){activeTrails[i].renderer.gameObject.SetActive(false);}activeTrails.Clear();}}/// <summary>/// 捡起武器,制定当前武器拥有者即DoctorController的引用/// </summary>public void PickUp(DoctorController doctorController){owner = doctorController;}/// <summary>/// 攻击方法/// </summary>public void Fire(){if (currentWeaponState!=WEAPONSTATE.IDLE||shotTimer>0){return;}if (clipContent==0){if (cockAudio.isPlaying){cockAudio.Play();}return;}AudioSourceManager.Instance.playSound(shootClip);shotTimer = fireRete;clipContent -= 1;UIManager.Instance.UpdateBulletNum(clipContent, owner.GetAmmoAmount(itemID));animator.SetTrigger("fire");owner.cameraShaker.SetShakeValue(advancedWeaponSettings.shakeTime, 0.05f * advancedWeaponSettings.shakeStrength);currentWeaponState = WEAPONSTATE.FIRING;if (weaponType==WEAPONTYPE.RAYCAST){RayCastShot();}else{ProjectileShot();}}/// <summary>/// 发射激光类型枪的攻击/// </summary>private void RayCastShot(){//发散比例(当前单位长度)float spreadRatio = advancedWeaponSettings.spreadAngle / Camera.main.fieldOfView;Vector2 spread = spreadRatio*Random.insideUnitCircle;Ray ray= Camera.main.ViewportPointToRay(Vector3.one*0.5f+(Vector3)spread);RaycastHit hit;if (Physics.Raycast(ray, out hit, 1000, ~(1 << 8), QueryTriggerInteraction.Ignore)){ParticleSystem ps= PoolManager.Instance.GetInstance<ParticleSystem>(raycastHitEffectPrefab);ps.transform.position = hit.point;ps.transform.forward= hit.normal;ps.gameObject.SetActive(true);ps.Play();if (hit.collider.gameObject.layer==9){Enemy enemy = hit.collider.GetComponent<Enemy>();enemy.TakeDamage(damageValue);}else if (hit.collider.gameObject.layer==10){Boss enemy = hit.collider.GetComponentInParent<Boss>();enemy.TakeDamage(damageValue,transform.position);}else{AudioSourceManager.Instance.playSound(hitWallClip);}if (rayTrailPrefab!=null){LineRenderer lineRenderer= PoolManager.Instance.GetInstance<LineRenderer>(rayTrailPrefab);lineRenderer.gameObject.SetActive(true);Vector3[] trailPos = new Vector3[] { shootPoint.position,hit.point};lineRenderer.SetPositions(trailPos);activeTrails.Add(new ActiveTrail(){renderer=lineRenderer,direction=(trailPos[1]-trailPos[0]).normalized,remainningTime=0.3f });}}}/// <summary>/// 更新激光拖尾效果(模拟位移)/// </summary>private void UpdateTrailState(){Vector3[] pos = new Vector3[2];for (int i = 0; i < activeTrails.Count; i++){ActiveTrail activeTrail = activeTrails[i];activeTrail.renderer.GetPositions(pos);       activeTrail.remainningTime -= Time.deltaTime;pos[0] += activeTrail.direction * 50 * Time.deltaTime;// pos[1] += activeTrail.direction * 50 * Time.deltaTime;activeTrail.renderer.SetPositions(pos);if (activeTrail.remainningTime<=0||Vector3.Distance(pos[0],pos[1])<=0.5F){activeTrail.renderer.gameObject.SetActive(false);activeTrails.RemoveAt(i);i--;}}}/// <summary>/// 发射子弹类型枪的攻击方式(包括投掷类武器比如手雷)/// </summary>private void ProjectileShot(){Projectile projectile=PoolManager.Instance.GetInstance<Projectile>(projectilePrefab);projectile.gameObject.SetActive(true);if (weaponMode==WEAPONMOOD.ACCUMULATION){projectile.SetBulletDamageValue(currentDamageValue);projectile.SetBulletSize(bulletSize);}Vector2 angleDir = Random.insideUnitCircle*Mathf.Sin(advancedWeaponSettings.spreadAngle*Mathf.Deg2Rad) ;Vector3 dir = shootPoint.forward + (Vector3)angleDir;dir.Normalize();projectile.Launch(this, dir, projectilelauchForce);}public Transform GetShootPoint(){return shootPoint;}/// <summary>/// 换弹夹/// </summary>public void Reload(){if (clipContent==clipSize||currentWeaponState!=WEAPONSTATE.IDLE)//弹夹子弹数已满{return;}int remainningBullet= owner.GetAmmoAmount(itemID);if (remainningBullet==0){if (itemID==2||itemID==6){PutAway();}return;}int chargeInClip= Mathf.Min(remainningBullet,clipSize-clipContent);clipContent += chargeInClip;currentWeaponState = WEAPONSTATE.RELOADING;owner.UpdateAmmoAmount(itemID, -chargeInClip);UIManager.Instance.UpdateBulletNum(clipContent, owner.GetAmmoAmount(itemID));animator.SetTrigger("reload");if (weaponMode==WEAPONMOOD.ACCUMULATION){bulletViewEffect.gameObject.SetActive(false);bulletViewEffect.startSize = 0;}if (reloadClip!=null){AudioSourceManager.Instance.playSound(reloadClip);}      }/// <summary>/// 更新动画控制器以及武器的状态/// </summary>private void UpdateController(){animator.SetFloat("moveSpeed", owner.actualSpeed / 5);AnimatorStateInfo animatorStateInfo= animator.GetCurrentAnimatorStateInfo(0);WEAPONSTATE newState;if (animatorStateInfo.shortNameHash==fireNameHash){newState = WEAPONSTATE.FIRING;}else if (animatorStateInfo.shortNameHash==reloadNameHash){newState = WEAPONSTATE.RELOADING;}else{newState = WEAPONSTATE.IDLE;}if (newState!=currentWeaponState){WEAPONSTATE lastState= currentWeaponState;currentWeaponState = newState;if (lastState==WEAPONSTATE.FIRING&&clipContent==0){Reload();}}}public bool HasBullet(){return clipContent > 0;}private void FireInput(){switch (weaponMode){case WEAPONMOOD.NORMAL:if (Input.GetMouseButtonDown(0)){Fire();}if (hasTelesopicView){if (Input.GetMouseButton(1)){telesopicView.OpenTheTelesopicView();}else{telesopicView.OpenTheTelesopicView(false);}if (currentWeaponState == WEAPONSTATE.RELOADING){telesopicView.OpenTheTelesopicView(false);}}              break;case WEAPONMOOD.AUTO:if (Input.GetMouseButton(0)){Fire();}break;case WEAPONMOOD.ACCUMULATION:if (Input.GetMouseButtonUp(0))//释放{Fire();InitAccumulationWeapon();}else if (Input.GetMouseButtonDown(0)&&clipContent>0&&currentWeaponState!=WEAPONSTATE.RELOADING)//聚能  {AccumulateEnergy();}               break;default:break;}}private void InitAccumulationWeapon(){chargeTimer = 0;chargeAudio.Stop();bulletViewEffect.gameObject.SetActive(false);bulletViewEffect.startSize = 0;}/// <summary>/// 聚能方法/// </summary>public void AccumulateEnergy(){bulletViewEffect.gameObject.SetActive(true);if (bulletViewEffect.startSize<=0.3){bulletViewEffect.startSize += Time.deltaTime;}if (currentDamageValue<=5*damageValue){currentDamageValue += Time.deltaTime;}//第一次播放完整聚能音效if (chargeTimer<=0){chargeTimer = Time.deltaTime;chargeAudio.time = 0;chargeAudio.Play();}//后续播放持续循环的部分(即聚能)if (Time.deltaTime-chargeTimer>=1.463f){if (!chargeAudio.isPlaying){//只持续播放某一个时间点到最后的音效chargeAudio.time = 0.4f;chargeAudio.Play();stopChargeTimer = Time.time;}if (Time.time-stopChargeTimer>=0.5f){chargeAudio.Stop();}}}
}
public enum WEAPONTYPE
{RAYCAST,PROJECTILE
}
/// <summary>
/// 激光信息类
/// </summary>
public class ActiveTrail
{public LineRenderer renderer;public Vector3 direction;public float remainningTime;
}
/// <summary>
/// 武器的额外设置
/// </summary>
[System.Serializable]
public class AdvancedWeaponSettings
{public float spreadAngle;//偏移 (发散) 角度(单位不是传统意义上的度数,而是计量单位)public float shakeTime;//震动时间public float shakeStrength;//震动大小
}public enum WEAPONSTATE
{IDLE,FIRING,RELOADING
}
/// <summary>
/// 攻击模式
/// </summary>
public enum WEAPONMOOD
{NORMAL,AUTO,ACCUMULATION
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/146004.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

JavaWeb初阶 day1

目录 tomcat目录结构 tomcat:web服务器软件 项目部署的方式 直接将项目放到webapps下 配置conf/server.xml文件 在conf\Catalina\localhost创建任意名称的xml文件。在文件中编写 静态项目和动态项目 Servlet Servlet执行原理 Servlet方法&#xff08;生命周期&#x…

Linux入门学习:make/Makefile(Linux项目自动化构建工具)

文章目录 1. makefile文件语法2. make clean工程清理3. 细节语法4. make原理 ⭕背景&#xff1a; 会不会写makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力。一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c…

Linux相关概念和重要知识点(5)(权限的修改、时间属性)

1.权限的修改 &#xff08;1&#xff09;提权行为 普通用户是会受到权限的限制&#xff0c;但root账户无视一切权限限制&#xff0c;因此当我们要获取更高的权限&#xff0c;有一种办法就是将自己变成root或者短暂拥有和root一样的权力。 普通用户 -> root &#xff1a;s…

C++QT医院专家门诊预约管理系统

目录 一、项目介绍 二、项目展示 三、源码获取 一、项目介绍 医院专家门诊预约管理系统 [要求] 该系统需创建和管理以下信息&#xff1a;1、门诊专家信息&#xff1a;专家姓名、编号、性别、年龄、职称、门诊科目、服务时间、门诊预约数据集等&#xff1b;2、门诊预约信息…

2024 研究生数学建模竞赛(E题)建模秘籍|高速公路应急车道紧急启用模型|文章代码思路大全

铛铛&#xff01;小秘籍来咯&#xff01; 小秘籍团队独辟蹊径&#xff0c;运用聚类分析&#xff0c;逻辑回归模型&#xff0c;决策树/规则&#xff0c;ARIMA等强大工具&#xff0c;构建了这一题的详细解答哦&#xff01; 为大家量身打造创新解决方案。小秘籍团队&#xff0c;始…

Open3D 计算点云的曲率密度参数【2024最新版】

目录 一、算法原理1、曲率密度参数2、参考文献二、代码实现三、结果展示本文由CSDN点云侠原创,原文链接,首发于:2024年9月21日。如果你不是在点云侠的博客中看到该文章,那么此处便是不要脸的抄袭狗。 一、算法原理 1、曲率密度参数 对于点云数据集中任意一点 p i p_i

Python Selenium 自动化爬虫 + Charles Proxy 抓包

一、场景介绍 我们平常会遇到一些需要根据省、市、区查询信息的网站。 1、省市查询 比如这种&#xff0c;因为全国的省市比较多&#xff0c;手动查询工作量还是不小。 2、接口签名 有时候我们用python直接查询后台接口的话&#xff0c;会发现接口是加签名的。 而签名算法我…

vue3 TagInput 实现

效果 要实现类似于下面这种效果 大致原理 其实是很简单的,我们可以利用 element-plus 组件库里的 el-tag 组件来实现 这里我们可以将其抽离成一个公共的组件,那么现在有一个问题就是通讯问题 这里我们可以利用父子组件之间的通讯,利用 v-model 来实现,父组件传值,子组…

精密制造与质量控制:保障滚珠丝杆重载运行精度

滚珠丝杆作为精密机械传动领域的重要零部件&#xff0c;能够将旋转动力精准地转化为流畅的直线运动。在数控机床、精密制造及高度自动化生产线上扮演着不可或缺的角色。在应对温度波动、负载突变及严苛环境条件的考验中&#xff0c;都有很好的表现。那么&#xff0c;应该如何确…

Linux_openEuler_24.03部署Oracle 19c部署安装实测验证(无图形桌面-RPM模式)

前言&#xff1a; 近期对openeuler有点兴趣&#xff0c;顺带在做个开发数据仓项目&#xff0c;那就正好安装个环境做个调测&#xff0c;做个记录放上来做个备录给到大家参考。 openEuler 24.03 LTS&#xff1a;四大升级&#xff0c; 首个AI原生开源操作系统正式发布 openEuler …

2024华为杯研赛数学建模E题分析

2024华为杯数学建模E题分析如下&#xff0c;完整版本可查看最下方名片

U9多组织单据关连生单时的错误提示

开立采购退货单时&#xff0c;有以下的错误提示。从这段文字来看。生成【采购退货单】同时生成关联公司的【退回处理单】&#xff0c;检查退回处理单的单据类型是正常的。不明所以。系统商出来的错误提示一般是用来迷惑人的&#xff0c;不可尽信。 【未找到满足条件【上游推式…

Mybatis的XML实现方法

Mybatis的开发有两种方式&#xff1a; 1、注解 2、XML 使用Mybatis的注解方式&#xff0c;主要是来完成一些简单的增删改查功能。如果需要实现复杂的SQL功能&#xff0c;建议使用XML来配置映射语句&#xff0c;也就是将SQL语句写在XML配置文件中。 Mybatis的XML的实现需要以下…

最新版本TensorFlow训练模型TinyML部署到ESP32入门实操

最新版本TensorFlow训练模型TinyML入门实操 1.概述 这篇文章介绍微型嵌入式设备的机器学习TinyML&#xff0c;它们的特点就是将训练好的模型部署到单片机上运行。 2.TensorFlow深度学习原理 TensorFlow开源项目是由google研发的一个嵌入式机器学习工具&#xff0c;通过调用…

Compose动画

一、Compose动画种类和选择 1.1 选择动画API 1.采用SVG&#xff1a;AnimatedVectorDrawable 是否第三方动画框架&#xff1a;Lottie动画 2.是否需要永久播放&#xff1a;rememberInfiniteTransition 3.布局动画 在内容不同的多个可组合项之间切换 3.1 导航过渡动画&#…

154-钓鱼篇Offfice-CVE漏洞RLO隐藏压缩包释放免杀打包捆绑

#知识点&#xff1a; 1、文件名-RLO 伪装-后缀 2、压缩文件-自解压-运行 3、捆绑文件-打包加载-运行 4、Office 套件-漏洞钓鱼-CVE #文件后缀-钓鱼伪装-RLO cs生成一个exe后门 重命名为一个png反过来或者jpg反过来的名字 然后再g前面输入其他字符在g字符前面右键选择这个插入…

CUDA-事件计时方法cudaEventElapsedTime

作者&#xff1a;翟天保Steven 版权声明&#xff1a;著作权归作者所有&#xff0c;商业转载请联系作者获得授权&#xff0c;非商业转载请注明出处 实现原理 事件计时方法是CUDA编程中一种用于测量GPU内核执行时间的高效手段。其基本步骤包括&#xff1a; 创建事件&#xff1a;…

Python模拟鼠标轨迹[Python]

一.鼠标轨迹模拟简介 传统的鼠标轨迹模拟依赖于简单的数学模型&#xff0c;如直线或曲线路径。然而&#xff0c;这种方法难以捕捉到人类操作的复杂性和多样性。AI大模型的出现&#xff0c;能够通过深度学习技术&#xff0c;学习并模拟更自然的鼠标移动行为。 二.鼠标轨迹算法实…

echarts柱图

样式如下 关键代码 // html部分<div class"echarts-container" :id"echartDiv id"></div>// js部分 data() {return {myChart: null,xAxisData: [云南, 浙江, 山东, 广东, 四川, 河南, 广西, 河南, 广西],yAxisData: [{value: 230,num: {r…

超实用线程调度方法!

文章目录 前言一、实现思路二、实现实例三、实现效果 前言 你有想过这样一个问题吗&#xff1f;线程之间是如何调度的&#xff1f; 更具体点说是这样&#xff0c;有两个线程&#xff1a;线程A和线程B&#xff0c;线程B要先于线程A运行&#xff0c;或者是线程B运行了多次之后在…