- Home /
Prevent Bullets from going through objects/ No raycast
I have 2 Scripts 1 is attached to the gun the other to the bullet. The problem is, (and i really looked everywhere but nothing worked) that the bullets sometimes are going through objects. My scripts: GUN: #pragma strict
var Bullet : Rigidbody;
var FirePoint : Transform;
var shot : AudioClip;
var FireType : int = 0;
// 0 = Auto, 1 = Single, 2 = burst
private var autoTimer : float;
private var singleTimer : float;
var myTimer : float;
var myTimerSingle : float;
var BurstTimer : float;
var BurstCount : int;
private var myTimerBurst : float = 0.075;
var BurstFired = false;
var BurstReload : float = 1.5;
var force: float = 2.5; // controls recoil amplitude
var upSpeed: float = 9; // controls smoothing speed
var dnSpeed: float = 20; // how fast the weapon returns to original position
private var ang0: Vector3; // initial angle private
var targetX: float; // unfiltered recoil angle private
var ang = Vector3.zero; // smoothed angle
function Recoil()
{
targetX += force; // add recoil force
}
function Start()
{
autoTimer = myTimer;
singleTimer = myTimerSingle;
BurstTimer = myTimerBurst;
ang0 = transform.localEulerAngles;
}
function Update()
{
ang.x = Mathf.Lerp(ang.x, targetX, upSpeed * Time.deltaTime);
transform.localEulerAngles = ang0 - ang; // move the camera or weapon
targetX = Mathf.Lerp(targetX, 0, dnSpeed * Time.deltaTime); // returns to rest
if(Input.GetKeyDown(KeyCode.T))
{
FireType += 1;
}
if(FireType == 3)
{
FireType = 0;
}
if(autoTimer > 0)
{
autoTimer -= 1*Time.deltaTime;
}
if(autoTimer <= 0)
{
autoTimer = 0;
}
if(singleTimer > 0)
{
singleTimer -= 1*Time.deltaTime;
}
if(singleTimer <= 0)
{
singleTimer = 0;
}
if(BurstTimer > 0)
{
BurstTimer -= 1*Time.deltaTime;
}
if(BurstTimer <= 0)
{
BurstTimer = 0;
}
if(BurstCount == 0)
{
BurstCount = 3;
BurstFired = false;
BurstReload = 0.3;
}
if(BurstReload > 0)
{
BurstReload -= 1*Time.deltaTime;
}
if(BurstReload < 0)
{
BurstReload = 0;
}
}
function FixedUpdate ()
{
if(Input.GetButtonDown("Fire1") && FireType == 1 && singleTimer == 0 && Ammo.ClipAmmo > 0)
{
var BulletInstance : Rigidbody;
BulletInstance = Instantiate(Bullet, FirePoint.position, transform.rotation);
BulletInstance.AddForce(FirePoint.forward * 50);
audio.PlayOneShot(shot, 0.1);
singleTimer = myTimerSingle;
Recoil();
Ammo.ClipAmmo -= 1;
}
if(Input.GetButton("Fire1") && FireType == 0 && autoTimer == 0 && Ammo.ClipAmmo > 0)
{
BulletInstance = Instantiate(Bullet, FirePoint.position, FirePoint.rotation);
BulletInstance.AddForce(FirePoint.forward * 30000);
audio.PlayOneShot(shot, 0.1);
autoTimer = myTimer;
Recoil();
Ammo.ClipAmmo -= 1;
}
if(BurstFired == true && FireType == 2 && BurstTimer == 0 && BurstCount > 0 && BurstReload == 0 && Ammo.ClipAmmo > 0)
{
BulletInstance = Instantiate(Bullet, FirePoint.position, FirePoint.rotation);
BulletInstance.AddForce(FirePoint.forward * 30000);
audio.PlayOneShot(shot, 0.1);
BurstCount -= 1;
BurstTimer = myTimerBurst;
Recoil();
Ammo.ClipAmmo -= 1;
}
if(Input.GetButtonDown("Fire1") && FireType == 2)
{
BurstFired = true;
}
}
Bullet:
#pragma strict
var lifeTime : float = 10;
function OnCollisionEnter ()
{
Destroy(gameObject);
}
function FixedUpdate ()
{
rigidbody.collisionDetectionMode = CollisionDetectionMode.ContinuousDynamic;
}
function Update()
{
lifeTime -= 1*Time.deltaTime;
if(lifeTime <= 0)
{
Destroy(gameObject);
}
}
if anyone has any idea how to fix the problem it would be awesome, i already set the FixedTimestep to 0.01 and i dont want to use raycast because i want the bullets to go down with the time(gravity)
thanks in advance skullbeats1
Answer by Itaros · Oct 28, 2014 at 01:35 PM
It is how broadphase evaluation works in PhysX. If you go through its range no physics goes involved. The only solution is raycasting and "scheduling by raycasting". Technically, you need to perform a raycast, plan ahead and track when bullet will hit the wall and then perform velocity manipulation so it will end up frame in contact position. In next physics frame you can return force projected to collision event to make sure impact energy is conserved if you need that way of precision to actually use bullets.
Answer by Bieere · Oct 28, 2014 at 02:00 PM
It's recommended that you do use the raycasting as it will reduce the performance costs on the bullets themselves during runtime.
Now that being said if you have no real interest in using the raycast, what ever the reason you have another option. Put a box collider on the bullet and increase the size of the collider itself. If the bullet is too fast, the physics engine wont have be able to calculate the collision that had occured, and you'll see the bullet go through walls more often then not. Decrease the speed as well.
So TL;DR:
Use a box collider, with a size that is large for the bullet
Decrease the speed of the bullet
If these steps don't work, take the time to learn raycasts, it will be useful for you in the long run
Answer by _dns_ · Oct 28, 2014 at 03:32 PM
Hi, the problem you have can be solved by Raycasting, and you can still use gravity on your bullets. (You can also try Unity5 that just went Beta yesterday and is supposed to better handle high speed objects)
So, your bullet will move from it's current position to the next using the forces you added. Those forces will be computed by Unity into a velocity. You can use this velocity to know where your object will be after the physics engine update (that is computed just after all FixedUpdate()). Then, during each FixedUpdate, you can raycast a ray (from the bullet's position) that is equal to rigidbody.velocity * Time.fixedDeltaTime. This is the ray your bullet will move until the next FixedUpdate (you may now increase your FixedTimeSteps back to something like 1/30 or you may slow your game down with to small value).
The only thing that is missing is applying the gravity to this ray as Unity would do. I'm not sure how Unity apply gravity. Ignoring it may be accurate enough as the current velocity uses the gravity applied from previous frame anyway. You can also try using something like (in C#):
Vector3 myBulletVelocity = rigidbody.velocity + Physics.gravity * Time.fixedDeltaTime;
Vector3 myRay = myBulletVelocity * Time.fixedDaltaTime;
Your answer
Follow this Question
Related Questions
Looping animation on rightmousebutton? 1 Answer
Shooting multiple bullets 2 Answers
gun problems 1 Answer
Help on a pick up/reload script 3 Answers
Gun Script 1 Answer