Collision check

Hey guys, I am trying to make a game with a player falling through a pipe.
Player has to avoid obstacles and collect something.
I can’t make it working good enough. I tried with OnTriggerEnter() to check the collision, no luck, super not accurate. With rayCast is better but still is not 100% satisfying.
What is the best way to check collisions when you make objects move with AddForce? Or if I move them with Translate> What’s better? Btw, Fixed Update doesn’t seem to affect anything that much…
Thank you in advance!

Here is a piece of code I use…

Collision Check script:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class ObstacleCollision : MonoBehaviour {

ObstaclesSpawn osScript;
ScreenFlashHit scrScript;
CoinSelfDestroy cdScript;
MotionBlur	mbScript;
GlowEffect geScript;

public int	hitCounter = 0; 
public int	coinCounter = 0;

public GameObject player;
public GameObject muzzle_prefab;
public GameObject muzzleCoin_prefab;
public GameObject coin;

public Transform  player_transform;

public Material obst_material;
public Material obst_swap_material;

public RaycastHit hit;

void Start()
{
    scrScript = GameObject.Find("Main Camera").GetComponent<ScreenFlashHit>();
	osScript  = GameObject.Find ("Main Camera").GetComponent<ObstaclesSpawn>();
	cdScript  = coin.GetComponent<CoinSelfDestroy>();
	mbScript  = GameObject.Find("Main Camera").GetComponent<MotionBlur>();
	geScript  = GameObject.Find("Main Camera").GetComponent<GlowEffect>();

	mbScript.enabled = false;
	geScript.enabled = false;

}

void Update()
{

}

void FixedUpdate()
{
	RayHitCheck();	//Its here coz the rate is stable
	RayHitCoinCheck();
}

void RayHitCheck()
{
	bool hitSomething = false; //I reset it each frame

	hitSomething = Physics.Raycast(player.transform.position, new Vector3(0, -1, 0), out hit, 0.8f); //check for the ray hit
	
	if(hitSomething)
	{
		if(hit.transform.tag == "Obstacle")	//here I create sparks 
		{
			scrScript.Flash(0.2f);	//screen red flash
			hitSomething = false;	
			hitCounter++;			//add to counter
			

			GameObject clone = Instantiate(muzzle_prefab, new Vector3(player.transform.position.x, player.transform.position.y - 1.0f, player.transform.position.z), Quaternion.identity) as GameObject;
			clone.rigidbody.AddForce(0, 10, 0);

		}
		if(hit.transform.tag == "Accell") 
		{
			Debug.Log("hit accell");
			MakeRedScreen();
			Invoke("RemoveRedScreen", 10.0f);

		}
		if(hit.transform.tag == "Stopper") 
		{
			osScript.obstSpeed = 1000;
			Debug.Log("hit stopper");
			MakeGreenScreen();
			Invoke("RemoveGreenScreen", 0.75f);
		}
	}
}
void RayHitCoinCheck()
{
	bool hitSomething = false; //I reset it each frame
	
	hitSomething = Physics.Raycast(player.transform.position, new Vector3(0, -1, 0), out hit, 1.5f); //check for the ray hit

	if(hitSomething)
	{
		if(hit.transform.tag == "Collectable") 
		{
			cdScript.SelfDistruction();
			coinCounter += 1;
			Debug.Log("hit coin");
			hitSomething = false;	

			GameObject clone = Instantiate(muzzleCoin_prefab, new Vector3(player.transform.position.x, player.transform.position.y - 1.0f, player.transform.position.z), Quaternion.identity) as GameObject;
			clone.rigidbody.AddForce(0, 10, 0);
		}
		hitSomething = false;
	}
	hitSomething = false;
}

void MakeGreenScreen()
{
	mbScript.enabled = false;
	geScript.enabled = true;
	geScript.glowTint = new Color(0.0f,0.5f, 0.0f, 0.0f);
}
public void RemoveGreenScreen()
{
	geScript.enabled = false;
}

void MakeRedScreen()
{
	mbScript.enabled = true;
	geScript.enabled = true;
	mbScript.blurAmount = 0.75f;
	geScript.glowTint = new Color(0.5f, 0.0f, 0.0f, 0.0f);
	osScript.obstSpeed = 2000;
}
public void RemoveRedScreen()
{
	mbScript.enabled = false;
	geScript.enabled = false;
	osScript.obstSpeed = 1000;
}

}

PowerUp Spawn script:

using UnityEngine;
using System.Collections.Generic;
using System.Collections;

public class PowerUpScript : MonoBehaviour {

public GameObject stopperPrefab;
public GameObject accellPrefab;
public GameObject coinPrefab;

public float collectablesSpeed = 1500f;

float counter1;
float counter2;
bool ready1 = false;
bool ready2 = false;
bool ready3 = false;

// ObstaclesSpawn osScript;

void Start()
{
}

void FixedUpdate()
{
	SpawnDestroyStopper();
	SpawnDestroyAccell();
	SpawnDestroyCoins();
}

void Update()
{
	Counter();
}

void SpawnDestroyStopper()
{
	if(ready1)
	{
		float rand_x_pos = Random.Range(-2.0f, 2.0f);
		float rand_z_pos = Random.Range(-2.0f, 2.0f);

		GameObject clone = Instantiate(stopperPrefab, new Vector3(rand_x_pos, -125, rand_z_pos), Quaternion.identity) as GameObject;
		clone.rigidbody.AddForce(new Vector3(0, collectablesSpeed, 0), ForceMode.Force);
		clone.transform.Rotate(Time.deltaTime, Time.deltaTime, Time.deltaTime, Space.Self);
		ready1 = false;

		DestroyObject(clone, 10.0f);
	}
}
void SpawnDestroyAccell()
{
	if(ready2)
	{
		float rand_x_pos = Random.Range(-2.0f, 2.0f);
		float rand_z_pos = Random.Range(-2.0f, 2.0f);

		GameObject clone = Instantiate(accellPrefab, new Vector3(rand_x_pos, -125, rand_z_pos), Quaternion.identity) as GameObject;
		clone.rigidbody.AddForce(new Vector3(0, collectablesSpeed, 0), ForceMode.Force);
		clone.transform.Rotate(Time.deltaTime, Time.deltaTime, Time.deltaTime, Space.Self);
		ready2 = false;
		
		DestroyObject(clone, 10.0f);
	}
}

void SpawnDestroyCoins()
{
	if(ready3)
	{
		float rand_x_pos = Random.Range(-2.0f, 2.0f);
		float rand_z_pos = Random.Range(-2.0f, 2.0f);
		
		GameObject clone = Instantiate(coinPrefab, new Vector3(rand_x_pos, -125, rand_z_pos), Quaternion.identity) as GameObject;
		clone.rigidbody.AddForce(new Vector3(0, collectablesSpeed, 0), ForceMode.Force);
		clone.transform.Rotate(Time.deltaTime, Time.deltaTime, Time.deltaTime, Space.Self);
		ready3 = false;
		
		DestroyObject(clone, 10.0f);
	}
}

void Counter()
{
	counter1 += Time.deltaTime;
	counter2 += Time.deltaTime;

	if(counter1 >= 5) 
	{
		ready1 = true;
		ready2 = true;
		counter1 = 0;
	}
	if(counter2 >= .5) 
	{
		ready3 = true;
		counter2 = 0;
	}
}

}

Sorry, I forgot to remove all the comments, so there is a little break in PowerUpScript.

1 Answer

1

Use both! With fast moving objects colliders will occasionally pass through each other. First step is to set your colliders to continuous detection that will catch more collisions.

Secondly, if we detect a hit with the raycast, pull our collider back to the hit location. If you want to be really safe you could do a couple raycasts to cover the width of the collider. Either way, by pulling the object back, we stop handling the collision ourselves and allow an “OnEnterCollision()” to be called.

Hi, thanks for your answer! A am not even an intermediate user. I am quite new to all this. I know what u'r talking about, but can barely visualize the collider pull back.. Could you be more specific in this? And one more, the raycast works quite stable, however, the downside is that it "shoots" 3-4 times per collision. I can't use it's value for, say, collectables counting. Is there any way to be more accurate in here? Maybe drop a bool somewhere.. Thank you!!