I've seen some posts on the legacy system using Animations, but I'm using an Animator Controller and I want to know when an animation has completed playing.
Is there a way to assign a callback to when an animation has completed playing?
I could create a co-routine and check every frame but I feel thats the wrong way to do it.
Do you know how to check when an Animation Controller Animation has finished playing?
Since you are using Mecanim this will give you what you want:
if(this.animator.GetCurrentAnimatorStateInfo(0).IsName("AnimationName"))
{
// Do something.
}
Make sure you use the correct AnimationName and you will be alright.
The API reference GetCurrentAnimatorStateInfo.
Gets the current State information on a specified AnimatorController
layer.
It takes one parameter which is The Layer's Index.
Event Solution
You can trigger an Event by calling a function. You need to write the name of the function you want to call at the selected frame in the Function area of the Edit Animation Event window.
Short tutorial on how to do it.
Related
So I have an animation that fades into the menu screen but after the animation ends none of my buttons work. I have figured out that it is because the GameObject that holds the black image that fades to clear is always in the front, blocking me from using any of the buttons. I tried to write a script, that's attached to the game object, that disables the GameObject after it completes the animation, but it isn't working.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class LevelChanger : MonoBehaviour
{
public Animation anim;
public void SetTrigger()
{
this.StartCoroutine(this.PerformAnimRoutine());
}
private IEnumerator PerformAnimRoutine()
{
var state = anim.PlayQueued("Fade_In", QueueMode.PlayNow, PlayMode.StopSameLayer);
yield return new WaitForSeconds(state.length);
this.gameObject.SetActive(false);
}
}
Is there anything wrong with the code or is there an easier way to accomplish this? I am extremely new to unity so I am very stuck.
If all you are doing is fading a sprite to clear and you seem to know about coroutines, I might start by suggesting you do the fade within a coroutine instead.
Have that decrease the alpha by some fraction each frame and when it's 0 disable the object.
That's just if that sounds more fluid, nothing wrong with the animation way.
Doing it with animations though :
I'm not confident that you can disable the object the animation is on in that animation. If it is available on the dope sheet try that. Otherwise we can use state behaviours or animation events.
Animation Events
These can be used to trigger a function at a certain point of an animation. You can create them similar to keyframes. Here is a link to Unity's guide on this topic.
All you'd need to do is create an event and place it at the end of the animation. Then you need to in a script of that object make a public function that simply disables the object. Call that with the event.
State Behaviours
State Machine Behaviours allow you to define a script to run on a given animation state. It has many functions to hook onto such as OnStateEnter and OnStateExit.
You'd want to click on the state that fades in the animator. In the inspector you should be able to click "Add Behaviour". This will create a script that you can open and edit. Here is the reference for that class.
From there is should be very simple to disable the object through OnStateExit.
(check image) Hi! I actually have two questions,
THE FIRST ONE: I have two flash animations that I want to play in front of the tank's turret whenever I shoot a bullet (I have different weapons with different fire delays, machine gun, bombs..) so how can I play that flash animation to work in with the fire delay of a gun ? (note that if I uncheck loop time, the animation stops in the last sprite + I don't know how to replay it).
SECOND QUESTION: I want simply to animate my turret when I shoot I just want it to go back a little and return, you know what I mean, only in unity, how, please?
give me just the idea of working and I'll do my research :) thank you!
I have tried to enable my animation when I shoot and uncheck the loop time, but the animation stops at the last animation sprite and I don't know how to replay it.
Using Unity's built in animator, I'm assuming you are using this, you need to have at least have 2 states, in your case Idle and Fire. You would then set the transitions of the animations to go from one another, Fire -> Idle and Idle -> Fire.
Within the Idle-> Fire you will need add a trigger due to it only happening once.
You may also need 2 SpriteRenderer Components to allow for the display of the Shot effect, just make a child GameObject with it and edit it in the Animation Window.
Triggers reset as soon as the transition has been made.
If you do not have a trigger go to the parameter tab and click the '+' button which will allow you to create a new trigger. Now that that is created, in your code whenever you want your tank / boat to fire just add. referenceToAnimator.SetTrigger ("triggerName");
Bringing up your delay you could always add an additional wait state that mirrors the idle state but only runs for the selected amount of time. Your new Animator would look like.
Idle -> Trigger -> Wait -> Fire -> Idle
I attempted to give a delay to my function in Unity using C# language. By using Invoke, I achieved to add delay when the cursor is moved to a certain area. However, now I need to cancel the Invoke when the cursor is moved from that certain area. The idea is, when I accidentally move the cursor to the area, I can cancel whatever function being invoked there.
Here's my current code.
void SceneCall(){
Application.LoadLevel (MainMenu);
}
void SceneCallIn(){
Invoke ("SceneCall", 3f);
}
if (_newGameButton.Contains (Event.current.mousePosition)) {
SceneCallIn();
}
I tried to use CancelInvoke() as else, and it even doesn't want to invoke anymore when I move my cursor to _newGameButton afterwards. How do you cancel an Invoke then activate it once again? Thank you for your answer~
EDIT: Like #Programmer says in comments, what I exactly want to do is when my mouse is position at a certain point, timer will start counting. After 3 seconds
MainMenu scene will be loaded. While the timer is counting and the pointer is moved away from that certain position, I want the timer to stop and I don't want the MainMenu scene to be loaded anymore.
If you truly want to have "rollovers" and so on, here is a full tutorial:
https://stackoverflow.com/a/36046495/294884
Really you will have to become totally expert in all that, before you can do it.
I must tell you again though:
For 15 years now, you should never use rollovers for any reason in interface.
I faced the same problem yesterday, but I solved simply calling again the invoke method.
Here is my code:
public void OnGazeEnter()
{
InvokeRepeating("OnGazeStay", 0.0f, 1.0f / 30.0f);
}
public void OnGazeExit()
{
CancelInvoke("OnGazeStay");
}
In your case, if you want to register more than one method, you will have to save some sort of List<String> myMethods, so you will be able to delete every method that you've registered.
How do I detect Input.GetMouseButtonUp outside a specific GameObject's area in Unity? Are there any Unity Assets for this, or should we do this programmatically?
It certainly has to be done by programming it, whether there is an asset or not. As it is rather easy to program, I doubt there is one.
What you need to understand is, that Input.GetMouseButtonUp(int button) is an event and entirely decoupled from any "position". The description from the API says "Returns true during the frame the user releases the given mouse button.".
So in the frame a mouse button has been released you want to check if the arrow is "touching" or laying over some GameObject (GO). According to your example you will do nothing when the GO was hit, and else do something.
One way to do that is to use the following method:
http://docs.unity3d.com/ScriptReference/Camera.ScreenPointToRay.html
Your GameObject will at least need a collider, maybe a rigidbody too in order to be detected by the ray. I'm not completely sure atm if both are needed.
Additional note: Having an UI element, this method could also be used to set some flag while hovering over it e.g. : http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseOver.html
I'm trying to play two animations one after another in unity (each animation is two separate paths for the main camera) and from my research I think I need to use the following:
// Update is called once per frame
void Update () {
animation.PlayQueued("CameraMovement", QueueMode.PlayNow);
animation.PlayQueued("SpaceSceneMovement", QueueMode.CompleteOthers);
}
However, with this code attached to my camera, my game still only plays the first path. I created the paths so that there should be half a second delay between the different paths. I have both animations in the animation component of my camera (see attached pics) and I'm stumped as to why this isn't working.
Am I missing something?
As stated by user2025312, you are calling the code each frame. Which means that each frame you're telling it to play the first animation immediately, and you queue the second one. That won't work.
Depending on what you want to do you have several options. Say you want to continuously play the two animations in a loop. What you could do is:
void Update () {
if (!animation.isPlaying)
{
animation.PlayQueued("CameraMovement", QueueMode.PlayNow);
animation.PlayQueued("SpaceSceneMovement", QueueMode.CompleteOthers);
}
}
As should be easy to follow, that checks whether or not there is an animation playing, and if not, it will queue the two, playing the first one immediately. That will work fine within Update().
If however you're looking to play the animation sequence just once (or upon a trigger) place the two lines within Start() or a method of your choice.
void Start () {
animation.PlayQueued("CameraMovement", QueueMode.PlayNow);
animation.PlayQueued("SpaceSceneMovement", QueueMode.CompleteOthers);
}
That should work just fine. If not, verify that your animations work individually.