Unity Animation playing from coroutine - c#

As the title states the animation is not playing. the line telling it to play is in a coroutine and the code is before a waitforseconds(3f).
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Play : MonoBehaviour {
public Animator AnimatorRef;
// Use this for initialization
void Start () {
if (AnimatorRef == null)
{
AnimatorRef = GetComponent<Animator>();
}
}
public void PlayGame()
{
StartCoroutine(TitlePlay());
Debug.Log("playing");
}
IEnumerator TitlePlay()
{
Debug.Log("playing1");
AnimatorRef.SetBool("Enlarge", true);
yield return new WaitForSeconds(3f);
Debug.Log("playing2");
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex + 1);
}
}
it grabs the animator reference fine and all three of the comments show.

2 Considerations.
1st -
Did you check your transitions and AnimationController?
You can open up the AnimationController to see if the bool changes during runtime, if it does you'll know there is a transition error somewhere between your animation states.
2nd -
If you comment out the "LoadScene" part, does the animation then play correctly?
I suspect that the Animation bool is for some reason not allowed to carry out it's actions before the entire method has been run through, could be wrong though.

My unity shutdown without saving but it now works. If anyone has this problem remake the animation and MAKE SURE you go from the initial animation and click add clip. Then it worked for me :)

Related

My audio only plays one time in unity c# (beginner)

I am making a gunshot code for a zombie shooter, but for some reason whenever I fire more than once in the same time period as the other shot, they don't overlap? Is there any way I can make it so that they do? Also, it only plays occasionally when I wait
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class audioplay : MonoBehaviour
{
public AudioSource source;
public AudioClip clip;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButton(0))
{
source.PlayOneShot(clip);
}
}
}
You wouldn't want a shoot function without any cooldown, especially in update. Also check your audio file to see if has blank space in it, like the one I used:
I used Audacity to trim the audio file. (it's free and open source :D )
Code stuff:
using UnityEngine;
public class MyPlayAudio : MonoBehaviour {
public AudioSource audioSource;
public AudioClip audioClip;
public float shootCooldown; //change this according to how fast you want to shoot
private float currentShootCooldown;
void Update()
{
//if you are holding mouse button down and we are ready to shoot
if(Input.GetMouseButton(0) && currentShootCooldown <= 0)
{
Pewpew();
}
//make sure you are not changing the public value
currentShootCooldown -= Time.deltaTime;
}
public void Pewpew()
{
//code whatever gun is supposed to do, like dealing damage
//resets cooldown for pewpew
currentShootCooldown = shootCooldown;
//plays the audio
audioSource.PlayOneShot(audioClip);
}
}
I think .Play might be better if we are thinking about a gun. I don't know, try both and see which one is better for your needs
audioSource.clip = audioClip; //this is not necessary if your gun is only going to do 1 sound.
audioSource.Play();
`
If you want it to overlap, you could for example add that component to two different gameobjects in the scene, that way there will be one frame where the function is called twice. Since Update would run on two objects.

Coroutine completely freezes Unity 2020.3

I'm making a first-person game and am having trouble animating my character. I have the right animations in place. I need to find a way to make the game detect when the player has just landed on the ground so that I can play the 'landing' animation. The problem is that the only way I've thought of thus far to do this is with a coroutine. But the coroutine, when initiated, completely freezes my whole application. I suspect it's because the act of being midair initiates the coroutine once per frame. Here's the script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerAnimationHandler : MonoBehaviour
{
Animator animator;
IEnumerator LandDetect()
{
while (!playermove.isGrounded)
{
animator.SetBool("Midair", true);
}
animator.SetTrigger("Land");
yield return null;
}
PlayerMove playermove;
void Start()
{
// These are the two most important components for this
// script. I'll need PlayerMove for the mini-API
// that I have in there and I'll need the animator
// for obvious reasons.
playermove = GetComponent<PlayerMove>();
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
JumpHandler();
}
void JumpHandler()
{
if (!playermove.isGrounded)
{
if (playermove.doubleJumpOccur)
{
animator.SetTrigger("DoubleJump");
StartCoroutine(LandDetect());
}
else
{
animator.SetBool("Midair", true);
StartCoroutine(LandDetect());
}
}
else if (playermove.jumpOccur)
{
animator.SetTrigger("Jump");
StartCoroutine(LandDetect());
}
}
}
I suspect that the application doesn't leave
while (!playermove.isGrounded)
{
animator.SetBool("Midair", true);
}
until you land. This loop is continuously executed in the same frame (which freezes your game) because you're not skipping frames. You need to put yield return 0 (0, not null. Null won't cause the coroutine to skip any frames) somewhere in it so it can be resumed in the next frame. Also may remove yield return null at the end of the method, I doesn't do anything at this point
That's how I think it should look:
IEnumerator LandDetect()
{
while (!playermove.isGrounded)
{
animator.SetBool("Midair", true);
yield return 0;
}
animator.SetTrigger("Land");
}
Also I don't know if using a coroutine is the best choice here. I usually use some trigger/collision detection for stuff like this.

Flashlight toggle script initiates flash on startup

On startup the flashlight toggle script mode toggles ON/OFF, I'm not sure how to patch this.
I believe it's coming from IEnumerator Start() but, I've tried changing the yield return new WaitForSeconds to 0 but that didn't change a thing.
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using System.Collections.Generic;
using Vuforia;
public class FlashlightAPI : MonoBehaviour
{
IEnumerator Start()
{
yield return new WaitForSeconds(0);
hasTorch = CameraDevice.Instance.SetFlashTorchMode(true);
yield return new WaitForSeconds(0.000f);
CameraDevice.Instance.SetFlashTorchMode(false);
}
bool torchState = true, hasTouch = false;
public bool hasTorch;
public FlashlightAPI(bool torchState, bool hasTorch)
{
this.torchState = torchState;
this.hasTorch = hasTorch;
}
}
Zero is too long
Wait makes Unity wait until the next frame after the condition has passed. In this case, it waits for the first frame after at least 0 seconds have elapsed, meaning that it waits 1 frame.
If you want it to happen instantly, you need to remove the Waits entirely.
void Start()
{
hasTorch = CameraDevice.Instance.SetFlashTorchMode(true);
CameraDevice.Instance.SetFlashTorchMode(false);
}
However as you're fiddling with an external device (the phone's camera), this may still cause the light to flash and you should refer to the documentation to resolve the issue. As CameraDevice is not a Unity class I cannot do this for you.

Creating a Unity project that plays an animation when a key is pressed but does not cancel/restart the animation if the same key is pressed again

I'm trying to create a Unity 2018 1.4f1 project that will play a specific animation when a specific key is pressed and will play a copy of the animation if the same key is pressed while the first instance is still playing.
The idea is that the user can type a word and for every letter they input an animation is played to represent that letter.
I've tried using things like Animation.PlayQueued to queue up animations but to no success.
Here's what my basic code looks like (this is only trying to play an animation on a key press):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AnimateKey : MonoBehaviour
{
public Animator animator;
// Use this for initialization
void Start()
{
animator = GetComponent<Animator>();
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown("1"))
{
animator.Play("Take1");
}
}
}
Any help would be greatly appreciated.
From this thread
You can check if an Animator already is in a certain state using GetCurrentAnimatorStateInfo and only make the call if IsName returns false:
if (!animator.GetCurrentAnimatorStateInfo(0).IsName("Take1"))
{
animator.Play("Take1");
}
Note: The parameter of GetCurrentAnimatorStateInfo is the layer index. So when you work with multiple layers you'll have to adopt that.
For multiple parallel Animations however you might want to checkout the Animation component maybe.
There you don't have to handle States but rather can simply start and stop AnimationClips. You would than do
public Animation animation;
private void Awake()
{
animation = GetComponent<Animation>();
}
private void Update()
{
if(!Input.GetKeyDown("1")) return;
if(animation.IsPlaying("Take1")) return;
animation.Play("Take1");
}

What is the difference between playing Animator State and/or playing AnimationClip ? And why i can't play animation clips?

The states and animations not my own.
I have a prefab of a character that have Animator component attached to it. The character in the Hierarchy have Animator with some states and blends and also have some animation clips.
Now when i play/run a State of the Animator is that meaning i'm playing animation? Or the animation clips is something else ?
And why i can't playing the animation clips ? I'm not getting errors or exceptions it's just not playing it.
Here is a script that attached to this character and i also added to this character a Animation component. So now the character object have both Animator and Animation components.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class SwitchAnimations : MonoBehaviour
{
private Animator animator;
private int index = 0;
private static UnityEditor.Animations.AnimatorController controller;
private UnityEditor.Animations.AnimatorState[] an;
// Use this for initialization
void Start()
{
animator = GetComponent<Animator>();
an = GetStateNames(animator);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
animator.Play(an[index].name);
if (++index == an.Length)
index = 0;
}
}
private static UnityEditor.Animations.AnimatorState[] GetStateNames(Animator animator)
{
controller = animator ? animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController : null;
return controller == null ? null : controller.layers.SelectMany(l => l.stateMachine.states).Select(s => s.state).ToArray();
}
private void RollSound()
{
}
private void CantRotate()
{
}
private void EndRoll()
{
}
private void EndPickup()
{
}
}
Inside the variable an there are 9 states:
Aiming
Death_A
Use
Grounded
Roll
PickupObject
Reload_Rifle
Shoot_Rifle
Empty
When i click on A key it's playing the states one by one each time i click on A Everything is working fine i can play the 9 states by clicking on A.
what i don't understand with the States is inside the editor when i'm in the hierarchy selecting the character and in the menu make: Window > Animator i see the 9 states on the LegsLayer:
But then if i click on state Grounded double click i see a blend tree and i'm not sure if this is also states or maybe this is animation clips ? Then how can i get access to them ?
Ok this is one part i don't understand yet about the Animator and what and how i can play with it.
The second part is related to AnimationClip/s and why i can't play them ?
The script for animations clips:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEditor.Animations;
using UnityEngine;
public class SwitchAnimations : MonoBehaviour
{
private Animation animation;
private AnimationClip[] animationClips;
// Use this for initialization
void Start()
{
animation = GetComponent<Animation>();
animationClips = AnimationUtility.GetAnimationClips(gameObject);
foreach (AnimationClip clip in animationClips)
{
animation.AddClip(clip, clip.name);
}
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.A))
{
animation.clip = animationClips[6];
animation.Play(animationClips[6].name);
}
}
private void RollSound()
{
}
private void CantRotate()
{
}
private void EndRoll()
{
}
private void EndPickup()
{
}
private void FootStep()
{
}
}
And in the variable animationClips i have 9 animations:
Rifle_Aiming_Idle
Rifle_Aiming_Walk_F_RM
Rifle_Aiming_Walk_B_RM
Rifle_Aiming_Walk_L_RM
Rifle_Aiming_Walk_R_RM
Rifle_Idle
Rifle_Walk_F_RM
Rifle_Run_F_RM
Rifle_Sprint_F_RM
When i'm running the game and clicking on A this time i see in the Inspector inside the Animation component all the animation clips and in Animation i see the animation clip to play.
I'm not getting any errors or exceptions but it's just not playing it. The character stay still idle. Even if i choose another animation clip index to play 5 or 3 or 1 nothing is playing.
I wonder why it's not playing the animations when i click A. In this case animation number 6 from the List but still not playing.
The Animation component is a legacy component, kept in Unity to ensure backward compatibility with older projects, so you should never use it for animations.
Basically, the system works this way:
First of all, you need an Animator Controller asset. This Animator is a Finite State Machine (with substates etc.), and every single state can have an Animation Clip (you assign it via script of via Inspector in the Motion field). When the FSM enters a specific state, it will play the Animation Clip assigned.
Clearly the Animator, in order to be used by a game object, has to be assigned to that object via the Animator component.
Animation Clips are assets which contain the actual animation, they're never assigned as components to game objects, but instead they must be referenced by an Animator to be played, as I said before.
Blend trees are used to blend different animations in a seamless way by using linear interpolation. They're a "special" state of the Animator, which has multiple Animation Clips that you can interpolate to display transitions from a state to another, for example when you need to change the animation among running forward, running left and running right.
The argument is very broad, you can start to get into it by reading the official documentation about Animators, Animation Clips and Blend Trees here:
https://docs.unity3d.com/Manual/AnimationSection.html

Categories

Resources