/// <summary> /// Generates a bullet hole decal. /// </summary> /// <param name="surface">The surface properties of the hit object.</param> /// <param name="hitInfo">The information about the projectile impact such as position and rotation.</param> public virtual void CreateBulletDecal(SurfaceIdentifier surface, RaycastHit hitInfo) { SurfaceType surfaceType = surface.GetSurfaceType(hitInfo.point, hitInfo.triangleIndex); if (surface && surfaceType) { if (surface.AllowDecals(hitInfo.triangleIndex) && m_MaxDecals > 0) { Material material = surfaceType.GetRandomDecalMaterial(); if (material) { GameObject decal = new GameObject("BulletMark_Decal"); decal.transform.position = hitInfo.point; decal.transform.rotation = Quaternion.FromToRotation(Vector3.back, hitInfo.normal); decal.transform.Rotate(new Vector3(0, 0, Random.Range(0, 360))); float scale = surfaceType.GetRandomDecalSize() / 5; decal.transform.localScale = new Vector3(scale, scale, scale); decal.transform.parent = hitInfo.transform; DecalPresets decalPresets = new DecalPresets() { maxAngle = 60, pushDistance = 0.009f + RegisterDecal(decal, scale), material = material }; Decal d = decal.AddComponent <Decal>(); d.Calculate(decalPresets, hitInfo.collider.gameObject); } } GameObject particle = surfaceType.GetRandomImpactParticle(); if (particle) { Instantiate(particle, hitInfo.point, Quaternion.FromToRotation(Vector3.up, hitInfo.normal)); } AudioClip clip = surfaceType.GetRandomImpactSound(); if (clip) { AudioManager.Instance.PlayClipAtPoint(clip, hitInfo.point, 1, 25, surfaceType.BulletImpactVolume); } } }
protected virtual void Penetrate(RaycastHit lastHitInfo, Vector3 direction, SurfaceIdentifier surf, float range, float damage) { Ray ray = new Ray(lastHitInfo.point + direction * 0.1f, direction); int affectedObjectID = lastHitInfo.collider.GetInstanceID(); if (Physics.Raycast(ray, out RaycastHit hitInfo, range, m_GunData.AffectedLayers, QueryTriggerInteraction.Collide)) { // Get the surface type of the object. SurfaceIdentifier newSurf = hitInfo.collider.GetSurface(); // Exit hole Ray exitRay = new Ray(hitInfo.point, direction * -1); if (Physics.Raycast(exitRay, out RaycastHit exitInfo, range, m_GunData.AffectedLayers, QueryTriggerInteraction.Collide)) { float distanceTraveled = Vector3.Distance(lastHitInfo.point, exitInfo.point) * surf.Density(lastHitInfo.triangleIndex); // Does the bullet gets through? if (m_GunData.PenetrationPower > distanceTraveled) { if (newSurf) { BulletDecalsManager.Instance.CreateBulletDecal(newSurf, hitInfo); } if (affectedObjectID == exitInfo.collider.GetInstanceID()) { BulletDecalsManager.Instance.CreateBulletDecal(surf, exitInfo); } // If hit a rigid body applies force to push. Rigidbody rigidBody = hitInfo.collider.GetComponent <Rigidbody>(); if (rigidBody) { rigidBody.AddForce(direction * m_GunData.Force, ForceMode.Impulse); } if (hitInfo.transform.root != transform.root) { IProjectileDamageable damageableTarget = hitInfo.collider.GetComponent <IProjectileDamageable>(); damageableTarget?.ProjectileDamage(damage * (distanceTraveled / m_GunData.PenetrationPower), transform.root.position, exitInfo.point, m_GunData.PenetrationPower - distanceTraveled); } } } }
protected virtual void Shot() { Vector3 direction = m_CameraTransformReference.TransformDirection(m_NextShootDirection); Vector3 origin = m_CameraTransformReference.transform.position; Ray ray = new Ray(origin, direction); float tracerDuration = m_GunEffects.TracerDuration; if (Physics.Raycast(ray, out RaycastHit hitInfo, m_GunData.Range, m_GunData.AffectedLayers, QueryTriggerInteraction.Collide)) { SurfaceIdentifier surf = hitInfo.collider.GetSurface(); float damage = m_GunData.DamageType == GunData.DamageMode.Constant ? m_GunData.Damage : m_GunData.Damage * m_GunData.DamageFalloffCurve.Evaluate(hitInfo.distance / m_GunData.Range); if (surf) { BulletDecalsManager.Instance.CreateBulletDecal(surf, hitInfo); if (m_GunData.PenetrateObjects && surf.CanPenetrate(hitInfo.triangleIndex)) { Penetrate(hitInfo, direction, surf, m_GunData.Range - hitInfo.distance, damage); } } // If hit a rigid body applies force to push. Rigidbody rigidBody = hitInfo.collider.GetComponent <Rigidbody>(); if (rigidBody) { rigidBody.AddForce(direction * m_GunData.Force, ForceMode.Impulse); } if (hitInfo.transform.root != transform.root) { IProjectileDamageable damageableTarget = hitInfo.collider.GetComponent <IProjectileDamageable>(); damageableTarget?.ProjectileDamage(damage, transform.root.position, hitInfo.point, m_GunData.PenetrationPower); } tracerDuration = hitInfo.distance / m_GunEffects.TracerSpeed; } if (tracerDuration > 0.05f) { m_GunEffects.CreateTracer(transform, direction, tracerDuration); } }
private void OnEnable() { m_Target = (target as SurfaceIdentifier); m_SurfaceList = serializedObject.FindProperty("m_SurfaceList"); }
private void Start() { m_SurfaceIdentifier = GetComponent <SurfaceIdentifier>(); }