# How can I play an animation as long as the player is on the pressure pad?

I'm making a 2D platformer with Unity. Recently, I implemented a pressure pad system. Basically, when the player triggers the pad, a door near there should be opened. The system works properly but the only problem is when the player stays on the pad, the OpenWhenOn animation (an idle animation that is for the door opening) is not playing. I want to make this keep playing as long as the player is on the pad and if it exits the trigger, the DoorClosing animation should be played. I wrote this code mainly for playing the animation but it doesn't work and I get Null Reference error all the time.

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

{
private Animator anim;
public UnityEvent OnActivate;
public UnityEvent OnDeactivate;
public GameObject door;

public float deactivationDelay = 2f;

int objectsInContact;
Coroutine waitingToDeactivate;

IEnumerator Timer()
{
yield return new WaitForSeconds(deactivationDelay);

// Tell our listeners we're switched OFF.
if (OnDeactivate != null)
OnDeactivate.Invoke();

waitingToDeactivate = null;
}

void OnTriggerEnter2D(Collider2D other)
{

if (other.CompareTag("Player"))

{
anim.Play("OpenWhenOn");

}

door.GetComponent<Animator>().Play("OpenWhenOn");

objectsInContact++;

if (objectsInContact == 1)
{

if (waitingToDeactivate != null)
{
// Cancel deactivation timer.
StopCoroutine(waitingToDeactivate);
waitingToDeactivate = null;

}
else if (OnActivate != null)
{
// Tell our listeners we're switched ON.
OnActivate.Invoke();
}

}
}

void OnTriggerExit2D(Collider2D other)
{
objectsInContact--;

if (objectsInContact == 0)
{
// Start a delay before telling anyone.
waitingToDeactivate = StartCoroutine(Timer());
}
}
}


This is my Animator Controller. HasExitTime is disabled for all the transitions. The condition for the transition between OpenWhenOn and DoorClosing is set to false.

I'd recommend you do something like this:

1. Set up your Animator control graph with 4 animation states:

• Opening

• Open (single frame with the door stationary in its open position)

• Closing

• Closed (single frame with door stationary in its closed position)

• "StartOpening"

• "StartClosing"

• from Opening to Open with "HasExitTime" so it transitions to the Open state when the Opening animation is finished, holding the door open

• from Closing to Closed with "HasExitTime" so it transitions to the Closed state when the Closing animation is finished, holding the door shut

• from Open/Opening to Closing with a condition on "StartClosing"

• from Closed/Closing to Opening with a condition on "StartOpening"

4. Wire up the UnityEvents on your PressureSwitch:

• OnActivate should call your door's Animator.SetTrigger() method, with the argument "StartOpening"

• OnDeactivate should call your door's Animator.SetTrigger() method, with the argument "StartClosing"

This lets you wire up the door open-close behaviour without hard coupling between the pressure switch and the door, and you don't even need a custom door script!

Of course, you could also write a DoorControl script to slightly simplify the Inspector setup by letting the door manage its own animator state:

[RequireComponent(typeof(Animator))]
public class DoorControl {

[SerializeField, HideInInspector]
Animator _animator;

[SerializeField]
bool _isOpen;

void OnValidate() {
_animator = GetComponent<Animator>();
SetOpen(_isOpen);
}

void Start() {
SetOpen(_isOpen);
}

public void Open() {
SetOpen(true);
}

public void Close() {
SetOpen(false);
}

public void SetOpen(bool open) {
_isOpen = open;
_animator.SetBool("Open", _isOpen);
}
}


Now you can use a single boolean instead of two triggers to control your door (the SetBool method takes two arguments, so we can't wire that one up via the Inspector). And hooking up your events is a little easier - you can just call DoorControl.Open() or DoorControl.Close() without needing to type the exact name of the animation parameter - that knowledge is delegated to the DoorControl, keeping your setup less coupled.

• Thank you very much! I set up my Animator control graph and now the animations are working!
– Ali
Dec 26 '20 at 4:19

I think you could simply

this.gameObject.GetComponent<Animator>().Play("DoorOpening");


So it will just play and loop.

If you prefer using the animator itself you can also duplicate the open door animation and have a new trigger for it, so when you trigger it will stay in that forever, or it will change based on your animator

For example, if you have the pressure pad in an OnTriggerEnter() you need to access the Animator of the door and then use my script:

public Animator anim;

void OnTriggerEnter(Collision other)
{
if(other.compareTag("Player")
anim.Play("DoorOpening");
}


This is just an example, but you can use it anywhere

• Thanks for your answer. I added my code to the question. Where should I put this line of code?
– Ali
Dec 23 '20 at 0:03
• I have edited with a new example, @Ali Dec 23 '20 at 6:51
• If you have a reference for door, it's not a "this". You should just door.GetComponent :) @Ali Dec 23 '20 at 19:41
• I added that but still not working. Before this, at least it could play the other animations but now even the pressure pad is not opening the door, it's just like a normal object in the scene. Still, I get NullReference when the player collides with the pad. The IDE shows anim.Play("OpenWhenOn"); as the source of the error. That's so weird. I don't know what the problem is from.
– Ali
Dec 24 '20 at 0:16
• If you have the access to the door you need to do door.getcomponent<Animator>() but if you have the access to the animator you have to do anim.Play(). You are telling me 2 different things, pay attention. I suggest to use a public GameObject door; then drag the door inside it in the inspector and then start the animation with door.GetComponent<Animator>().Play("OpenWhenOn"); @Ali Dec 24 '20 at 8:06

I can't see anywhere where you're setting the condition to true to move between the DoorOpening and OpenWhenOn animations. Try removing the condition on the transition between DoorOpening and OpenWhenOn, if there's no condition then OpenWhenOn should play automatically after the DoorOpening animation plays.

• Thanks for your answer. I removed that condition but still the animation doesn't play. I think this problem is mostly related to the code, because Unity doesn't know when to play the animation.
– Ali
Dec 23 '20 at 19:05