Progressbar not working properly on click.
So I have a basic progress bar that runs in my woodcutting script. When I click on the tree that its attached to it set to setactive(true), and once its destroyed it goes back to setactive(false). However when I run the SetActive(false) in start it allows me to click on one tree, but not the other. When I take out SetActive(false) in start, the progress bar shows at start up, when I click on tree it works, then it hides the bar, and then when I click on the second tree it does the same thing(which is how its supposed to be). What am I doing wrong here? I basically want the progressbar to not show till I click on the tree, and hide when its done.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Woodcutting : MonoBehaviour
{
Inventory inventory;
public float timeRemaining = 10f;
private bool counterActive = false;
public Transform LoadingBar;
[SerializeField]
private float currentAmount;
[SerializeField]
private float speed;
GameObject progressBar;
GameObject loadingBar;
// Use this for initialization
void Start()
{
inventory = GameObject.Find("Inventory").GetComponent<Inventory>();
progressBar = GameObject.Find("ProgressBar");
progressBar.SetActive(false);
}
void OnMouseDown()
{
counterActive = true;
}
void Update()
{
if (timeRemaining > 0 && counterActive == true)
{
progressBar.SetActive(true);
Debug.Log("Waitting..." + timeRemaining);
currentAmount -= speed * Time.deltaTime;
LoadingBar.GetComponent<Image>().fillAmount = currentAmount / 100;
timeRemaining -= Time.deltaTime;
if (timeRemaining <= 0)
{
inventory.AddItem(0);
progressBar.SetActive(false);
Destroy(gameObject);
}
}
}
}
Answer by Fredex8 · Mar 01, 2016 at 03:19 AM
GameObject.Find only returns active objects so any tree after the first to initialise isn't going to manage to find it as it will have been set to false by then.
I would suggest having the progress bar held as a public variable in another script on one object, like a game manager and then having each tree fetch it from this object at start with GetComponent. Then it shouldn't matter if it is active or not.
EDIT (in response to your comment):
Declare it the same way you're already doing with the LoadingBar in this script.
Your game manager object would have something like this on it:
using UnityEngine;
using System.Collections;
public class GameManagerScript: MonoBehaviour {
public GameObject progressBar;
void Start()
{
progressBar.SetActive(false);
}
}
Drag the progress bar object to that variable in the inspector.
Your tree script may then want to do something like this:
private GameObject gameManager;
void Start()
{
inventory = GameObject.Find("Inventory").GetComponent<Inventory>();
gameManager = GameObject.Find("GameManager");
treeProgressBar = gameManager.GetComponent<GameManagerScript>().progressBar;
}
void OnMouseDown()
{
treeProgressBar.SetActive(true);
}
That should work and enable the trees to call the progress bar even if it has been deactivated. Obviously in the long run it is going to be better to avoid using GameObject.Find as much as possible so you might want to roll the inventory script into the game manager or use a more efficient method to get the object.
Hmm. Never done it this way so its a bit confusing. I'll give it a whirl. Thanks for the tip. I may be back asking for an example soon haha.
Wow this is great. What about treeProgressBar. How am I referencing that so that it works in the start?
treeProgressBar is referenced by the GetComponent in the start there so it is just getting the gameobject from the game$$anonymous$$anager. I called it treeProgressBar just to make it clearer, it can also be named progressBar without causing a conflict.
The initial reference for progressBar is on the game$$anonymous$$anager object and then each tree is just fetching it from there with GetComponent. Assign that to game$$anonymous$$anager in the inspector in Unity or you can just stick:
progressBar = GameObject.Find("ProgressBar");
...that on the game$$anonymous$$anager object if you want.
It works! Thanks a ton, this is a much better solution for many of the features I want to show and hide. Thanks again.
Answer by pheekle · Mar 01, 2016 at 10:02 PM
Okay I'm back @Fredex8 , this may be an easy fix and I'm being dumb. So basically I have a basic script that allows my progress bar to follow my character. Here is my issue http://i.imgur.com/qltHDuC.png .
My script for it to follow my player. Any idea?
public class ProFollow : MonoBehaviour
{
public RectTransform canvasRectT;
public RectTransform healthBar;
public Transform objectToFollow;
void Update()
{
Vector2 screenPoint = RectTransformUtility.WorldToScreenPoint(Camera.main, objectToFollow.position);
healthBar.anchoredPosition = screenPoint - canvasRectT.sizeDelta / 2f;
}
}
Unless you actually need the health bar to move independently to the character like lagging behind him as he runs and catching up as he stops... then you could just make it a child object of the player character and manually position it. No need for any follow script then as the player character's movement will control it directly.
I assume the transform centre on your player sprite is on his face which is why that script is positioning the bar there. If you did want to script it you'd need to give the vertical position of the bar an offset by doing something like objectToFollow.position.y + 1
. I'm not familiar enough with 2D graphics to be sure but I don't think you really need to use the WorldToScreenPoint bit at all or set the x position to that of the camera. You could just set it to player.position.x
and player.position.y + offsetValue
... if you actually need to script it at all.
Well it's sort of named wrong. The progress bar you helped me with for woodcutting, this is for that. So basically when I cut the tree, it shows it above my characters game object.
If the progress bar is always going to be in the same place above the character when he starts chopping I would say you are best off making it a child of the player character and positioning it where you want above his head. Then you just need to use SetActive to control when it is visible and not worry about the positioning.
Your answer
Follow this Question
Related Questions
I am trying to close the GUI if its already active and the user clicks 0 Answers
Can't use SetActive (true) on collision 0 Answers
How to change GUI label size 1 Answer
Moving GUI Label through key board? 1 Answer
Connect C# script with GuiText 1 Answer