- Home /
How can I make sure triggers or collisions are never skipped even for high speeds?
Firstoff: I once made a forum post that handelled a simular problem and I also added this to it, but I'm not getting any reactions so I'm just going to refer to it here. (it may be eassier to read it over there. Forum post
I have 2 types of bullets and the problems are I think simular in solution but the effect is somewhat different.
My first bullet type is a fireball, it just moves in straight lines, when colliding with a player it is destroyed unless it's the player who fired the bullet, if it collides with another bullet or object or ground it should be destroyed aswel. Now for some reason 2 colliding bulelts arn't always detected, 2/3 times they get destroyed, 1/3 they just continue.
I just noticed that if I try hard enough I can even pass through walls: GIF: Another thing that goes wrong
This is my collision matrix: IMG: Collision Matrix
The code that sees if any trigger has been made:
using UnityEngine;
using System.Collections;
/// <summary>
/// Stef Geukens
///
/// This code will determine if the object it is attached to has triggered a overlap with a collider object.
/// If so, the object is destroyed. When the object hits another player then his own (set playernum to the correct player)
/// then a function is called (Hurt) in the ShotPlayer script so thaty script knows when the score in the scorescript has
/// to be updated and for what player.
/// </summary>
public class BulletTriggerDetection : MonoBehaviour {
public static BulletTriggerDetection BTD;
public int playerNum = 1;
public bool destroyOnImpact = true;
public bool destroyOnTimer = true;
public bool destroyOnNumberOfCollides = false;
public int maxNumberOfCollides = 6;
private int numberOfCollides = 0;
void Start()
{
BTD = gameObject.GetComponent<BulletTriggerDetection>(); ;
}
void OnTriggerEnter2D(Collider2D col)
{
Debug.Log(gameObject.name + " has collided with " + col.gameObject.name);
Debug.Log("My layer: " + gameObject.layer);
Debug.Log("Number of Impacts: " + numberOfCollides);
if (playerNum == 1)
{
if (col.gameObject.tag == ("Player2") || col.gameObject.tag == ("Player3") || col.gameObject.tag == ("Player4"))
{
col.gameObject.GetComponent<ShotPlayer>().Hurt(col.gameObject.tag, playerNum);
// Debug.Log("Player" + playerNum + " just shot " + col.gameObject.tag);
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player1") && destroyOnImpact)
{
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player1"))
{
numberOfCollides += 1;
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
}
else if (playerNum == 2)
{
if (col.gameObject.tag == ("Player1") || col.gameObject.tag == ("Player3") || col.gameObject.tag == ("Player4"))
{
Debug.Log("State1");
col.gameObject.GetComponent<ShotPlayer>().Hurt(col.gameObject.tag, playerNum);
// Debug.Log("Player" + playerNum + " just shot " + col.gameObject.tag);
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player2") && destroyOnImpact)
{
Debug.Log("State2");
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player2"))
{
Debug.Log("State3");
numberOfCollides += 1;
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
}
else if (playerNum == 3)
{
if (col.gameObject.tag == ("Player1") || col.gameObject.tag == ("Player2") || col.gameObject.tag == ("Player4"))
{
col.gameObject.GetComponent<ShotPlayer>().Hurt(col.gameObject.tag, playerNum);
// Debug.Log("Player" + playerNum + " just shot " + col.gameObject.tag);
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player3") && destroyOnImpact)
{
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player3"))
{
numberOfCollides += 1;
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
}
else if (playerNum == 4)
{
if (col.gameObject.tag == ("Player1") || col.gameObject.tag == ("Player2") || col.gameObject.tag == ("Player3"))
{
col.gameObject.GetComponent<ShotPlayer>().Hurt(col.gameObject.tag, playerNum);
// Debug.Log("Player" + playerNum + " just shot " + col.gameObject.tag);
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player4") && destroyOnImpact)
{
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
else if (col.gameObject.tag != ("Player4"))
{
numberOfCollides += 1;
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
}
}
public static void destroyBullet(GameObject objectInNeedOfDestruction, float destroyTimer, bool hit, bool exDestroyOnTimer, bool exDestroyOnCollide)
{
Vector3 position = objectInNeedOfDestruction.transform.position;
Quaternion rotation = objectInNeedOfDestruction.transform.rotation;
if (BTD.destroyOnTimer && exDestroyOnTimer)
{
Destroy(objectInNeedOfDestruction, destroyTimer);
BTD.showBulletAnimation(position, rotation, hit);
}
else if (BTD.destroyOnNumberOfCollides && BTD.numberOfCollides >= BTD.maxNumberOfCollides)
{
Destroy(objectInNeedOfDestruction, 0);
BTD.showBulletAnimation(position, rotation, hit);
}
}
public Transform hitPrefab;
void showBulletAnimation(Vector3 position, Quaternion rotation, bool hit)
{
if (hit)
{
Transform hitParticleClone = Instantiate(hitPrefab, position, rotation) as Transform;
Destroy(hitParticleClone.gameObject, 2f);
}
}
}
gameobject settings (rigidbody is set to continues): IMG: Setting Fireball
The second type of bullet is a rubber ball, effected by gravity and it should bounce of objects and ground, and get destroyed by other bullets or hitting and killing a player.
As you can see this parent has been set as a trigger as to be destroyed by a player or another bullet, the child has been set as collider: IMG: More information about the Rubberball
GIF: Showing the problem with the rubber ball
With very low speeds the rubber ball seems to work a bit beter but thats not what I want. GIF: Showing it works on low speed
Answer by korbul · May 04, 2016 at 05:39 PM
Hello,
The quick thing you can try, is to play with your Physics2d settings where the collision matrix is.
You can find what each setting does here http://docs.unity3d.com/Manual/class-Physics2DManager.html
For starters, you may want to increase Velocity Iterations and Position Iterations but the other settings may help you as well.
Now for the off-topic part.
I looked at your code and there is quite a lot of duplication just for checking
if (playerNum == 1) else if (playerNum == 2) etc ...
This does not scale well with more players. Imagine if at some point, you want to add 2 more players. You would have to change a lot of code.
My suggestion is to tag all players with the tag "Player". Just "Player", no number after it. Now your OnTriggerEnter2D becomes
void OnTriggerEnter2D(Collider2D col)
{
Debug.Log(gameObject.name + " has collided with " + col.gameObject.name);
Debug.Log("My layer: " + gameObject.layer);
Debug.Log("Number of Impacts: " + numberOfCollides);
if(col.gameObject.tag == ("Player"))
{
BulletTriggerDetection otherBTD = col.GetComponent<BulletTriggerDetection>();
if(playerNum != otherBTD.playerNum)
{
col.gameObject.GetComponent<ShotPlayer>().Hurt(col.gameObject.tag, playerNum);
// Debug.Log("Player" + playerNum + " just shot " + col.gameObject.tag);
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
numberOfCollides += 1;
}
}
else if(destroyOnImpact)
{
destroyBullet(gameObject, 0, true, destroyOnTimer, destroyOnNumberOfCollides);
}
}
Thanks, you've been a great help! I'm still learning what it is I can do with Unity and there is allot to learn!
Today I learned something new, thank you ^^
It seems I was to fast to react, I quickly looked at it and basics seem to work, but then I started shooting my opponent and the bullets go straight through. (That was also the initial reason for my duplication :p)
Hey, I have no doubt that what I suggested would work. The code above was written without knowledge of your whole code. You need to adjust some things for it to work properly.
Also, the duplication removal i suggested was not a fix for bullets going trough objects. It's just a suggestion
Hi, yeah I know that the duplication part wasn t a solution to my original question. But now my other player don't get triggered, so your code isn t a valid alternative for my code, I lokken at it but I can't really find a solution for this. But I will look if I can get the duplication out
Answer by coolraiman · May 04, 2016 at 07:27 PM
if your bullet actually go as fast as a real bullet (higher than the speed of sounds), Use raycasting. This way you are sure to miss nothing. only down side with raycasting, it does not work well for large object.
It's a 2D platformer and the bullets are slow, you can dodge them if you want. So I didn't think it would be to fast
is the Is Trigger on your collider on? trigger function only work if you checked the is trigger
Your answer
Follow this Question
Related Questions
2D collision not registering 1 Answer
Trigger2D not working 0 Answers
collider doesnt work the 2nd time 1 Answer
Unity 2D Collider Safe Sizes 0 Answers