- Home /
Triggers (colliders?) randomly stop working
Hey. I am working on my very first project in Unity. I have encountered a major problem though, that I don't even know how to approach, let alone tackle. The project is a simple top-down shooter based mostly on the "shooter project" tutorial. All seems to be working as intended for the most part. You can play the game on a website I have published it on, except on some rare, seemingly random occasions, all the collision detection just stops working. You can fly through enemies, bullets do not register and fly through everything... Any ideas what could be causing this? Any help would be greatly appreciated as I have no idea how to start battling this issue. I can't even debug it as I have never seen this in the Unity software. It just happened to me in the exported version on the web site and even the it's once per 10 or 15 plays.
EDIT:
Here is the code I wrote. As I mentioned most is just a copy of the "shooter project" from Unity official site.
Destroy (a script for enemy hp, destruction if hp falls to 0 and helps with counting score. It also adds few minor details to make it look a bit better):
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
[System.Serializable]
public class Destroy : MonoBehaviour
{
bool IsDead;
private float DeathSilence ;
public float EnemyHP;
public GameObject Explosion;
public GameObject SmallExplosion;
public GameObject Smoke;
public int scoreValue;
private GameController gameController;
public AudioClip Impact;
void Start ()
{
GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
if (gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent <GameController>();
Debug.Log ("We have a 'GameController' script");
}
if (gameController == null)
{
Debug.Log ("Cannot find 'GameController' script");
}
}
void OnTriggerEnter(Collider other)
{
if (other.tag == "Shot")
{
audio.PlayOneShot (Impact);
audio.volume = 0.05f;
Instantiate (Smoke, transform.position, transform.rotation);
EnemyHP = EnemyHP - 1f;
Instantiate (Smoke, transform.position, transform.rotation);
Destroy (other.gameObject);
}
if (other.tag == "Sidewinder")
{
Instantiate (Smoke, transform.position, transform.rotation);
Instantiate (SmallExplosion, transform.position, transform.rotation);
EnemyHP = EnemyHP - 10f;
Destroy (other.gameObject);
}
if (other.tag == "Player") {
Instantiate (Explosion, other.transform.position, other.transform.rotation);
}
Debug.Log (EnemyHP);
if (EnemyHP <= 0 && Time.time > DeathSilence)
{
death ();
IsDead = true;
Instantiate (Explosion, transform.position, transform.rotation);
Destroy (other.gameObject);
}
}
void death ()
{
if (IsDead == true)
gameController.AddScore (scoreValue);
DeathSilence = Time.time +1f;
gameController.AddScore (scoreValue);
Destroy (gameObject,0.1f);
}
}
Destroy smoke (just cleans up a bit)
using UnityEngine;
using System.Collections;
public class DestroySmoke : MonoBehaviour {
// Use this for initialization
void Start () {
Destroy (gameObject, 5);
}
}
Edge (another little cleaner makes sure stuff gets wiped after it goes off the screen):
using UnityEngine;
using System.Collections;
public class Edge : MonoBehaviour
{
void OnTriggerExit(Collider other)
{
Destroy(other.gameObject);
}
}
Enemy Fire (allows enemies to shoot. half of it could be deleted but I'll use it later so I don't bother):
using UnityEngine;
using System.Collections;
public class EnemyFire : MonoBehaviour
{
public float FireRate;
private float FireInterval;
public Transform EShotSpawn;
public Transform EShotSpawn2;
public GameObject shot;
public GameObject shot2;
void Update ()
{
if (Time.time > FireInterval)
{
FireInterval = Time.time + FireRate;
Instantiate (shot, EShotSpawn.position, EShotSpawn.rotation);
audio.Play ();
}
}
}
Game control (Oh boy. This one spawns the enemies, keeps track of the game state and if player is alive etc)
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameController : MonoBehaviour
{
public GameObject Enemy;
public Vector3 Spawns;
public float SpawnRate;
private float SpawnRateRandomized;
private float SpawnInterval;
private float MinSpawnRandFactor;
public Text ScoreText;
private int score;
public int AlertLvl;
private int Alertlvl;
private int AlertLvlRandomized;
public Text RestartText;
public Text KilledText;
private bool Player01Dead;
private bool Restart;
void Start ()
{
Player01Dead = false;
Restart = false;
RestartText.text = "";
KilledText.text = "";
Time.timeScale = 1.0f;
score = 0;
UpdateScore ();
}
void Update ()
{
MinSpawnRandFactor = SpawnRate * 0.5f;
SpawnRateRandomized = Random.Range (SpawnRate - MinSpawnRandFactor, SpawnRate + MinSpawnRandFactor);
AlertLvlRandomized = Random.Range (1, AlertLvl * AlertLvl);
Waves(); // WAVES STARTS STARTS HERE
if (Restart)
{
if (Input.GetKeyDown (KeyCode.Space))
{
Application.LoadLevel (Application.loadedLevel);
}
}
if (Input.GetKeyDown (KeyCode.Escape))
{
if (Time.timeScale == 1.0f)
{
Time.timeScale = 0.0f;
}
else
{
Time.timeScale = 1.0f;
}
}
}
//_______________________________WAVES FUNCTION EXECUTES HERE____________________________________________
void Waves ()
{
while (Time.time > SpawnInterval && Player01Dead == false)
{
for (Alertlvl = 0 ; Alertlvl <AlertLvlRandomized ; Alertlvl++ )
{
SpawnInterval = Time.time + SpawnRateRandomized;
Vector3 SpawnPosition = new Vector3 (Random.Range (-Spawns.x, Spawns.x), Spawns.y , Spawns.z + Alertlvl *4f);
Quaternion SpawnRotation = Quaternion.identity;
Instantiate (Enemy, SpawnPosition, SpawnRotation);
}
}
if (Player01Dead == true)
{
RestartText.text = "Press 'SPACE' to restart";
Restart = true;
}
}
public void AddScore (int newScoreValue)
{
score += newScoreValue;
UpdateScore ();
}
void UpdateScore ()
{
ScoreText.text = "Score: " + score;
}
public void MissionFailed ()
{
Player01Dead = true;
if (Player01Dead == true)
{
KilledText.text = "Mission Failed";
}
}
}
Mover 03 (I have 4 of these, responsible for movement of NPCs, bullets, ground scrolling etc. This one is the longest one)
using System.Collections;
public class Mover03 : MonoBehaviour
{
public float speed;
private float XPosition;
private float ZPosition;
private bool XCheck;
public float Chance;
private float DirectionRandomized;
void Start ()
{
DirectionRandomized = Random.Range (0, Chance);
XCheck = false;
XPosition = rigidbody.transform.position.x;
rigidbody.velocity = transform.forward * speed;
if (XPosition < 0)
{
XCheck = true;
}
}
void Update ()
{
ZPosition = rigidbody.transform.position.z;
if (DirectionRandomized >= 1)
{
if (ZPosition <= 24 && XCheck == true) {
rigidbody.AddForce (Vector3.right * speed * -0.5f);
}
if (ZPosition <= 24 && XCheck == false) {
rigidbody.AddForce (Vector3.right * speed * 0.5f);
}
}
}
}
PlayerCController (And finally the script responsible for player HP and controls):
using UnityEngine;
using System.Collections;
[System.Serializable]
public class Boundary
{
public float xmax , xmin , zmax , zmin;
}
public class PlayerController : MonoBehaviour
{
private GameController gameController;
void Start ()
{
if (PlayerHP > 0)
{
Player01Died = false;
}
GameObject gameControllerObject = GameObject.FindWithTag ("GameController");
if (gameControllerObject != null)
{
gameController = gameControllerObject.GetComponent <GameController>();
}
if (gameController == null)
{
Debug.Log ("Cannot find 'GameController' script");
}
}
private bool Player01Died;
public float PlayerHP;
public GameObject Explosion;
public GameObject Smoke;
public GameObject PlayerSmoke;
void OnTriggerEnter(Collider other)
{
if (other.tag == "Eshot") {
PlayerHP = PlayerHP - 1f;
Destroy (other.gameObject);
Debug.Log (PlayerHP);
if (PlayerHP == 1) {
Instantiate (Smoke, transform.position, transform.rotation);
}
if (PlayerHP <= 0) {
//Instantiate(Smoke,transform.position,transform.rotation);
Instantiate (Explosion, transform.position, transform.rotation);
Destroy (other.gameObject);
Destroy (gameObject,0.1f);
Player01Died = true;
}
}
if (other.tag == "Enemy") {
PlayerHP = PlayerHP - 5f;
Destroy (other.gameObject);
if (other.tag == "Enemy") {
Instantiate (Explosion, other.transform.position, other.transform.rotation);
}
Debug.Log (PlayerHP);
if (PlayerHP <= 0) {
//Instantiate(Smoke,transform.position,transform.rotation);
Instantiate (Explosion, transform.position, transform.rotation);
Destroy (other.gameObject);
Destroy (gameObject,0.1f);
Player01Died = true;
}
}
if (Player01Died == true)
{
gameController.MissionFailed ();
}
}
public float speed;
public Boundary boundary;
public float tilt;
//_____________________ WEAPONS_____________________________
//machinegun declarations
public GameObject shot;
public Transform ShotSpawn;
public Transform ShotSpawn2;
public float FireRate;
private float FireInterval;
//Air2Air declarations
public float SidewinderRate;
private float SidewinderInterval;
private AudioSource audioSource;
public AudioClip RocketSound;
public GameObject rocket;
public Transform RocketSpawn;
public Transform RocketSpawn2;
//void awake ()
//{
// audioSource = GetComponent<AudioSource>();
// audioSource.clip = RocketSound;
// }
void Update ()
{
if (PlayerHP == 1) {
Instantiate (PlayerSmoke, transform.position, transform.rotation);
}
//machinegun shots
if (Input.GetButton ("Fire1") && Time.time > FireInterval)
{
FireInterval = Time.time + FireRate;
Instantiate (shot, ShotSpawn.position, ShotSpawn.rotation);
Instantiate (shot, ShotSpawn2.position, ShotSpawn2.rotation);
audio.Play ();
}
// Air2Air shots
if (Input.GetButton ("Fire1") && Time.time > SidewinderInterval)
{
//audioSource.Play ();
SidewinderInterval = Time.time + SidewinderRate;
Instantiate (rocket, RocketSpawn.position, RocketSpawn.rotation);
Instantiate (rocket, RocketSpawn2.position, RocketSpawn2.rotation);
Physics.IgnoreCollision(shot.collider, collider);
}
}
void FixedUpdate ()
{
float MoveHorizontal = Input.GetAxis ("Horizontal");
float MoveVertical = Input.GetAxis ("Vertical");
Vector3 movement = new Vector3(MoveHorizontal, 0.0f,MoveVertical);
rigidbody.velocity = movement * speed;
rigidbody.position = new Vector3 (Mathf.Clamp (rigidbody.position.x, boundary.xmin, boundary.xmax),
20f,
Mathf.Clamp (rigidbody.position.z, boundary.zmin, boundary.zmax)
);
rigidbody.rotation = Quaternion.Euler (0.0f, 0.0f, rigidbody.velocity.x * -tilt);
}
$$anonymous$$y first suggestions, without much knowledge of the project, are to 1. Add a rigidbody (turn gravity off if you need to) to all of your gameObjects that use physics. 2. Turn on "Continuous Dynamic" on the rigidbody for each object that uses physics.
@ LT23Live I don't really have scripts for layers. I just throw stuff manually on a new layer if i need to get it out of the way and make sure it doesn't collide with something (ie game object with particle emitter for explosions). @ Addyarb gravity is turned off just to make it work and rigid body is added to all objects just to make them move. I will try the continuous dynamic later today. Thanks!:)
What speed are the bullets travelling at? Calculations for these use Time.deltaTime so the speed matches the available frame rate. If the frame rate drops and the bullets are going fast enough then chances are they miss the collider altogether. As in they're in front of the collider 1 frame, next frame they move to behind the collider.
Would also explain an intermittent fault as frames rates aren't constant.
EDIT
you could have a text box and output the result of 1 / Time.deltaTime as that'll give you the frame rate. If it only happens when frame rates are low then, in a very litteral sense, we have our smoking gun :)
@ $$anonymous$$mmpies: But Wouldn't that mean that whenever the frame-rate stabilizes everything should go back to normal? $$anonymous$$y issue is that it looks as if something disables a whole bunch of code and it suddenly stops working at all. I mean- the enemies still spawn, you still can move and shoot,the background scrolls, but that's about it. I guess I could post all of the code I did...