I want a animation to loop while in collision with a object that has a particular tag but due to the fact it cant constantly check if its collided with said object its just is a broken mess is there anyway to check for collision with a object that has a certain tag in the update function?
OnCollisionEnter / OnCollisionStay / OncollisionExit will likely be the most optimal way to detect collisions. What makes you think it won’t work, though?
There are multiple other ways. If you’re using a primitive collider, you could use a number of static methods in the Physics API such as OverlapSphere or OverlapCapsule:
You could probably also use rigidbody SweepTestAll, or something like that
That’s probably even less efficient, though.
Another useful tool is the raycast:
Best way to do this is just with a boolean variable to keep track of the collision state:
bool isCurrentlyColliding;
void OnCollisionEnter(Collision col) {
isCurrentlyColliding = true;
}
void OnCollisionExit(Collision col) {
isCurrentlyColliding = false;
}
void Update() {
if (isCurrentlyColliding) {
// Do something.
}
}
Howwver if you just want an animation to loop it’s probably better to utilize the animator state machine and just use animator parameters like:
void OnCollisionEnter(Collision col) {
animator.SetBool("IsColliding", true);
}
void OnCollisionExit(Collision col) {
animator.SetBool("IsColliding", false);
}
I’m having the same issue even when using the code above you see I want the player when entering a certain area to play a animation on loop it works the first time I make them go in the area but afterwards it doesn’t work right (sometimes there’s a delay between the animation starting and them entering the area and other times it just never plays at all)
bool isCurrentlyColliding;
void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "climbable")
{
isCurrentlyColliding = true;
}
}
void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.tag == "Unclimbable")
{
isCurrentlyColliding = false;
}
}
public float moveSpeed;
Animator animator;
SpriteRenderer spriteRenderer;
// Start is called before the first frame update
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (isCurrentlyColliding)
{
animator.Play("Climbing");
}
else
{
isCurrentlyColliding = false;
}
if (Input.GetKey("right"))
{
if (!isCurrentlyColliding)
{
animator.Play("Walking");
}
transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
}
else if (Input.GetKey("left"))
{
if (!isCurrentlyColliding)
{
animator.Play("Walking_Left");
}
transform.Translate(new Vector3(Input.GetAxisRaw("Horizontal") * moveSpeed * Time.deltaTime, 0f, 0f));
}
else if (Input.GetKey("down"))
{
if (!isCurrentlyColliding)
{
animator.Play("Walking_Down");
}
transform.Translate(new Vector3(0f, Input.GetAxisRaw("Vertical") * moveSpeed * Time.deltaTime, 0f));
}
else if (Input.GetKey("up"))
{
if (!isCurrentlyColliding)
{
animator.Play("Walking_Up");
}
transform.Translate(new Vector3(0f, Input.GetAxisRaw("Vertical") * moveSpeed * Time.deltaTime, 0f));
}
else if (!isCurrentlyColliding)
{
animator.Play("Idle");
}
}
You seem to be looking for different tags for some reason in your collision enter vs your collision exit. Why is that? Also this code here, because it is running inside Update, is going to restart the animation every frame, which will most likely look like it’s not playing at all:
if (isCurrentlyColliding)
{
animator.Play("Climbing");
}
Ultimately your strategy of trying to use Animator.Play directly instead of working with the animator state machine is biting you in the ass. You get a free state machine in your animator, you should utilize it. Your only job is to give it cues about when to transition between states. 90% of this work should be done in the animator editor window, setting up the states and transitions properly.
Here is an example script, Make sure to have the IsTrigger checkbox checked on your Box Collider.
using UnityEngine;
public class Tree : MonoBehaviour
{
private Rigidbody TreeRigidbody;
private BoxCollider TreeBoxCollider;
// Start is called before the first frame update
void Start()
{
TreeRigidbody = GetComponent<Rigidbody>();
TreeBoxCollider = GetComponent<BoxCollider>();
}
// Gets called when the object enters the collider area
void OnTriggerEnter(Collider objectName)
{
Debug.Log("Entered collision with " + objectName.gameObject.name);
TreeRigidbody.isKinematic = false;
TreeBoxCollider.isTrigger = false;
}
// Gets called during the stay of object inside the collider area
void OnTriggerStay(Collider objectName)
{
Debug.Log("Colliding with " + objectName.gameObject.name);
}
// Gets called when the object exits the collider area
void OnTriggerExit(Collider objectName)
{
Debug.Log("Exited collision with " + objectName.gameObject.name);
}
}