Check if animation has finished playing? - c#

How can I check if a specific animation has finished playing in Unity, then execute an action? [C#] I am not using an animator.

From: http://answers.unity3d.com/questions/52005/destroy-game-object-after-animation.html
To execute an action from the animation editor...
-Create a script with a simple public function that will destroy the object. e.g.
public class Destroyable : MonoBehaviour
{
public void DestroyMe()
{
Destroy(gameObject);
}
}
-Add that script to the animated object you want to destroy.
-In the animation editor, move the animation scrubber to the end of the animation.
-Use the 'Add Event' button in the animation toolbar
-Select 'DestroyMe' from the function drop-down in the Edit Animation Event dialog.
-Now your animation should play, run the 'DeleteMe' function, and destroy the object/do your action.
I've used this method a few times, comes in handy for certain things in animations :)

You should check Animation.IsPlaying value.
From the docs:
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour {
public Animation anim;
void Start() {
anim = GetComponent<Animation>();
}
void OnMouseEnter() {
if (!anim.IsPlaying("mouseOverEffect"))
anim.Play("mouseOverEffect");
}
}

Just as Andrea said in his post : Animation-IsPlaying is pretty much what you need since you don't use Animator. Check Animation to see other sweet stuff you can use.
using UnityEngine;
using UnityEngine.Collections;
public class ExampleClass : MonoBehaviour
{
Animation anim;
void Start()
{
anim = GetComponent<Animation>();
}
//In update or in another method you might want to check
if(!anim.isPlaying("StringWithAnimationClip") //or anim.clip.name
//Do Something
}
You can also force stop the animation with anim.Stop();
Now you commented that you don't want to use isPlaying() so if you can please elaborate I will edit my post.

Related

How to set an inactive object active in Unity?

I am making a restart button in unity to restart the game, but the problem is that the button won't appear again after I have hidden it during the game.
Here is the code of the button:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class restartButtonScript : MonoBehaviour
{
public GameObject Player;
public Button restartButton;
public GameObject restartButtonObject;
// Start is called before the first frame update
void Start()
{
gameObject.SetActive(false);
}
// Update is called once per frame
void Update()
{
if (Player.GetComponent<playerScript>().playerEliminated == true)
{
gameObject.SetActive(true);
}
else if (Player.GetComponent<playerScript>().playerEliminated == false)
{
gameObject.SetActive(false);
}
}
}
If Game Object is inactive, its update won't be called, that's why you aren't seeing your button appear.
Turn off buttons graphics instead of disabling whole gameObject.
Alternatively you can can create an empty parent to your button, attach restartButtonScript to it, and turn off just child gameObject with button. gameObject with script will be active, so its update will be running as well.
Also, you could make it active from another script, but that's not needed there.

How to have a button run while it is being pressed

Im trying to have a method continuously run while a button is pressed. At the moment the method only runs once when the UI button is pressed. I've tried implementing a coroutine but I couldn't figure out a way a condition for StopCoroutine() to run. I've also tried using the event triggers PointerUp and PointerDown that set a boolean to false and true that determine if a coroutine runs or not but that seemed to work.
Would anyone know how to implement a continuous on button hold? Any help is appreciated.
The method I want to continuously run while the button is held. This method is called in a PointerDown event trigger in the UI button.
public void spawnLaser()
{
GameObject laser = Instantiate(laserprefab, transform.position, Quaternion.identity) as GameObject;
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(laserSpeed, 0);
}
Input.GetKeyDown returns true during the frame the user starts pressing down the key identified by name, while Input.GetKey returns true while the user holds down the key identified by name.
Seems you need to give Input.GetKey a try.
To keep it calling while pressed, call it from the Update().
public void spawnLaser()
{
GameObject laser = Instantiate(laserprefab, transform.position,
Quaternion.identity) as GameObject;
laser.GetComponent<Rigidbody2D>().velocity = new Vector2(laserSpeed, 0);
}
void Update()
{
if (Input.GetKey("up"))
{
print("up arrow key is held down");
spawnLaser();
}
}
In general you can just implement the IPointerDownHandler, IPointerUpHandler, IPointerExitHandler and IPointerEnterHandler interfaces like e.g.
public class WhilePressedButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerDownHandler, IPointerUpHandler
{
public UnityEvent whilePressed;
// adjust according to your needs via the Inspector
[Min(0f)] public float delay = 0.3f;
public void OnPointerDown(PointerEventData pointerEventData)
{
StartCoroutine(ContinuousButton());
}
public void OnPointerUp(PointerEventData pointerEventData)
{
StopAllCoroutines();
}
public void OnPointerEnter(PointerEventData pointerEventData)
{
// Actually not really needed
// but not sure if maybe required for having OnPointerExit work
}
public void OnPointerExit(PointerEventData pointerEventData)
{
StopAllCoroutines();
}
private IEnumerator ContinuousButton()
{
// Whut? o.O
// No worries, this is fine in a Coroutine as long as you yield somewhere inside
while (true)
{
whilePressed.Invoke();
// Very important for not freezing the editor completely!
// This tells unity to "pause" the routine here
// render the current frame and continue
// from this point on the next frame
// If you want some delay between calls
if(delay > 0)
{
yield return new WaitForSeconds (delay);
}
else
{
// Otherwise it directly contineus in the next frame
yield return null;
}
}
}
}
And reference your spawnLaser method in whilePressed like usually in a Button onClick via the Inspector or in code.
Note: This is either on an UI element such as a UI.Button or on a 3D object with a collider but then you additionally require a PhysicsRaycaster component on your Camera.
You do NOT need an EventTrigger component for this! The interface methods OnPointerXY will simply be called by the UI itself!
However, are you really going to Instantiate a new object every frame while the button is pressed?
You should probably checkout Object Pooling or in general only activate and deactivate your object instead of Instantiate and delete it over and over again.
According to Unity Documentation:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;// Required when using Event data.
public class ExampleClass : MonoBehaviour, IPointerDownHandler// required interface when using the OnPointerDown method.
{
//Do this when the mouse is clicked over the selectable object this script is attached to.
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log(this.gameObject.name + " Was Clicked.");
}
}
Add the IPointerDownHandler interface to your class and implement the OnPointerDown(PointerEventData) method.
I recommend using a bool to track the state of the button (e.g true if pressed) and then in your Update() method, if the bool is true, make your lazer move.

How can I change this animation transition to happen automatically?

Currently, my code allows the player to go to the next scene by clicking. I want to, however, make the fade out into the next scene animation automatic after 4 seconds. How can I do this?
I've tried looking up information, but nothing seems to work.
using UnityEngine;
using UnityEngine.SceneManagement;
using System.Collections;
public class LevelChanger : MonoBehaviour
{
// Start is called before the first frame update
float timer = 4f;
public Animator animator;
private int levelToLoad;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Invoke("FadeToLevel(1)", 2f);
}
}
public void FadeToLevel (int levelIndex)
{
levelToLoad = levelIndex;
animator.SetTrigger("FadeBlack");
}
public void OnF`enter code here`adeComplete()
{
SceneManager.LoadScene(levelToLoad);
}
}
The code works as intended, but I want the animation to happen automatically.
If I understood correctly, what you are aiming is to make an animation to play automatically when the player enters the new scene.
If that's the case, then you are looking for the sceneLoaded() method from SceneManager
Also, this discussion may be useful

Unity GameOver Screen

I am just trying to activate game over screen when the Player's activate is 'false'. There is no animation, just the
There are 3 objects that need to be active and i added the script to those 3 objects but the screen does not appear.
How can i fix?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
void Start()
{
_player = GameObject.FindGameObjectWithTag("Player");
}
void Update()
{
if (_player.activeInHierarchy == false)
{
gameObject.SetActive(true);
}
else
{
gameObject.SetActive(false);
}
}
}
My suspicion is the following. Whenever a Gameobject is not enabled, its code does not run. Test this by adding a Debug.Log("test") message.
If no message appears you can be certain that this check is never evaluated. To work around this simply add a script that is bound to an active gameObject. Creat a new empty gameobject in the scene. And add something like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
if (_player.activeInHierarchy == false)
{
_endscreen.SetActive(true);
}
else
{
_endscreen.SetActive(false);
}
}
}
Assign the Variables in the Inspector by dragging the object to the empty fields. Never use GameObject.Find Methods.
If you need any further help tell me :)
What you're currently doing is to find a single GameObject and checking whether that is active or not.
It would make more sense, and be more optimized, if each player object adds himself to a list of all players when he spawns. You can then loop over that list instead to check all players.
An even better way would be if you only call that "GameOver" check after a player has died. So when you call whichever method kills him.
Based on Franz Answer, I did some modification in the code. You won't need any if else statement if you use a shortcut.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameOverManager : MonoBehaviour
{
public GameObject _player;
public GameObject _endscreen;
void Update()
{
_endscreen.SetActive(!_player.activeInHierarchy);
}
}

Bool parameter won't change through script, animation wont play OnClick

I'm doing an android 2d platformer. In the Animator everything is set up. On applicaton start does everything right but when I click on the button the bool parameter does not change so my animation won't play backwards. But when I tick the bool parameter in the animator the animation plays right as it should. No console errors. Here is my script.
I was using this tutorial and from it I just needed the first part (the "Start game" animation part). I followed every step. Probably I'm missing something.
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.UI;
using UnityEngine;
public class UIManager : MonoBehaviour
{
public Animator optionsButton;
public void OpenSettings()
{
optionsButton.SetBool("isHidden", false);
}
}
My goal is to play the animation backward when the option button is pressed and I want to change the bool parameter through a script.
The problem was that the script was trying to change the bool on a canvas child element object. And there wasn't a bool. So I altered the existing script to get it. Worked perfectly.
public class UIManager : MonoBehaviour
{
public Animator optionsButton;
public bool hide;
private void Start()
{
//to find the parent element - canvas - which has a bool
optionsButton = GameObject.Find("MainMenu").GetComponent<Animator>();
}
public void OpenSettings()
{
hide = true;
optionsButton.SetBool("AnimOut", hide);
Debug.Log("I'm finaly working!");
}
}

Categories

Resources