I am working on a 2D video game project but I have a somewhat strange error in the character's attack. I've been using Unity for a short time...
When I press the attack button, an animation is played and a boolean variable is set to true. When the attack animation ends, it has an event in place that calls a function to change the boolean variable back to false.
Main script added to player gameobject (MonoBehaviour):
void Update(){
if (Input.GetKey(script_buttons.button_attack))
{
gun_attacking = false;
player_animator.Play("gun_attack");
}
}
Event that is called when the weapon attack animation ends:
void foot_gun_attack()
{
attack_script.gun_attacking = false;
}
It works fine, but if I quickly press the attack button, there are times when the variable never goes to false, and the game goes crazy.
Is it unreliable to use events in the animations themselves? why does it fail and not change the boolean variable to false again?
I have partially fixed it by adding a State machine behavior script to the animation, and in said script, right in the OnStateExit function I change the variable to false. This works and the attack never misses no matter how fast you press the button, the problem? which forces me to have both at once, the animation event and the state machine behavior script. If I remove the event the vairable never goes false, if I remove the state machine behavior the variable does go false but fails every once in a while.
Script on state machine behavior:
override public void OnStateExit(Animator animator, AnimatorStateInfo stateInfo, int layerIndex)
{
attack_script.gun_attacking = false;
}
The only way it won't fail is to set the variable to false in both places, which I think is crazy and shouldn't be normal behavior. The animation event should suffice and work fine, but why isn't it working correctly? I wouldn't like to have to limit button presses or add Timeouts, or would that be the only way?
Maybe it's my mistake or Unity problem, does anyone know what's going on?
The reason may be that the animation never ends and goes to another state
The first way is that
When You can call the function you want when the animation starts, but in the coroutine, it waits for the animation time and then returns the bool to false.
or continue with your own method, but check and change this configuration in the transitions before and after that animation.
Especially try these 2 checkboxes
Related
I am new to C# and Unity and I'm trying to figure out how to make an animation for an object in unity play when I press a key but I can only make the animation play once, and then it is broken and doesn't work. (I am trying to make an FPS game)
The code I have right now looks like this:
void Start()
{
gameObject.GetComponent<Animator>().enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
gameObject.GetComponent<Animator>().enabled = true;
}
}
When I press run and left click, the animation triggers and does as it is supposed to but when I try to do it again, the animation doesn't work. Can anybody help me change this code so that the animation will work and play every time the button is pressed?
I am assuming your animation is non-looping as if it was looping it would already play back into itself when it is over.
One quick note I would have with your code is do not use GetComponent in an Update function as it is quite costly. An easy way to get an animation state to reset is to enable and disable it, however I am assuming you want to have more animations than shooting. You would want to look into what is called an Animation Tree or a Blend Tree and add States to your animation. Examples of states would be an Idle, Walk, Run, Shoot, Crouch, etc. I would consider researching Animation Trees and Blend Trees to get a full animation cycle in.
Once you get a State machine working, I would have the enter go to an Idle state, then either set a transition Bool or directly switch the animation in code.
// when you serialize a private field, it will appear in
// the inspector so you can drag in the reference in the editor
[SerializeField] private Animator anim = null;
private void Start()
{
anim.enabled = false;
}
private void Update
{
if(Input.GetButtonDown("Fire1")
{
Shoot();
if(!anim.enabled)
anim.enabled;
else
anim.Play("AnimationStateName", -1, 0f);
}
}
I have not tested the code, but I believe this would work with your setup. I would still strongly advise to not do this and look into Trees. After implementing the tree, instead of calling using the enabled, just use the line anim.Play("AnimationStateName", -1, 0f) or you can do anim.SetBool(isAttacking, true) if you set your state to transition from Idle/Run/Walk/etc. to Attacking when the isAttacking bool is set to true.
I found a video that might help you out. I do not want to post a full explanation to animation states and blend trees, just point you in the right direction to a better approach.
So I have a JoyStick script attached to a player prefab and I disabled it while my timer is not equal to 0 and re-enable it. It's being re-enabled but my player cannot move anymore even though the script is checked on the inspector.
so the first picture shows that the joystick is checked and enabled before i click the start game button which will initiate a timer
the second picture shows that while the timer goes, the script is disabled
and the third shows that it's being enabled again but i can't seem to make my prefab move. FYI, it's moving before i disable the script.
It's because when you disable it you are causing some issues with some variables or gameObjects that probably were accessing to that script.
For example :
public int counter
If in another script you are accessing to that counter
Player.counter = n + 1;
It is giving to you an error when you disable the script and even if you re-able it, it won't work again because of the errors. The same can occur for prefab called, public functions and so on.
Instead of disabling that script you should add a bool called isTimerZero and put it in the movement section for example
if(Input.GetKeyDown("a") && isTimerZero == false)
// move the player
else
// don't move it
In this way you will just change the bool to true when timer is 0, and it won't cause problems
(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've been trying to put one attack animation working and it is playing non-stop instead of playing when I press left-shift.
For now, that is what I have.
Set a null state or an idle in your controller and make sure it's the base state, create a parameter trigger name Attack, drag your animation into the controller and transition from base to your attack anim with the parameter as attack and a transition back.
In code on shift press write
anim.setTrigger ("Attack");
Also if u haven't referenced your animation by either draging it in to your variable or a getcomonent ref it also wont work :)
I recently thought about adding a InGame Button to my Game. It's not a GUI or UI Button, it's a Block, added to a Wall for example.
Dummy Code:
OnTriggerEnter(c:Collider) {
if(c.gameObject.tag =="Player")
{
//Text = "E to interact!"
if(key.pressed("e")
{
//Connect the Button to a specific Block, play a Animation
}
}
}
So how do I connect a specific Block to the Button, and if I press e, Play the Animation just on the specific block? Please keep in mind that I'm new in Unity.
Thanks for helping out!
I don't know if you already managed to create your animation, so I-ll explain from scratch. When in the editor, select your Door and press ctrl+6 to open the animation window. From here you can animate your block. When you will be done creating the animation, your block object will have a new script attached to it: an animator. You can see the animator state machine in the animator window
These are two different things:
Animation: Defines a single animation (translation, rotation, change of color, ...)
Animator: defines when an animation occurs for the corresponding gameobject. An animator can have variables (for example, a bool) that define which is the next animation to be played
Any object can have an animator (your button can have one to move when it is pressed. You door can have another one to open / close)
For instance, in your button animator, you should have three states: Idle, Press, UnPress.
The state Press will contain the animation "press" with speed 1. The state UnPress will contain the animation "press with speed -1
Then, still in the animator window, You will create links between Idle and the two other states and add a trigger condition called "OnPress" (for example)
You can do the same to animate your door
In your Button code, you will then write
public Animator Door; // In the editor, give a reference to your door. It must have an Animator script for this to work
OnTriggerEnter(c:Collider) {
if(c.gameObject.tag =="Player")
{
//Text = "E to interact!"
if(key.pressed("e")
{
GetComponent<Animator>().SetTrigger("OnPress"); // The button's animator goes to "pressed" state
Door.SetTrigger("Open"); // The door's animator goes to "open" state
}
}
}
Then you could add another trigger to unpress the button
One more thing: When you say "Connect the button to the block", I feel like you misunderstood something: Your button script should be already added to the block in the editor
Look at these two links for more information on animations:
http://docs.unity3d.com/Manual/animeditor-UsingAnimationEditor.html
http://docs.unity3d.com/Manual/AnimatorWindow.html