OnTriggerStay2D only detecting trigger collisions while moving

My game has two players who spawn in facing each other when the game launches, and each player has a child object with the collision box set up to be where the sword is in the swing sprite and with “Is Trigger” selected in the inspector. I have my code set up to play a sound when the “swing” bool is true and the child collision box detects a collision. As the question states, the collision is only detected when there is movement. Additionally, the child “Is Trigger” collision boxes are detecting each other.

Code is posted below.

Player One


using UnityEngine;
using System.Collections;

public class p1movement : MonoBehaviour {

	public float moveSpeed = 10;

	float timer = 0.33f;
	float reset = 0.33f;
	bool swing = false;

	public Sprite img1;
	public Sprite img2;

	void SetSprite()
	{
		gameObject.GetComponent<SpriteRenderer>().sprite = img1;
	}
	void SetSprite2()
	{
		gameObject.GetComponent<SpriteRenderer>().sprite = img2;
	}
	void Update()	{

		if (Input.GetKey(KeyCode.A)) {
			transform.Translate(Vector3.right * -moveSpeed * Time.deltaTime);
									}
			
		if (Input.GetKey (KeyCode.D)) {
			transform.Translate (Vector3.right * moveSpeed * Time.deltaTime);
				}
		if (Input.GetKeyDown(KeyCode.J)) {
			this.gameObject.GetComponent<SpriteRenderer>().sprite = img2;
			swing = true;
			AudioSource audio = GetComponent<AudioSource>();
			audio.Play();
				}
		if (swing == true) {
			timer -= 1 * Time.deltaTime;
				}

		if (timer <= 0) {
			this.gameObject.GetComponent<SpriteRenderer>().sprite = img1;
			swing = false;
			timer = reset;
			}
		}
	}

Player One Child


using UnityEngine;
using System.Collections;

public class child1 : MonoBehaviour {

	void OnTriggerStay2D(Collider2D other) {
		Debug.Log ("C1");
		if (swing == true) {
			AudioSource audio = GetComponent<AudioSource>();
			audio.Play();
		}
	}

	float timer = 0.33f;
	float reset = 0.33f;
	bool swing = false;

	void Update () {

		if (timer <= 0) {
			swing = false;
			timer = reset;
		}
		if (swing == true) {
			timer -= 1 * Time.deltaTime;
		}
		if (Input.GetKey (KeyCode.J)) {
			swing = true;
		}
	}
}

Player 2


using UnityEngine;
using System.Collections;

public class p2movement : MonoBehaviour {
	
	public float moveSpeed = 10;
	
	float timer = 0.33f;
	float reset = 0.33f;
	bool swing = false;

	public Sprite img1;
	public Sprite img2;

	void SetSprite()
	{
		gameObject.GetComponent<SpriteRenderer>().sprite = img1;
	}
	void SetSprite2()
	{
		gameObject.GetComponent<SpriteRenderer>().sprite = img2;
	}
	void Update()	{
		
		if (Input.GetKey(KeyCode.LeftArrow)) {
			transform.Translate(Vector3.right * -moveSpeed * Time.deltaTime);
		}
		
		if (Input.GetKey (KeyCode.RightArrow)) {
			transform.Translate (Vector3.right * moveSpeed * Time.deltaTime);
		}
		if (Input.GetKeyDown(KeyCode.Period)) {
			this.gameObject.GetComponent<SpriteRenderer>().sprite = img2;
			swing = true;
			AudioSource audio = GetComponent<AudioSource>();
			audio.Play();
		}
		if (swing == true) {
			timer -= 1 * Time.deltaTime;
		}
		
		if (timer <= 0) {
			this.gameObject.GetComponent<SpriteRenderer>().sprite = img1;
			swing = false;
			timer = reset;
			}
		}
	}

Player 2 Child


using UnityEngine;
using System.Collections;

public class child2 : MonoBehaviour {
	
	void OnTriggerStay2D(Collider2D other) {
		Debug.Log ("C2");
		if (swing == true) {
			AudioSource audio = GetComponent<AudioSource>();
			audio.Play();
		}
	}
	
	float timer = 0.33f;
	float reset = 0.33f;
	bool swing = false;
	
	void Update () {
		
		if (timer <= 0) {
			swing = false;
			timer = reset;
		}
		if (swing == true) {
			timer -= 1 * Time.deltaTime;
		}
		if (Input.GetKey (KeyCode.Period)) {
			swing = true;
		}
	}
}

Please point out any other flaw or inefficiency in my code as well, as I am trying to learn. Thank you in advance.

i had this problem, solved it just by changing the sleeping in my player rigidbody2D to never sleep

I’m not sure I understand what’s going on here exactly. I can see that your OnTriggerStay methods are going to act with whatever collider enters the trigger; I guess your character (parent) objects have their own solid colliders and this is triggering the trigger collider in the child objects. In the OnTriggerStay function check that the ‘other’ variable you’re passing through is checking which collider it is being triggered by (e.g. if(other.collider.gameObject.tag == “Enemy”)).

Also, whenever you have a moving object with a collider, you should really give it a rigidBody componenet (otherwise it messes with how it processes objects in the scene and can cause efficiency issues). Add the component to the parent object and un-check ‘use gravity’ if you want all the movement controller by Translate (I think checking ‘isKinematic’ would work best).

And your P1movement and P2movement scripts are nearly identical, so when it comes to moving the character depending on what button/key is being pressed then you could use a public bool or [SerializedField] private bool to tick in the inspector whether the script is for p1 or not (p2). Then, depending on that bool, use different key inputs (e.g. if(p1_bool == true){ use w key}else {use Up key}).

I’m not sure why your script is only working when movement is involved, but maybe using some of the fixes I’ve provided might solve the issue. Whenever you use Translate to move your objects then they are going to move INTO whatever position you want them to move into; hence if your character’s next position is inside a collider, they will go to inside the collider and then be pushed out via Physics. This will cause a horrible bouncing effect so… you may want to use rayCasts to see if the player is about to walk into a collider OR use physics movements (velocity/force) in the FixedUpate() update method via a rigidBody.

You can use

void Start()
{
this.GetComponent<Rigidbody>().sleepThreshold = 0.0f;
}

this worked for me