void Hit(Collision col) { //播放爆炸特效 Explode(col.contacts[0].point); //让被击中物受到伤害 if (SelectedDamageType == DamageType.Direct) { ReactiveTarget target = col.collider.gameObject.GetComponent <ReactiveTarget>(); if (target) { //第二个参数设置为true,不分敌我进行伤害 target.OnHit(this.gameObject.name, true, Damage); } else { target = col.collider.transform.root.GetComponent <ReactiveTarget>(); if (target) { //第二个参数设置为true,不分敌我进行伤害 target.OnHit(this.gameObject.name, false, Damage); } } } }
//射线武器,开火 public void Fire() { //调用RPC函数 if (IsLocalObject) { m_NetSyncController.RPC(this, "Fire"); } //重置计时器 FireTimer = 0.0f; //增加已射击的子弹数 BurstCounter++; //半自动武器不能连续射击 if (AutoMode == Auto.Semi) { m_CanFire = false; } //判断当前是否仍有弹药 if (m_CurrentAmmo <= 0) { DryFire(); return; } //能够开枪,发送开枪消息 SendMessage("StartShooting", SendMessageOptions.DontRequireReceiver); //如果不是无线弹药模式,减少弹药量 if (!InfiniteAmmo) { m_CurrentAmmo--; } //单次射击,射出shotPerRound颗子弹 for (int i = 0; i < ShotPerRound; i++) { Vector3 direction = m_CurrentShootPoint.forward; //计算当前的精确度 float accuracyVary = (100 - CurrentAccuracy) / 1000; //根据精确度确定散射范围 direction.x += UnityEngine.Random.Range(-accuracyVary, accuracyVary); direction.y += UnityEngine.Random.Range(-accuracyVary, accuracyVary); direction.z += UnityEngine.Random.Range(-accuracyVary, accuracyVary); CurrentAccuracy -= AccuracyDropPerShot; if (CurrentAccuracy <= 0.0f) { CurrentAccuracy = 0.0f; } //创建射线 Ray ray = new Ray(m_CurrentShootPoint.position, direction); bool hitResult; RaycastHit hit; int layer = LayerMask.NameToLayer(LayerMaskName); if (layer != -1) { //过滤LayerMaskName这一层 LayerMask mask = ~(1 << layer); hitResult = Physics.Raycast(ray, out hit, Range, mask); } else { hitResult = Physics.Raycast(ray, out hit, Range); } if (hitResult) { //蓄力 float damage = Power; if (Warmup) { damage *= m_Heat * PowerMultiplier; m_Heat = 0.0f; } //造成伤害 ReactiveTarget target = hit.collider.gameObject.GetComponent <ReactiveTarget>(); if (target) { target.OnHit(this.transform.root.name, false, Power); } else { target = hit.collider.transform.root.gameObject.GetComponent <ReactiveTarget>(); if (target) { target.OnHit(this.transform.root.name, false, Power); } } //判断被击中物体是否满足不产生弹孔的条件 bool exception = false; if (BHSystem == BulletHoleSystem.Tag) { foreach (SmartBulletHoleGroup bhg in BulletHoleExceptions) { if (hit.collider.gameObject.tag == bhg.Tag) { exception = true; break; } } } else if (BHSystem == BulletHoleSystem.Material) { foreach (SmartBulletHoleGroup bhg in BulletHoleExceptions) { MeshRenderer mesh = FindMeshRenderer(hit.collider.gameObject); if (mesh != null) { if (mesh.sharedMaterial == bhg.Material) { exception = true; break; } } } } else if (BHSystem == BulletHoleSystem.Physic_Material) { foreach (SmartBulletHoleGroup bhg in BulletHoleExceptions) { if (hit.collider.sharedMaterial == bhg.PhysicMaterial) { exception = true; break; } } } //如果需要生成弹孔,且物体满足生成弹孔条件 if (MakeBulletHoles && !exception) { //保存所有符合条件的SmartBulletHoleGroup List <SmartBulletHoleGroup> holes = new List <SmartBulletHoleGroup>(); if (BHSystem == BulletHoleSystem.Tag) { foreach (SmartBulletHoleGroup bhg in BulletHoleGroups) { if (hit.collider.gameObject.tag == bhg.Tag) { holes.Add(bhg); } } } else if (BHSystem == BulletHoleSystem.Material) { MeshRenderer mesh = FindMeshRenderer(hit.collider.gameObject); foreach (SmartBulletHoleGroup bhg in BulletHoleGroups) { if (mesh != null) { if (mesh.sharedMaterial == bhg.Material) { holes.Add(bhg); } } } } else if (BHSystem == BulletHoleSystem.Physic_Material) { foreach (SmartBulletHoleGroup bhg in BulletHoleGroups) { if (hit.collider.sharedMaterial == bhg.PhysicMaterial) { holes.Add(bhg); } } } //保存被选中的SmartBulletHoleGroup SmartBulletHoleGroup sbhg = null; //没有满足条件的弹孔,使用默认弹孔 if (holes.Count == 0) { List <SmartBulletHoleGroup> defaultsToUse = new List <SmartBulletHoleGroup>(); foreach (BulletHolePool h in DefaultBulletHoles) { defaultsToUse.Add(new SmartBulletHoleGroup("Default", null, null, h)); } //随机选择一个SmartBulletHoleGroup sbhg = defaultsToUse[Random.Range(0, defaultsToUse.Count)]; } else { //随机选择一个SmartBulletHoleGroup sbhg = holes[Random.Range(0, holes.Count)]; } //在场景中生成弹孔 if (sbhg.BulletHole != null) { sbhg.BulletHole.PlaceBulletHole(hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal)); } } //击中的特效 if (MakeHitEffects) { foreach (GameObject hitEffect in HitEffects) { if (hitEffect != null) { Instantiate(hitEffect, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal)); } } } //给被射中的物体加上一个击退的力 if (UseForce && hit.rigidbody) { hit.rigidbody.AddForce(ray.direction * Power * ForceMultiplier); } } } //如果使用后坐力,调用后坐力函数 if (UseRecoil) { Recoil(); } //如果使用枪口火焰效果,就显示枪口火焰 if (MakeMuzzleEffects) { GameObject muzfx = MuzzleEffects[Random.Range(0, MuzzleEffects.Length)]; if (muzfx != null) { Instantiate(muzfx, MuzzleEffectsPosition.position, MuzzleEffectsPosition.rotation); } } //创建弹壳 if (UseSpitShells) { GameObject shellGO = Instantiate(Shell, ShellSpitPosition.position, ShellSpitPosition.rotation) as GameObject; shellGO.GetComponent <Rigidbody>().AddRelativeForce(new Vector3(ShellSpitForce + Random.Range(0, ShellForceRandom), 0, 0), ForceMode.Impulse); shellGO.GetComponent <Rigidbody>().AddRelativeTorque(new Vector3(ShellSpitTorqueX + Random.Range(-ShellTorqueRandom, ShellTorqueRandom), ShellSpitTorqueY + Random.Range(-ShellTorqueRandom, ShellTorqueRandom), 0), ForceMode.Impulse); } //播放射击音效 GetComponent <AudioSource>().PlayOneShot(FireSound); }
//激光武器,发射激光 public void Beam() { //调用RPC函数 if (IsLocalObject) { m_NetSyncController.RPC(this, "Beam"); } //能够开枪,发送开枪消息 SendMessage("StartShooting", SendMessageOptions.DontRequireReceiver); //当前正在发射激光 m_IsBeaming = true; //如果不是无限激光,开始计时 if (!InfiniteBeam) { m_BeamHeat += Time.deltaTime; } //如果没有设置激光Object,创建一个带有line renderer的GameObject if (m_BeamGO == null) { m_BeamGO = new GameObject(BeamTypeName, typeof(LineRenderer)); //设置为Weapon的子对象 m_BeamGO.transform.parent = transform; } //设置线渲染器属性 LineRenderer beamLR = m_BeamGO.GetComponent <LineRenderer>(); beamLR.material = BeamMaterial; beamLR.material.SetColor("_TintColor", BeamColor); beamLR.startWidth = StartBeamWidth; beamLR.endWidth = EndBeamWidth; //反射次数 int reflections = 0; //保存激光的所有反射点 List <Vector3> reflectionPoints = new List <Vector3>(); //添加第一个反射点 reflectionPoints.Add(RaycastStartSpot.position); //保存上一个反射点 Vector3 lastPoint = RaycastStartSpot.position; //用于保存激光的入射方向和反射方向 Vector3 incomingDirection; Vector3 reflectDirection; //激光是否需要继续进行反射 bool keepReflecting = true; //投射射线 Ray ray = new Ray(lastPoint, RaycastStartSpot.forward); RaycastHit hit; do { //如果没有检测到任何物体,那么下一个点为终点 Vector3 nextPoint = ray.direction * Range; if (Physics.Raycast(ray, out hit, Range)) { //保存碰撞点 nextPoint = hit.point; //计算反射方向 incomingDirection = nextPoint - lastPoint; reflectDirection = Vector3.Reflect(incomingDirection, hit.normal); ray = new Ray(nextPoint, reflectDirection); //更新上一次的反射点 lastPoint = hit.point; //创建击中特效 if (MakeHitEffects) { foreach (GameObject hitEffect in HitEffects) { if (hitEffect != null) { Instantiate(hitEffect, hit.point, Quaternion.FromToRotation(Vector3.up, hit.normal)); } } } //造成伤害 ReactiveTarget target = hit.collider.gameObject.GetComponent <ReactiveTarget>(); if (target) { target.OnHit(this.transform.root.name, false, Power); } // 增加反射次数 reflections++; } else { //不再进行反射 keepReflecting = false; } //添加反射点 reflectionPoints.Add(nextPoint); } while (keepReflecting && reflections < MaxReflections && Reflect && (ReflectionMaterial == null || (FindMeshRenderer(hit.collider.gameObject) != null && FindMeshRenderer(hit.collider.gameObject).sharedMaterial == ReflectionMaterial))); //设置线渲染器的顶点 beamLR.positionCount = reflectionPoints.Count; for (int i = 0; i < reflectionPoints.Count; i++) { beamLR.SetPosition(i, reflectionPoints[i]); //枪口反射特效 // Doesn't make the FX on the first iteration since that is handled later. This is so that the FX at the muzzle point can be parented to the weapon if (MakeMuzzleEffects && i > 0) { GameObject muzfx = MuzzleEffects[Random.Range(0, MuzzleEffects.Length)]; if (muzfx != null) { Instantiate(muzfx, reflectionPoints[i], MuzzleEffectsPosition.rotation); } } } //枪口闪烁特效 if (MakeMuzzleEffects) { GameObject muzfx = MuzzleEffects[Random.Range(0, MuzzleEffects.Length)]; if (muzfx != null) { GameObject mfxGO = Instantiate(muzfx, MuzzleEffectsPosition.position, MuzzleEffectsPosition.rotation) as GameObject; mfxGO.transform.parent = RaycastStartSpot; } } //播放激光音效 if (!GetComponent <AudioSource>().isPlaying) { GetComponent <AudioSource>().clip = FireSound; GetComponent <AudioSource>().Play(); } }
//将Start设置为协程,自动开始协程 IEnumerator Start() { //暂停一帧,避免有碎片还没被创建 yield return(null); //获取物理层 int layer = LayerMask.NameToLayer(LayerMaskName); Collider[] cols; Collider[] colsWithoutMask; if (layer != -1) { //创建物理遮罩 LayerMask mask = ~(1 << layer); //爆炸范围内的物体 cols = Physics.OverlapSphere(transform.position, ExplosionRadius, mask); } else { Debug.LogWarning("Can not find the layer to create a layer mask"); //爆炸范围内的物体 cols = Physics.OverlapSphere(transform.position, ExplosionRadius); } colsWithoutMask = Physics.OverlapSphere(transform.position, ExplosionRadius); //造成伤害 if (CauseDamage) { foreach (Collider col in cols) { float damageAmount = Damage * (1 / Vector3.Distance(transform.position, col.transform.position)); //造成伤害 ReactiveTarget target = col.gameObject.GetComponent <ReactiveTarget>(); if (target) { //第二个参数为true,不分敌我进行伤害 target.OnHit(this.gameObject.name, true, Damage); } } } //用来保存爆炸范围内所有Rigidbody信息 List <Rigidbody> rigidbodies = new List <Rigidbody>(); foreach (Collider col in cols) { //保存范围内所有Rigidbody信息 if (col.attachedRigidbody != null && !rigidbodies.Contains(col.attachedRigidbody)) { rigidbodies.Add(col.attachedRigidbody); } } foreach (Rigidbody rb in rigidbodies) { rb.AddExplosionForce(ExplosionForce, transform.position, ExplosionRadius, 1, ForceMode.Impulse); } foreach (Collider col in colsWithoutMask) { //如果子对象包含Vibration脚本,就调用函数进行抖动 if (ShakeCamera && col.transform.GetComponentInChildren <Vibration>() != null) { float shakeViolence = 1 / (Vector3.Distance(transform.position, col.transform.position) * CameraShakeViolence); col.transform.GetComponentInChildren <Vibration>().StartShakingRandom(-shakeViolence, shakeViolence, -shakeViolence, shakeViolence); } } }