- Home /
A Bullet's rigidbody, hit.normal
Q1.I have a problem with using a GameObject as a bullet instead of a Ray. I'd use Rays if it werent for it to be invisible and no flying bullets that are present.
The problem now with a rigidbody is that I want a bullethole to appear(a plane with a picture) where the bullet hits a part with the tag "LevelParts" and some sparks at the same point.
Now with a rigidbody the first thing is that you don't have any hit.normal as in Rays. And then the collision detection doesnt record a collision if the bullet goes too fast.
Code attached to bullet:
var maxDist : float = 1000000000;
var decalHitWall : GameObject;
var floatInfrontOfWall : float = 0.0001;
function Update () {
Destroy(gameObject, 3);
}
function OnTriggerEnter(hit : Collider){
if(hit.gameObject.CompareTag("Enemy")){
hit.gameObject.SendMessage("OnDamage", null);
Destroy(gameObject);
Debug.Log("Hit an enemy");
}
if(hit.tag == "LevelParts"){
Destroy(gameObject);
Debug.Log("Hit a levelpart");
}
}
To get the bullet to record a collision every time I got to set the bulletspeed to about 1500 which is very slow, About 3000 is the normal speed I have on the bullet right now.
Help would be appreciated
Q2. Is there any difference between hit.tag or hit.gameObject.CompareTag("") ??
Q3. I have tried many ways of turning my bullet the way I want it to but it just points straight up in the air even tho it flies as it should to the right direction,
var projectile = Instantiate(Bullet, transform.position, Quaternion.identity);
projectile.rigidbody.AddForce(transform.forward * bulletSpeed);
The bullet's tip is ^ but it should be pointing > or < depending on to what direction you shoot(2D platformer)
Answer by aldonaletto · Jun 08, 2012 at 03:11 PM
1- OnTrigger events don't record collision info - they just pass the other collider reference. You should use OnCollisionEnter(col: Collision) to get more detailed information - usually we read col.contacts[0] and extract info from it, like below. To avoid the fast bullet problem, a simple trick is to make its collider very long (one or two meters) and ahead of the bullet, like this:
var bulletHolePrefab: Transform; // drag the bullet hole prefab here var dust: ParticleEmitter; // drag a dust particle prefab here var blood: ParticleEmitter; // drag the blood particle prefab here
function OnCollisionEnter(col: Collision){ var part: ParticleEmitter; var contact: ContactPoint = col.contacts[0]; // get first contact point // calculate rotation from prefab normal to contact.normal: var rot = Quaternion.FromToRotation(Vector3.up, contact.normal); if (col.gameObject.CompareTag("Enemy")){ col.gameObject.SendMessage("OnDamage", null); Debug.Log("Hit an enemy"); part = blood; // select blood particles } if (col.gameObject.CompareTag("LevelParts")){ Debug.Log("Hit a levelpart"); part = dust; // select dust particles var hole = Instantiate(bulletHolePrefab, contact.point, rot); hole.parent = col.transform; // child the hole to the hit object } if (part){ // if some particle effect selected, create it... var p: ParticleEmitter = Instantiate(part, contact.point, rot); p.Emit(); // and emit a chunk of particles } Destroy(gameObject); // destroy bullet on any collision } NOTE: Since enemies usually have capsule colliders, attaching a bullet hole to them produces very weird effects - thus it's better to do it only for simple geometry.
2- gameObject.CompareTag is faster than comparing tags directly, and doesn't allocate memory - the tag names are actually stored in a Unity's table, and must be converted to a string when we read the tag property.
3- You're instantiating the bullet without any rotation (Quaternion.identity). Use transform.rotation instead:
var projectile = Instantiate(Bullet, transform.position, transform.rotation);
Weirdly enough none of that did work, my bullet is still pointin upwards, no bullethole and no sparks. It doesnt even register any hit cuz them bullets keep going through the wall.
Ah, I fixed the bullet rotation by messing with the object from which the bullet gets created and the AddForce.
projectile.rigidbody.AddForce(transform.up * bulletSpeed);
EDIT: I changed the bullet a little cuz it was so small and now it doe s show bulletholes but they are wrongly placed and I get a long error saying:
$$anonymous$$issingFieldException: Field 'UnityEngine.ContactPoint.hit' not found. Boo.Lang.Runtime.DynamicDispatching.PropertyDispatcherFactory.FindExtension (IEnumerable`1 candidates) Boo.Lang.Runtime.DynamicDispatching.PropertyDispatcherFactory.Create (SetOrGet gos) Boo.Lang.Runtime.DynamicDispatching.PropertyDispatcherFactory.CreateGetter () Boo.Lang.Runtime.RuntimeServices.DoCreatePropGetDispatcher (System.Object target, System.Type type, System.String name) Boo.Lang.Runtime.RuntimeServices.CreatePropGetDispatcher (System.Object target, System.String name) Boo.Lang.Runtime.RuntimeServices+c_AnonStorey14.<>m_9 () Boo.Lang.Runtime.DynamicDispatching.DispatcherCache.Get (Boo.Lang.Runtime.DynamicDispatching.Dispatcher$$anonymous$$ey key, Boo.Lang.Runtime.DynamicDispatching.DispatcherFactory factory) Boo.Lang.Runtime.RuntimeServices.GetDispatcher (System.Object target, System.String cache$$anonymous$$eyName, System.Type[] cache$$anonymous$$eyTypes, Boo.Lang.Runtime.DynamicDispatching.DispatcherFactory factory) Boo.Lang.Runtime.RuntimeServices.GetDispatcher (System.Object target, System.Object[] args, System.String cache$$anonymous$$eyName, Boo.Lang.Runtime.DynamicDispatching.DispatcherFactory factory) Boo.Lang.Runtime.RuntimeServices.GetProperty (System.Object target, System.String name) UnityScript.Lang.UnityRuntimeServices.GetProperty (System.Object target, System.String name)
In order to use OnCollision events, the bullet and the targets must have regular colliders (not triggers) - do they have their Is Trigger check boxes unchecked? Remember that in the bullet case you must clear it in the prefab (or set projectile.collider.isTrigger = false; right after instantiation).
Well It works better now but I still get the error a few times. By the way, is there a faster way of executing the code in the bullet cuz sometimes it falls to the ground and then the bullethole is created on the ground before its destroyed. And the bullethole isnt turned the right way, its like facing the wrong direction. Its like 90 degrees on the y axis wrong, and some holes get created in the air behind the wall.
There was an error in the following line:
var p: ParticleEmitter = Instantiate(part, contact.point, rot);
I've written contact.hit, which doesn't exist. Now the answer is fixed.
About the wrong direction: the hole planes are assumed to be facing the up direction. If they aren't, change Vector3.up in FromToRotation to the direction the hole is facing to: if it's facing the forward (blue axis) direction, use Vector3.forward.
Answer by multinfs · Jun 09, 2012 at 07:43 AM
Yea now its working better but not perfectly :/ If i shoot on the normal wall with normal collider nothing happens, and on the wall which have a thicker collider it works sometimes but not always and almost half of the bullets appear at the end of the collider instead of in front of.
Thanks for your time btw :)
Answer by multinfs · Jun 11, 2012 at 09:21 PM
I don't know why but the bullethole is like sometimes appearing at the other side of the wall or in the middle, I think it would be fixed if I only slowed down the bulletspeed but that comes with a problem.
Even if I set the angular drag very low the bullets drop to the floor after just a meter or two. I don't know how I'ma make it so that it would drop as normal after a long time in the air instead of dropping in front of the gun but still be slow enough to see it go and make the collision more accurate.
Answer by Mewada-Neil · Mar 12, 2015 at 05:17 PM
I think i can help you with the bulletHole code...
// You have to instantiate the bullet using another script
// Attach this script to bullet
// Edit it if you need
// You can raycast even when you are using physical bullet
// This will cast a ray which will be 2 units ahead of the bullet
var bulletHole: GameObject;
var rayDistance: float = 2.0f; // Note that the ray will be 2 units ahead of the bullet
var maxHits: int = 4;
private var oldPos;
private var newPos: Vector3;
private var hasHit: boolean = false;
private var hitCount: int = 0;
function Start ()
{
oldPos = transform.position;
newPos = transform.position;
}
function Update ()
{
if (hasHit) {
return;
}
newPos = transform.position;
var hits : RaycastHit[] = Physics.RaycastAll(newPos, transform.forward, rayDistance);
for (var i: int = 0; i < hits.Length; i++)
{
var hit: RaycastHit = hits[i];
newPos = hit.point;
hitCount++;
var holeRotation: Quaternion = Quaternion.FromToRotation(Vector3.up, hit.normal);
var holeInstance = Instantiate(bulletHole, hit.point, holeRotation);
if (hitCount >= maxHits) {
hasHit = true;
Destroy(gameObject);
return;
}
}
}