How to get animation to play multiple times in Unity? - c#

I want to get a sprite to play an animation of a drop of liquid falling every time that it is clicked, however the animation only plays the first time I click it and I have no idea why.
Here is the code used on the sprite:
public class PipetteScript : MonoBehaviour {
public Animator pipetteAnim;
public BoxCollider2D pipetteMove;
public IndicatorScript indicator;
// Use this for initialization
void Start () {
pipetteAnim.enabled = true;
pipetteMove.enabled = true;
indicator.enabled = true;
}
void OnMouseDown () {
pipetteAnim.Play ("Pipette_dropping");
Debug.Log ("Anim playing");
}
}
The debug log even prints out "Anim playing" every time I click on the sprite.

Use animation in Update function and Let me update
public class PipetteScript : MonoBehaviour {
public Animator pipetteAnim;
public BoxCollider2D pipetteMove;
public IndicatorScript indicator;
public bool boolval = false;
// Use this for initialization
void Start () {
pipetteAnim.enabled = true;
pipetteMove.enabled = true;
indicator.enabled = true;
}
void update()
{
if(boolval == true)
pipetteAnim.Play ("Pipette_dropping");
if(boolval == false)
pipetteAnim.Stop ("Pipette_dropping");
}
void OnMouseDown () {
boolval = True;
}
void OnMouseUp () {
boolval = False;
}

Related

i have a camera shake script but when i click start it directy goes off and it wont stop

i have a camera shake script but when i click start it directy goes off and it wont stop
in this script i wanted to trigger the shake effect
public class GameOver : MonoBehaviour
{
public Explosion shake;
void OnCollisionEnter2D (Collision2D coll)
{
Debug.Log("Collision!");
if (coll.gameObject.tag == "platform")
{
Destroy(gameObject);
shake.GameOver = true;
}
}
}
and this is the other script
public class Explosion : MonoBehaviour
{
public Transform cameraTransform;
private Vector3 orignalCameraPos;
public float shakeDuration;
public float shakeAmount;
private bool canShake = false;
public bool GameOver = false;
private float _shakeTimer;
void Start()
{
orignalCameraPos = cameraTransform.localPosition;
GameOver = false;
_shakeTimer = 0;
}
void Update()
{
if (GameOver = true)
{
ShakeCamera();
}
}
public void ShakeCamera()
{
_shakeTimer = shakeDuration;
StartCameraShakeEffect();
}
public void StartCameraShakeEffect()
{
if (_shakeTimer > 0)
{
cameraTransform.localPosition = orignalCameraPos + Random.insideUnitSphere * shakeAmount;
_shakeTimer -= Time.deltaTime;
}
else
{
_shakeTimer = 0f;
cameraTransform.position = orignalCameraPos;
GameOver = false;
}
}
}
if you are able to help me i would be very thankfull :)
in the statement if (GameOver = true) you are setting GameOver to true and then checking its value. I think you might have wanted to use if (GameOver == true) or if (GameOver) which will check if this variable is set to true.

Everything breaks after using PlayOneShot

In a game I am working on, the player uses a cube to open doors. When the player interacts with the cube while near the door, the door slides open. I am now trying to make it so that while it slides open, it makes a sound as doors should but I kinda ran into some issues. When I tried to add in the sound for the door, it ignored the part where the door should open altogether.
Here is what I did:
I added an AudioSource to the Cube's child object, CORE because the Cube object already contains an AudioSource which will play at the same time as this sound and assigned it in my Cube's script...
public AudioSource Woosh;
void Start()
{
//Debug.Log("Script initialized!");
Hm = gameObject.GetComponent<AudioSource>();
anim = GameObject.Find("TheFirstDoor").GetComponent<Animator>();
//Door = GameObject.Find("TheFirstDoor").GetComponent<AudioSource>();
Woosh = GameObject.Find("CORE").GetComponent<AudioSource>();
}
Here's the interactive part of the script, it runs a check but for some reason, it is pretending CanBeKey is false...
public void OnActivate()
{
if(HasPlayed == false) //Have I played? Has the Time out passed?
{
HasPlayedFirstTime = true;
Hm.Play();
HasPlayed = true;
PlayTimeOut = 30.0f;
if(CanBeKey == true)
{
anim.Play("Door_Open");
//Door.Play();
StartCoroutine(PlayDaWoosh());
Debug.Log("OPENING!");
}
}
}
Now here is the IEnumerator part of the script, PlayDaWoosh()
IEnumerator PlayDaWoosh()
{
Woosh.PlayOneShot(Woosh.clip);
yield return new WaitForSeconds(Woosh.clip.length);
}
I am aware that the last code snippet is a bit messy but it was the best thing I can think of.
Here is the full script in case you are that curious.....
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CUBE_CORE : MonoBehaviour
{
public AudioSource Hm; // HM!!!
private bool HasPlayed = false;
public float PlayTimeOut = 0.0f;
public static bool CanBeKey = false;
public Animator anim;
public static bool HasPlayedFirstTime = false;
public static AudioSource Door;
public AudioSource Woosh;
// Start is called before the first frame update
void Start()
{
//Debug.Log("Script initialized!");
Hm = gameObject.GetComponent<AudioSource>();
anim = GameObject.Find("TheFirstDoor").GetComponent<Animator>();
//Door = GameObject.Find("TheFirstDoor").GetComponent<AudioSource>();
Woosh = GameObject.Find("CORE").GetComponent<AudioSource>();
}
// Update is called once per frame
void Update()
{
if(HasPlayed == true)
{
if (PlayTimeOut < 0.0f)
{
HasPlayed = false;
}
PlayTimeOut -= Time.smoothDeltaTime;
}
}
public void OnActivate()
{
if(HasPlayed == false) //Have I played? Has the Time out passed?
{
HasPlayedFirstTime = true;
Hm.Play();
HasPlayed = true;
PlayTimeOut = 30.0f;
if(CanBeKey == true)
{
anim.Play("Door_Open");
//Door.Play();
StartCoroutine(PlayDaWoosh());
Debug.Log("OPENING!");
}
}
}
private void OnTriggerEnter(Collider other)
{
if(other.gameObject.name == "SecondDoor")
{
anim = GameObject.Find("DoorSecond").GetComponent<Animator>();
}
if(other.gameObject.name == "ThirdDoor")
{
anim = GameObject.Find("TheThirdDoor").GetComponent<Animator>();
}
if(other.gameObject.name == "FourthDoor")
{
anim = GameObject.Find("TheFourthDoor").GetComponent<Animator>();
}
}
IEnumerator PlayDaWoosh()
{
Woosh.PlayOneShot(Woosh.clip);
yield return new WaitForSeconds(Woosh.clip.length);
}
}
Expected result: Door opening and sound playing
Actual result: Neither happening unless I remove anything that has to do with the Woosh
I apologize ahead of time if I wasn't specific enough or if the question was answered somewhere else. I am relatively new here.

Music is not getting stop when scene reload in unity

I am using a toggle button to play and stop music and I am using playerPrefs to save the state. Toggle button is playing or stopping the music but when I reload the scene It gets messed up. Music keeps playing even if the toggle button is on(Means set the music off).
For the player Prefs. I am using Player prefs Manager script:
public static void SetMusicOnOFF(int value)
{
PlayerPrefs.SetInt(Music, value);
}
public static int GetMusicOnOff()
{
return PlayerPrefs.GetInt(Music, 5);
}
For the toggle button I am using:
class MusicToggleButton : MonoBehaviour
{
Toggle t;
// Use this for initialization
void Start ()
{
t = GetComponent<Toggle>();
if (PlayerPrefsManager.GetMusicOnOff() == 1)
{ //ERROR CALLING THE METHOD TO CHANGE MUSIC TO ON
t.isOn = true;
}
}
When the toggle button is pressed I am calling StartStopMusicPlayer method:
class MusicPlayer : MonoBehaviour
{
public static bool stopPlayer;
// Use this for initialization
void Awake ()
{
if (PlayerPrefsManager.GetMusicOnOff() == 2)
{
audioSource.Play();
audioSource.playOnAwake = true;
audioSource.loop = true;
}
else
{
audioSource.Stop();
}
}
public void StartStopMusicPlayer()
{
stopPlayer = !stopPlayer;
if (stopPlayer)
{
PlayerPrefsManager.SetMusicOnOFF(1);
audioSource.Stop();
}
else
{
PlayerPrefsManager.SetMusicOnOFF(2);
audioSource.Play();
}
}
}
Music Player Class is not destroying on reload. But the MusicToggleButton class is destroyed on reload.
Thank you for your help.
Calling PlayerPrefs.SetInt(Music, value) is not enough. You should call PlayerPrefs.Save() after that. Or your changes will not take effect after restart.
public static void SetMusicOnOFF(int value)
{
PlayerPrefs.SetInt(Music, value);
PlayerPrefs.Save();
}
Solution was so simple. If anyone want to know. Just change the toggle button with normal button. and Inside the MusicToggleButton class.
public class MusicToggleButton : MonoBehaviour
{
public Image offOnImage;
public bool changeValue;
public Color TargetColor;
public Color originalColor;
// Use this for initialization
void Start ()
{
changeValue = !(PlayerPrefsManager.GetMusicOnOff() == 1);
if (PlayerPrefsManager.GetMusicOnOff() == 1)
{
Debug.Log("stop Music");
offOnImage.color = TargetColor;
}
else
{
Debug.Log("Playing Music");
offOnImage.color = originalColor;
}
}
public void musicButtonClick()
{
changeValue = !changeValue;
if (changeValue)
{
//Debug.Log("changing to target color");
//offOnImage.CrossFadeColor(TargetColor, 0.5f, false, false);
offOnImage.color = originalColor;
Debug.Log("Playing");
}
else
{
//Debug.Log("changing to original color");
//offOnImage.CrossFadeColor(Color.white, 0.5f, false, false);
Debug.Log("pause");
offOnImage.color = TargetColor;
}
}
}
This will do Play and pause music. Act like a toggle button.

Unity PauseMenu doesn't work in second level

I am making a pause menu for my game. In level1 my pause menu works, but in level2 if you press esc it appears but the buttons aren't interactive for some reason. I copied the canvas from level.
public class PauseMenu : MonoBehaviour {
public string levelSelect;
public string mainMenu;
public bool isPaused;
public GameObject pauseMenuCanvas;
void Start (){
}
void Update () {
if(isPaused)
{
pauseMenuCanvas.SetActive(true);
Time.timeScale = 0f;
} else {
pauseMenuCanvas.SetActive(false);
Time.timeScale = 1f;
}
if(Input.GetKeyDown(KeyCode.Escape))
{
isPaused = !isPaused;
}
}
public void Resume()
{
isPaused = false;
}
public void LevelSelect()
{
Application.LoadLevel(levelSelect);
}
public void Quit()
{
Application.LoadLevel(mainMenu);
}
}
You need to add EventSystem
The EventSystem allows you to interact with buttons

Disable instantiate and button click

There is issue that i facing with two objects and one button. One is cube second is ground when we click on button cube is collide with ground destroy and instantiate again. On Cube collision score is decrement.Also in hierarchy there is Empty game object which name is controller which has method of text score.Score is working fine but i want that when score is 0 then button click does not work and cube is not instantiate.
Cube :
Ground :
Controller :
CubeScript:
public class Cube : MonoBehaviour {
Rigidbody2D body;
void Start () {
body = GetComponent<Rigidbody2D>();
body.isKinematic = true;
}
}
Ground Script:
public class Ground : MonoBehaviour {
private Button button;
private BoxCollider2D collide;
public GameObject object1Clone;
void Start () {
collide = GetComponent<BoxCollider2D>();
collide.isTrigger = true;
button = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
button.onClick.AddListener (() => Magnetic ());
}
void OnTriggerEnter2D(Collider2D target) {
Destroy (target.gameObject);
Instantiate (object1Clone, new Vector3 (0f, 4.12f, 0f), Quaternion.identity);
}
public void Magnetic(){
GameObject.FindGameObjectWithTag ("Player").GetComponent<Rigidbody2D> ().isKinematic = false;
}
}
ScoreScript:
public class ScoreScript : MonoBehaviour {
public static int Score=1;
void OnTriggerEnter2D(Collider2D target) {
if (Score <=0) {
} else {
Score--;
Controller.instance.SetScore(Score);
}
}
}
Controller:
public class Controller : MonoBehaviour {
public static Controller instance;
public Text scoreText;
void Start () {
scoreText.text = ""+1;
if(instance==null){
instance=this;
}
}
public void SetScore(int score){
scoreText.text =""+score;
}
}
First change the listener registration to this:
button.onClick.AddListener (Magnetic);
this will make it easier to remove the listener.
I will show you two ways of doing it, an easy one and a proper one a bit harder to grasp. So if you don't quite get it, use the first and learn about the second.
Every time you decrease the score, check for it and call for the appropriate action:
public class ScoreScript : MonoBehaviour {
public static int Score=1;
void OnTriggerEnter2D(Collider2D target)
{
Score--;
Controller.instance.SetScore(Score);
if(Score <= 0){
GameObject.Find("ground").GetComponent<Ground>().ClearButtonListener();
}
}
}
And in the Ground component:
public void ClearButtonListener()
{
button.onClick.RemoveListener (Magnetic);
}
Now the second more appropriate way would be to use event and listener
public class ScoreScript : MonoBehaviour, IScoreHandler {
public static int Score=1;
public event Action OnScoreZero = () => {};
void OnTriggerEnter2D(Collider2D target)
{
Score--;
Controller.instance.SetScore(Score);
if(Score <= 0){
OnScoreZero();
}
}
}
public interface IScoreHandler{ event Action OnScoreZero; }
And your listeners listens.
public class Ground : MonoBehaviour {
private Button button;
private BoxCollider2D collide;
public GameObject object1Clone;
private IScoreHandler scoreHandler = null;
void Start () {
scoreHandler = GameObject.Find("Score").GetComponent<IScoreHandler>();
if(scoreHandler != null){
scoreHandler.OnScoreZero += ClearButtonListener;
}
collide = GetComponent<BoxCollider2D>();
collide.isTrigger = true;
button = GameObject.FindGameObjectWithTag ("Button").GetComponent<Button> ();
button.onClick.AddListener (Magnetic);
}
void OnDestroy(){
if(scoreHandler != null){
scoreHandler.OnScoreZero -= ClearButtonListener;
}
}
}
Thanks to interface and event, your class is no more relying on another class but on an interface which makes it more flexible and scalable.
You need to set the field interactable of the UnityEngine.UI.Button object to false, see http://docs.unity3d.com/ScriptReference/UI.Button.html, i.e. use
void OnTriggerEnter2D(Collider2D target) {
if (Score <=0) {
/* disable the button */
GameObject.FindGameObjectWithTag ("Button").GetComponent<Button>().interactable = false;
}
in your ScoreScript.cs.

Categories