- Home /
Bullet collision help
My bullets are occasionally flying through objects and I really can't figure out why. I'm using raycasting as opposed to colliders. Strangely, the speed of the bullet doesn't seem to stop this from happening, can anyone see anything wrong with my code?
using UnityEngine;
using System.Collections;
public class BulletBase : MonoBehaviour {
public const string BulletHit = "bullethit";
public const string BulletExplode = "bulletExplode";
public float speed = 10.0F;
public float lifeTime = 2.0F;
protected Transform _tr;
protected float _spawnTime = 0.0F;
private void Awake() {
_tr = transform;
}
public virtual void Start() {
_tr = transform;
_spawnTime = Time.time;
}
private void FixedUpdate() {
// Check for collisions
RaycastHit hit;
if (Physics.Raycast(_tr.position, _tr.forward, out hit, 1.0F)){
if(hit.transform){
Messenger<RaycastHit>.Broadcast(BulletBase.BulletHit, hit);
DestroyBullet();
return;
}
}
}
private void Update() {
_tr.position += _tr.forward * speed * Time.deltaTime;
if (Time.time > _spawnTime + lifeTime){
DestroyBullet();
}
}
public void DestroyBullet(){
ObjectPoolManager.DestroyPooled( gameObject );
gameObject.SetActiveRecursively(false);
}
}
Answer by Statement · Aug 13, 2011 at 11:59 AM
You're raycasting 1 unit ahead, but move them 10 per second. This is error prone. Try something like this:
private void FixedUpdate() {
// Check for collisions
RaycastHit hit;
float moved = speed * Time.deltaTime;
if (Physics.Raycast(_tr.position, _tr.forward, out hit, moved)){
if(hit.transform){
Messenger<RaycastHit>.Broadcast(BulletBase.BulletHit, hit);
DestroyBullet();
return;
}
}
// Moved Update code to FixedUpdate.
_tr.position += _tr.forward * moved;
if (Time.time > _spawnTime + lifeTime){
DestroyBullet();
}
}
private void Update() {
// Nothing goes here
}
Basically, move the update code to fixed update and raycast for as long down the line you intend to move it. FixedUpdate may happen more frequently than your Update so you should also move the transform in FixedUpdate.
Oh and you might want to do the life time test in the beginning of the function, with an early return if it was destroyed.
You've got clean code there, but I am curious as to why you get the transform in both Awake and Start? This is of course of little importance but I thought you want to tidy that up too. Nice code.
Well this snippet is actually an amalgamation of two classes (which is why Start() is virtual) , I have a base bullet class and a sub class which is unique for each different bullet type. Since I am using the Object Pool, I need to reset the transform as the Start() method gets called when the bullet is resurrected. I could probably do without the Awake method though, thanks for noticing :)