Hello, I've recently tweaked the bullet penetration script on my code so that it can tell the thickness of the object that it passes through. However this is all working well untill I shoot an object that is close to another one. The bullet appears to register going through the front of the first object and the coming out the back of the second object. Like so: (The red line represents the visual path of the bullet, ie where it leaves bullet holes. The bullet does actually travel through the middle it just doesn't register that it has) Code: Code (JavaScript): #pragma strict #pragma implicit #pragma downcast //BULLET Particles var Untagged : GameObject; // default bullet hole var Concrete : GameObject; // concrete bullet hole var Wood : GameObject; // wood bullet hole var Metal : GameObject; // metal bullet hole var Dirt : GameObject; // dirt/sand bullet hole var Blood : GameObject; // blood bullet hole var Glass : GameObject; // glass bullet hole var Snow : GameObject; // Snow bullet hole var Water : GameObject; // water bullet hole var IsTracer : float; var Tracer : boolean = false; var TrailScript : GameObject; var lifeTime : float = 2.0; // bullet life Time var mask : LayerMask = 1; var Gravity : float = 2; var distance : float; var DamageDropoff : float; var FinalDamage : float; var RawDamage : float; var DropCurve : AnimationCurve = new AnimationCurve(); var debugDamage : boolean = false; private var hitCount : int = 0; // hit counter for counting bullet impacts for bullet penetration private var damage : float; // damage bullet applies to a target private var force : float; private var maxHits : float = 3; // number of collisions before bullet gets destroyed private var impactForce : float; // force applied to a rigid body object private var maxInaccuracyHIP : float; // maximum amount of inaccuracy private var spread : float; // used in machineguns to decrease accuracy if maintaining fire private var speed : float; // bullet speed private var hit : RaycastHit; private var hit2 : RaycastHit; private var player : GameObject; var Rotation : Transform; var ExitPoint : Vector3; var Width : float; var EntryPoint : Vector3; //private var goWind:GameObject; var MaximumPenetration : float = 2; private var velocity : Vector3 = Vector3.zero; // bullet velocity private var hasHit : boolean = false; // has the bullet hit something? private var ignore : Collider = null; // ignore this collider private var direction : Vector3; // direction bullet is travelling private var direction2 : Vector3; private var newPos : Vector3; private var oldPos : Vector3; var startPos : Vector3; var endPos : Vector3; var dist : float; private var isTracer : boolean = true; private var bulletInfo : float[] = new float[2]; function SetUp(bulletInfo : float[] ){ // information sent from gun to bullet to change bullet properties damage = bulletInfo[0]; // bullet damage force = bulletInfo[1]; // force applied to rigid bodies maxHits = bulletInfo[2]; // max number of bullet impacts before bullet is destroyed maxInaccuracyHIP = bulletInfo[3]; // max inaccuracy of the bullet spread = bulletInfo[4]; // current inaccuracy... mostly for machine guns that lose accuracy over time speed = bulletInfo[5]; // bullet speed IsTracer = bulletInfo[6]; // Is it a tracer? (Trail Renderer) newPos = transform.position; // bullet's new position oldPos = newPos; // bullet's old position velocity = speed * transform.forward; // bullet's velocity determined by direction and bullet speed // drection bullet is traveling direction = transform.TransformDirection(Random.Range(-maxInaccuracyHIP, maxInaccuracyHIP) * spread, Random.Range(-maxInaccuracyHIP, maxInaccuracyHIP) * spread, 1); Destroy(gameObject, lifeTime); } function Start() { GetComponent(MeshRenderer).enabled = false; yield WaitForSeconds(0.01); GetComponent(MeshRenderer).enabled = true; //goWind = GameObject.Find("Wind"); if (IsTracer == 1){ Tracer = true; } if (Tracer == true){ TrailScript.GetComponent(TrailRenderer).enabled = true; } startPos = transform.position; } function FixedUpdate(){ newPos += (velocity + direction) * Time.deltaTime; oldPos = transform.position; // set old position to current position transform.position = newPos; // set current position to the new position if(hasHit) return; // Check if we hit anything on the way var dir : Vector3 = newPos - oldPos; dist = dir.magnitude; var fwd = transform.TransformDirection (Vector3.forward); var back = transform.TransformDirection (Vector3.back); // normalize dir /= dist; if(Physics.Raycast(newPos - (newPos - oldPos), fwd, hit, dist)){ newPos = hit.point; // notify hit OnHit(hit); EntryPoint = newPos; if (hitCount >= maxHits) { hasHit = true; Destroy(gameObject); } } if (Physics.Raycast(newPos + (newPos - oldPos), back, hit2, dist)) { // send a ray behind the bullet to check for exit impact ExitPoint = hit2.point; Width = Vector3.Distance(EntryPoint, ExitPoint); Debug.Log("Width is: " + Width); ExitPoint = Vector3.zero; EntryPoint = Vector3.zero; OnBackHit(hit2); // send rear impact and check what to do with it } velocity.y -= Gravity * Time.deltaTime; Rotation.transform.rotation = Quaternion.LookRotation(dir); } function OnHit(hit : RaycastHit){ hitCount++; // add another hit to counter var contact : Vector3 = hit.point; // point where bullet hit var rotation : Quaternion = Quaternion.FromToRotation(Vector3.up, hit.normal); // rotation of bullet impact var direction2 = gameObject.transform.TransformDirection(Vector3(Random.Range(-0.01, 0.01) * spread, Random.Range(-0.01, 0.01) * spread, 1)); var hitHeight : float = 0.008; endPos = transform.position; distance = Vector3.Distance(startPos, endPos); DamageDropoff = distance / 10; RawDamage = damage - DamageDropoff; FinalDamage = Mathf.Round(RawDamage); if(FinalDamage < 10){ FinalDamage = 10; } if (hit.rigidbody) hit.rigidbody.AddForceAtPosition(force * direction2, hit.point); hit.collider.SendMessageUpwards("ApplyDamage", FinalDamage, SendMessageOptions.DontRequireReceiver); hit.collider.SendMessageUpwards("PlayerDamage", FinalDamage, SendMessageOptions.DontRequireReceiver); if (hit.transform.tag == "Untagged" && Untagged != null) { var untaggedHole : GameObject = Instantiate(Untagged, hit.point, rotation) as GameObject; untaggedHole.transform.localPosition += hitHeight * hit.normal; untaggedHole.transform.parent = hit.transform; } if (hit.transform.tag == "Concrete" && Concrete != null) { var concreteHole : GameObject = Instantiate (Concrete, hit.point, rotation) as GameObject; concreteHole.transform.localPosition += hitHeight * hit.normal; concreteHole.transform.parent = hit.transform; } if (hit.transform.tag == "Wood" && Wood != null) { var woodHole = Instantiate (Wood, hit.point, rotation) as GameObject; woodHole.transform.localPosition += hitHeight * hit.normal; woodHole.transform.parent = hit.transform; } if (hit.transform.tag == "Metal" && Metal != null) { var metalHole = Instantiate (Metal, hit.point, rotation) as GameObject; metalHole.transform.localPosition += hitHeight * hit.normal; metalHole.transform.parent = hit.transform; } if (hit.transform.tag == "Enemy" && Blood != null) { var bloodHole = Instantiate (Blood, hit.point, rotation) as GameObject; bloodHole.transform.localPosition += hitHeight * hit.normal; bloodHole.transform.parent = hit.transform; return; } if (hit.transform.tag == "Player" && Blood != null) { var playerHole = Instantiate (Blood, hit.point, rotation) as GameObject; playerHole.transform.localPosition += hitHeight * hit.normal; playerHole.transform.parent = hit.transform; return; } if (hit.transform.tag == "Snow" && Snow != null) { var snowHole = Instantiate (Snow, hit.point, rotation) as GameObject; snowHole.transform.localPosition += hitHeight * hit.normal; snowHole.transform.parent = hit.transform; } if (hit.transform.tag == "Dirt" || hit.transform.tag == "Grass"|| hit.transform.tag == "Sand" && Dirt != null) { var dirtHole = Instantiate (Dirt, hit.point, rotation) as GameObject; dirtHole.transform.localPosition += hitHeight * hit.normal; dirtHole.transform.parent = hit.transform; } if (hit.transform.tag == "Water" && Water != null) { var waterHole = Instantiate (Water, hit.point, rotation) as GameObject; waterHole.transform.localPosition += hitHeight * hit.normal; waterHole.transform.parent = hit.transform; } if (hit.transform.tag == "Glass" && Glass != null) { var glassHole = Instantiate (Glass, hit.point, rotation) as GameObject; glassHole.transform.localPosition += hitHeight * hit.normal; glassHole.transform.parent = hit.transform; } if(debugDamage){ Debug.Log("Start Damage: " + damage); Debug.Log("Hit Distance: " + distance); Debug.Log("Damage Drop-Off: " + DamageDropoff); Debug.Log("Raw Damage: " + RawDamage); Debug.Log("Current Damage is : " + FinalDamage); } } function OnBackHit(hit : RaycastHit){ var contact : Vector3 = hit.point; // point where bullet hit var rotation : Quaternion = Quaternion.FromToRotation(Vector3.up, hit.normal); // rotation of bullet impact var hitHeight : float = 0.008; width = 0; //if(Width > MaximumPenetration){ //Destroy(gameObject); //return; //} if (hit.transform.tag == "Untagged" && Untagged != null) { var untaggedHole : GameObject = Instantiate(Untagged, hit.point, rotation) as GameObject; untaggedHole.transform.localPosition += hitHeight * hit.normal; untaggedHole.transform.parent = hit.transform; } if (hit.transform.tag == "Concrete" && Concrete != null) { var concreteHole : GameObject = Instantiate (Concrete, hit.point, rotation) as GameObject; concreteHole.transform.localPosition += hitHeight * hit.normal; concreteHole.transform.parent = hit.transform; } if (hit.transform.tag == "Wood" && Wood != null) { var woodHole = Instantiate (Wood, hit.point, rotation) as GameObject; woodHole.transform.localPosition += hitHeight * hit.normal; woodHole.transform.parent = hit.transform; } if (hit.transform.tag == "Metal" && Metal != null) { var metalHole = Instantiate (Metal, hit.point, rotation) as GameObject; metalHole.transform.localPosition += hitHeight * hit.normal; metalHole.transform.parent = hit.transform; } if (hit.transform.tag == "Enemy" && Blood != null) { var bloodHole = Instantiate (Blood, hit.point, rotation) as GameObject; bloodHole.transform.localPosition += hitHeight * hit.normal; bloodHole.transform.parent = hit.transform; } if (hit.transform.tag == "Dirt" || hit.transform.tag == "Grass" && Dirt != null) { var dirtHole = Instantiate (Dirt, hit.point, rotation) as GameObject; dirtHole.transform.localPosition += hitHeight * hit.normal; dirtHole.transform.parent = hit.transform; } if (hit.transform.tag == "Glass" && Glass != null) { var glassHole = Instantiate (Glass, hit.point, rotation) as GameObject; glassHole.transform.localPosition += hitHeight * hit.normal; glassHole.transform.parent = hit.transform; } } The specific bit of the code that handles registering the bullet exit hole: Code (JavaScript): if (Physics.Raycast(newPos + (newPos - oldPos), back, hit2, dist)) { // send a ray behind the bullet to check for exit impact ExitPoint = hit2.point; Width = Vector3.Distance(EntryPoint, ExitPoint); Debug.Log("Width is: " + Width); ExitPoint = Vector3.zero; EntryPoint = Vector3.zero; OnBackHit(hit2); // send rear impact and check what to do with it } So the actual problem is that it doesn't leave an exit hole on the first object or an entrance hole on the second, I'm assuming that this is because the bullet is moving to quick for the code to keep up. But that seems bizzare to me. Anyway any help would be much appreciated. Thanks - Aiden Leeming
Tip #1 - Don't post 300 lines of code and then go grab a coke, expecting your problem to be solved when you get back. Without even looking at it, are you using Physics.RaycastAll? Because a Physics.Raycast is only going to retrieve the first hit. You must also understand that there are instances that a Physics.Raycast will NOT register a hit, it must pass through a mesh perpendicularly AND it must pass through the mesh from outside-in, you can't get a Hit from the back side of a mesh.You'd do well to actually fire a RaycastAll in the bullet firing direction and then from the stop point of the RaycastHit back toward the origin point. Good luck. I just saw your picture. But, here's the concept that comes to my mind. We need to fire a RaycastAll to get every hit. Wherever there's a hit, leave a bullet hole. The rest is just a matter of refinement.