Unity Mecanim. How to reset animation before disabling a gameobject - unity3d

Unity 2019.3.7f1
..
The artist I'm working with has made some animations for some UI stuff using the mecanim system Animator component.
I fire the animation with
Animator.SetTrigger("ParamaterName")
The gameobjects with the animator components, which are being animated, can get disabled by some of my scripts.
This can happen while the animation is playing..
So if the animation starts playing, and lets say the animation has made a button get bigger, then the gameobject gets disabled. When the gameobject is re-enabled (the animation is no longer playing) it is still big..
Is there a way to tell the Animator to go back to normal?
I have tried stuff like this in onEnable and OnDisable in a script on the GameObject
Animator.keepAnimatorControllerStateOnDisable = false
Animator.Play("normalState",0,0f);
Animator.playbackTime = 0f;
Animator.Update(0f);
This mecannim thing just seems like a black box as to how it works. I'm not familiar with it as I've always just used my own library to animate stuff that I've been using for donkeys years.
EDIT:
This was the solution...
private void Start()
{
Animator.keepAnimatorControllerStateOnDisable = true;
}
private void OnDisable()
{
Animator.Play("normalState",0,0f);
}

Make sure your keepAnimatorControllerStateOnDisable isn't set to true. Instead, you should set to false to clear the current state of the Animator controller
Animator.keepAnimatorControllerStateOnDisable = false
This way whenever you disable an object with an Animator, the Animator states and all its parameters go back to default.
Update
From your comments was able to understand the default is to have the button bigger. So, it's actually the other way around (set it to true, instead of false).
As you mention, write the following code
private void Start()
{
Animator.keepAnimatorControllerStateOnDisable = true;
}
private void OnDisable()
{
Animator.Play("normalState",0,0f);
}

Related

Cant get my player to jump /get detached from a rope

I Have a player which gets childed to a game object when it walks up to a trigger now I want the player's parent to become null again after space is pressed because I'm trying to make a rope system, and it's required for the player to be able to de-attach from the rope
This is the script that's supposed to attach/detach the player from the rope
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AttachToRope : MonoBehaviour
{
public GameObject objectToParentTo;
public GameObject objectWithSwingScript;
// Start is called before the first frame update
private void OnTriggerEnter(Collider collider)
{
if (collider.gameObject.tag == "Rope")
{
transform.parent = objectToParentTo.transform;
objectWithSwingScript.GetComponent<playerscript>().enabled = true;
GetComponent<PlayerController>().enabled = false;
GetComponent<CharacterController>().enabled = false;
GetComponent<Swinging>().enabled = false;
}
}
private void OnTriggerStay(Collider collider)
{
if (Input.GetButtonDown("Jump"))
{
transform.parent = null;
objectWithSwingScript.GetComponent<playerscript>().enabled = false;
GetComponent<PlayerController>().enabled = true;
GetComponent<CharacterController>().enabled = true;
GetComponent<Swinging>().enabled = true;
Debug.Log("Deattached");
}
}
}
What happens when the player enters the trigger is that the scripts that make the player move get disabled and then it gets chilled to the last section of the rope now in ontriggerstay i want it to check if space is pressed and re-enable all the scripts that are required for the player to move (which does not work) but since nothing in there works i tried to debug.log but even that does not work so if anyone knows how to fix this please help me
From the OnTriggerStay documentation: The function is on the physics timer so it won't necessarily run every frame.
Functions on the physics timer (e.g. FixedUpdate()) don't play nicely with Input.GetButtonDown because they don't run every frame. Instead, they run on a fixed timestep, 0.02 seconds by default.
The solution is to put calls to Input.GetButtonDown into Update(). For instance, in this example you could have a boolean member variable isJumpPushed and set it to true in Update() when the jump button is pushed and the player is attached, and then check that value in OnTriggerStay.
--
A note about debugging:
I tried to debug.log but even that does not work
If your Debug.Log isn't showing a log in the console, that still tells you something important. It tells you that code path isn't getting called. That's an important clue for you to figure out what's really going on. To further narrow down the problem, you could move the Debug.Log statement outside the if statement. This would show that it's Input.GetButtonDown that isn't returning true when you think it is.

Animator not animating a runtime instantiated child (UNITY)

I have a GameObject representing a room. As childs of this room I have 3 characters. Room has an animator component that control the synchronized animation of all characters.
The problem is I have another character that is instantiate from a prefab at runtime and this doesn't animate.
I tried several things:
//NOT WORKING
IEnumerator Start()
{
room.SetBool("e8", true);
yield return new WaitForSeconds(6);
...
}
//NOT WORKING
IEnumerator Start()
{
room.Rebind();
room.SetBool("e8", true);
yield return new WaitForSeconds(6);
...
}
//WORKING
IEnumerator Start()
{
yield return new WaitForEndOfFrame();
room.Rebind();
room.SetBool("e8", true);
yield return new WaitForSeconds(6);
...
}
The last try is working but the character looks stopped for an instant and suddenly jumps to the animation. I want the character animating from the beginning like the other characters.
My animator:
Simple solving
With current animator settings, this behavior is normal. You need to change your current animator using Any State section because when you use changing state from other states, Animation needs time to change your states. And for start Animator needs time for initializing, but if you will use Any State this will work.
Try doing something like this:
Entry different states
Either you can use what official documentation offers to you:
You can then add additional transitions from the Entry node to other states, to control whether the state machine should begin in a different state.
https://docs.unity3d.com/2019.4/Documentation/Manual/StateMachineTransitions.html
For example:

Active a Unity animation if certain conditions are met?

I'm developing a 2d game in Unity and I ran into a problem. When trying to create animation transitions for one of my animations for some reason Unity instantly or very quickly deactivates my animation(like less then a second after I activated it). However when I don't have a transition conected to the animation the animation works fine. However I need to be able to transition the gameobject back to the state it was in before the animation after a certain condtion is met and so I cant leave the animation running. Does anyone know how I can solve this problem?
Ive tried switching the way I activate the animations to see if it might be related to this by trying both a bool and trigger as the condition that determines when a transition should happen but the same problem arrises
THis is a rough outline of how I activate the animation
public class InteractControl : MonoBehaviour, IPooledObject
{
public static float timeLeft = 10f;
public void OnObjectSpawn()
{
anim = GetComponent<Animator>();
}
// Change this method to just be a temporary obstacle
void Update()
{
timeLeft -= Time.deltaTime;
if (timeLeft > 0)
{
anim.enabled = true;
}
if (timeLeft < 0)
{
anim.SetTrigger("FollowAd");
}
}
}
Ad Follow with transition:
Ad Follow without transition:
Transition Settings:
The animation should activate if timeLeft is bigger than 0 and deactivate as soon as it is smaller then 0 and return the the gameobject to the state it was in before the animation started. Right now if Ad Follow_ has no transition the animation works when called upon but doesn't deactivate. if Ad Follow_ has an empty state connected to it to which it should transition should
anim.SetTrigger("FollowAd");
be called like shown above it works for less then a second or not at all and then switches straight back to the default state. It should only switch back when timeLeft < 0.
You can create a public RuntimeAnimatorController animCon for your required animation. When your conditions are met. You can do anim.runtimeanimatorcontroller = animCon;.
And When the condition is false do this anim.runtimeanimatorcontroller = null;. Its not the best way but its quick and better then most.

Player disappears on Game mode in Uniity 2D while switching scenes

I'm making a function that it switches 2 scenes.
When the player enters the trigger, automatically unity switches the scene and in the "Scene view", the player is there, as I wanted. But in the game view, the player dissappears, I don't know why.
I tried to remove a script that it's function is teleport the player to a specific point of the new scene, and it worked.
But obviously I don't want that, because unity automatically teleports the player to a random point, how can I fix that?
Here are the scripts:
TeleportScript:
public class EnterScene : MonoBehaviour
{
public string transitionName; //Also 1-1
void Start()
{
if (transitionName == PlayerController.sharedInstance.areaTransitionName)
{
PlayerController.sharedInstance.transform.position = transform.position; //Moves the player to GameObject position
}
}
// Update is called once per frame
void Update()
{
}
}
https://pastebin.com/jdSPhR3s <-----SceneLoader
https://pastebin.com/KcwHVBfQ <----PlayerController
And a screenshot of my problem:
Problem

How to prevent mouse clicks from passing through GUI controls and playing animation in Unity3D [duplicate]

This question already has answers here:
Detect mouse clicked on GUI
(3 answers)
Closed 4 years ago.
Description
Hi Guys need your help I faced problems with mouse clicks which pass through UI panel in Unity, that is, I have created pause menu and when I click Resume button, the game gets unpaused and the player plays Attack animation which is undesirable.What I want is when I click Resume button, Attack animation should not be played. The same problem if I just click on panel not necessarily a button and the more I click on UI panel the more Attack animation is played after I exit pause menu. Moreover, I have searched for solutions to this issue and was suggeted to use event system and event triggers but since my knowledge of Unity is at beginner level I could not properly implement it. Please guys help and sorry for my English if it is not clear)) Here is the code that I use:
The code:
using UnityEngine;
using UnityEngine.EventSystems;
public class PauseMenu : MonoBehaviour {
public static bool IsPaused = false;
public GameObject pauseMenuUI;
public GameObject Player;
private bool state;
private void Update() {
//When Escape button is clicked, the game has to freeze and pause menu has to pop up
if (Input.GetKeyDown(KeyCode.Escape)) {
if (IsPaused) {
Resume();
}
else {
Pause();
}
}
}
//Code for Resume button
public void Resume() {
//I was suggested to use event system but no result Attack animation still plays once I exit pause menu
if (EventSystem.current.IsPointerOverGameObject()) {
Player.GetComponent<Animator>().ResetTrigger("Attack");
}
pauseMenuUI.SetActive(false);
Time.timeScale = 1f;
IsPaused = false;
}
//this method is responsible for freezing the game and showing UI panel
private void Pause() {
pauseMenuUI.SetActive(true);
Time.timeScale = 0f;
IsPaused = true;
}
//The code for Quit button
public void QuitGame() {
Application.Quit();
}
}
Im not sure if i understood your problem, but it sounds like somewhere in your code you start an attack when the player does a left click.
Now your problem is that this code is also executed when the player clicks on a UI element, for example in this case the Resume button?
You tried to fix this problem, by resetting the attack trigger of the animator, i think it would be a better solution to prevent the attack from starting instead of trying to reset it later.
EventSystem.current.IsPointerOverGameObject() returns true if the mouse is over an UI element.
So you can use it to modify your code where you start your attack:
... add this check in your code where you want to start the attack
if(EventSystem.current.IsPointerOverGameObject() == false)
{
// add your code to start your attack
}
...
Now your attack will only start if you are not over a UI element