How to make a simple progress bar - c#

var barDisplay : float = 0;
var pos : Vector2 = new Vector2(20,40);
var size : Vector2 = new Vector2(60,20);
var progressBarEmpty : Texture2D;
var progressBarFull : Texture2D;
function OnGUI()
{
// draw the background:
GUI.BeginGroup (new Rect (pos.x, pos.y, size.x, size.y));
GUI.Box (Rect (0,0, size.x, size.y),progressBarEmpty);
// draw the filled-in part:
GUI.BeginGroup (new Rect (0, 0, size.x * barDisplay, size.y));
GUI.Box (Rect (0,0, size.x, size.y),progressBarFull);
GUI.EndGroup ();
GUI.EndGroup ();
}
function Update()
{
// for this example, the bar display is linked to the current time,
// however you would set this value based on your desired display
// eg, the loading progress, the player's health, or whatever.
barDisplay = Time.time * 0.05;
}
How do I make a geometry dash type progress bar in unity using OnGUI? I tried looking it up online, couldn't find it really. I am building a runner game something like Temple run and I want to show the player how much of the map is left to go.

For a progress bar
You can use the Unity scrollbar object to make what you're looking for. There's a good tutorial on it here. Essentially, you add a scrollbar object to your canvas, and then change the slider value from code.
For scrolling textures
If you want a scrolling texture on your progress bar, then you can animate an image placed on the slider. If you don't want to animate it by hand, then it's a little more complicated. Ideally you could set the texture offset of the image in code to get it to scroll, but after looking it up I don't think that Unity allows you to do that on non-3D objects.
If you still want it to scroll and don't want to make a hand-drawn animation for it, you might want to look into combining the UI mask component (tutorial here), and the built-in 2D animation tools (tutorial here).

Related

How can I get screen position of a UI element?

I'm trying to get the global position of a UI element.
I've tried so many different ways to get the position but none of them seems to work. The problem comes with the anchors, as i'm moving them and not the UI element position itself (for resolution purposes), the position of the UI showing in the inspector is always 0,0,0. I also tried to get the anchoredPosition and also the Corners to make some calculations but it still not working, I always get (0,0,0) or some incoherent numbers.
Vector3 pointToTravel = Camera.main.WorldToScreenPoint(objectRectTransform.anchoredPosition);
This 'pointToTravel' variable should hold the screen position in pixels of the ui element.
anchoredPosition is the
position of the pivot of this RectTransform relative to the anchor reference point.
Since RectTransform inherits from Transform you can simply use
Vector3 pointToTravel = Camera.main.WorldToScreenPoint(objectRectTransform.position);
in order to get the absolute world position.
The position you see in the in the Inspector is always the
localPosition for Transform - relative to the parent GameObject.
or
anchoredPosition for RectTransform depending on the anchor settings - relative to the anchor reference point.
However in the case your Canvas is a Screen Space - Overlay all the contained UI (or better RectTransforms) already uses the screenspace coordinates in pixels so the WorldToScreenPoint is unnecessary or better said returns incorrect values.
So in that case you could instead simply use
Vector3 pointToTravel = objectRectTransform.position;
In order to get any information you could need about the dimensions and position of a UI Element from its RectTransform, I wrote this little utility function to convert a RectTransform to a Screen Space - Rect(For Canvas mode Screen Space - Camera).
public static Rect RectTransformToScreenSpace(RectTransform transform, Camera cam, bool cutDecimals = false)
{
var worldCorners = new Vector3[4];
var screenCorners = new Vector3[4];
transform.GetWorldCorners(worldCorners);
for (int i = 0; i < 4; i++)
{
screenCorners[i] = cam.WorldToScreenPoint(worldCorners[i]);
if (cutDecimals)
{
screenCorners[i].x = (int)screenCorners[i].x;
screenCorners[i].y = (int)screenCorners[i].y;
}
}
return new Rect(screenCorners[0].x,
screenCorners[0].y,
screenCorners[2].x - screenCorners[0].x,
screenCorners[2].y - screenCorners[0].y);
}
From this rect you can easily get all the information that the RectTransform does not give you that easily, such as Screen-Space-position and non-anchored size.

Vector 3 Position on different Screen Size

so this is what happens when Im using vector 3 on my game I want my vector 3 to be on specific position for different screen sizes? is that possible? here is my codes
public virtual void ShuffleButton()
{
Vector3 buttonFirst = gameButtons[0].transform.position;
buttonFirst.x += 297f;
gameButtons[0].transform.position = buttonFirst;
Vector3 buttonSecond = gameButtons[1].transform.position;
buttonSecond.x -= 74.25f;
gameButtons[1].transform.position = buttonSecond;
Vector3 buttonThird = gameButtons[2].transform.position;
buttonThird.x += 74.25f;
gameButtons[2].transform.position = buttonThird;
Vector3 buttonFourth = gameButtons[3].transform.position;
buttonFourth.x -= 148.5f;
gameButtons[3].transform.position = buttonFourth;
Vector3 buttonFifth = gameButtons[4].transform.position;
buttonFifth.x -= 148.5f;
gameButtons[4].transform.position = buttonFifth;
}
You are looking for the position conversion functions like Camera.ScreenToWorldPoint(). These can be found in the Unity Camera class documentation here: https://docs.unity3d.com/ScriptReference/Camera.html
If, for example, you want to place a Sprite in the top-left corner, regardless of screen size, you would use the screen or viewport space. The position of the sprite will have to be translated from this screen/viewport space to world space. You could use Camera.ScreenToWorldPoint() for this.
However, Unity uses three viewspaces: Screen, World and Viewport. You should read up on all three as your problem stems from the fact that you are trying to use world coordinates (transform.position) to set the position of UI elements (which use either the screen or world space; this is dependent on the parent Canvas settings)

Health Bar XNA C#

Here is my code
healthBarPosition = new Vector2(0, 550);
public Texture2D healthGaugeTexture;
public Texture2D healthBarTexture;
public Texture2D healthGaugeTexture;
public int maxHealth;
public int currentHealth = 500;
In load Method;
healthGaugeTexture = Content.Load<Texture2D>("HealthBar Gauge");
healthBarTexture = Content.Load<Texture2D>("Health Bar");
In Draw Method;
spriteBatch.Draw(healthGaugeTexture, healthBarPosition, Color.White);
spriteBatch.Draw(healthBarTexture, healthBarPosition, Color.White)
This Draws Full Health bar within Health Gauge.
I've tried to
spriteBatch.Draw(healthBarTexture, healthBarPosition,
new Rectangle((int)healthBarPosition.X, (int)healthBarPosition.Y,
currentHealth, healthBarTexture.Width),
Color.White);
Or
spriteBatch.Draw(healthBarTexture, healthBarPosition,
new Rectangle((int)healthBarPosition.X, (int)healthBarPosition.Y,0,0),
Color.White);`
When is like this it's just Health Gauge without health bar...bar is somewhere behind gods legs.... xD I do not know where is Source Rectange or where did i set it.
I also tried
https://www.youtube.com/watch?v=C9ldaOGjePE
Same as this video and
Maxhealth = healthBarTexture.width;
Gives me error, so I removed the comment and it works.
What I want is to draw full health with set health value i.e.: Current health = 100; but health bar to be full I can draw with just with Rectangle and problem is that i do now know how to use source rectangle and where to place it
You just need to draw using a clipping rectangle.
There are many overloads of SpriteBatch.Draw that allow you to set the source and destination rectangle. Heres one: (MSDN)
By shrinking the source and destination rectangle, you will give the illusion of a "variable length" health bar. You will likely want to fix the "Left" property, and shrink or grow the "Width" property of each rectangle to get your effect.
When setting up the source rectangle, be careful to set it up so that you are not "off" the texture. To try and explain what I mean when I say a source rectangle can be "off" of the texture, consider the following image:
The Green rectangle is "Off" of the texture, and is similar to what can happen with the code you posted. The cyan rectangle is what you want to happen.

Wobbling texture using source rectangle

I'm having a little trouble with a texture2d I'm trying to draw in XNA. Basically, I have a power-up "cooldown fill-effect" going on. I have a texture that I'm trying to draw partially as the cooldown decreases. So, for example, at 10% cooldown done I'm drawing only 10% cooldown of of the texture (the bottom), 20% done only 20% of the bottom of the texture, and so on.
The problem I'm having is, when drawing the texture, it keeps wobbling as it fills up.
Note that below, ActiveSkillTexture is my preloaded fill texture. It's size is the size of the fully filled graphic.
InterfaceDrawer.Draw is a method that calls SpriteBatch.Draw, but does some extra stuff beforehand. For all intents and purposes, it's the same as SpriteBatch.Draw.
Scale is my scale factor, it's just a float between 0 and 1.
MyDest is a pre-calculated position for where this texture should draw (from the top-left, as usual).
Here's a snippet of code:
Rectangle NewBounds = ActiveSkillTexture.Bounds;
float cooldown = GetCooldown(ActiveSkillId);
if (cooldown > 0) //cooldown timer
{
//Code that calculated cooldown percent which I'm leaving out
if (percentdone != 1) //the percentage the cooldown is done
{
//code for fill-from bottom --
float SubHeight = ActiveSkillTexture.Height * percentremaining;
float NewHeight = ActiveSkillTexture.Height * percentdone;
NewBounds.Y += (int) SubHeight;
NewBounds.Height = (int) NewHeight;
MyDest.Y += SubHeight * Scale;
}
}
if (ActiveSkillTexture != null)
InterfaceDrawer.Draw(SpriteBatch, ActiveSkillTexture, MyDest, NewBounds, Color, 0.0f, Vector2.Zero, Scale, SpriteEffects.None, 0.0f);
I know you can't see it, but it's basically wobbling up and done as it fills. I tried printing out the values for the destination, the newbounds rectangle, etc. and they all seemed to consistently increase and not "sway", so I'm not sure what's going on. Interestingly enough, if I fill it from the top, it doesn't happen. But that's probably because I don't have to do math to alter the destination position each time I draw it (because it should draw from the top-left corner each time).
Any help would be greatly appreciated. Thanks!
I think this would be easier if you set the Vector2.Origin parameter of your spriteBatch.Draw as the bottom-left of your texture.
In this way you simply increase your sourceRectangle.Height, with something like this:
sourceRectangle.Height = ActiveSkillTexture.Height * percentdone;
without doing that useless math to find the destination position.

XNA: Adding a Nuclex Screen to GuiManager.screen breaks 3d rendering

I am trying to set up an extremely simple XNA game with a 3d terrain and some 2d GUI objects on top. I chose Nuclex since that seems to be one of the few 2d GUIs that's currently active.
My problem: adding a Nuclex "screen" class to my game results in the 3d terrain and lines drawn on top of it to screw up -- I have three layers of 3d objects: terrain, a wireframe outline of the terrain and some "routes" that hug the terrain. With the screen added, the routes that are partially-submerged into the terrain appear entirely on top of the terrain, and the wireframe grid appears thicker.
This is the tail-end of my Game.Initialize method, as made by following the sample on the Nuclex GuiManager page:
InputManager im = new InputManager();
IGraphicsDeviceService igds = Nuclex.Graphics.GraphicsDeviceServiceHelper.MakeDummyGraphicsDeviceService(GraphicsDevice);
gui = new GuiManager(igds, im);
gui.Initialize();
Viewport vp = GraphicsDevice.Viewport;
Screen main_screen = new Screen(vp.Width, vp.Height);
//main_screen.
this.gui.Screen = main_screen;
main_screen.Desktop.Bounds = new UniRectangle(
new UniScalar(0.1f, 0.0f), new UniScalar(0.1f, 0.0f), // x and y
new UniScalar(0.8f, 0.0f), new UniScalar(0.8f, 0.0f) // width and height
);
LabelControl text = new LabelControl("hello");
text.Bounds = new UniRectangle(10, 10, 200, 30);
main_screen.Desktop.Children.Add(text);
Components.Add(gui);
base.Initialize();
So, any ideas as to what I'm doing wrong?
Thanks!
Right, so thanks to catflier who pointed me in the direction of render states, I fixed the problem:
* First, "RenderState" is an XNA3 term; XNA4 simply allows a few state flags directly on the GraphicsDevice object.
* The problem is that Nuclex is secretly setting the GraphicsDevice.DepthStencilState and leaving it instead of restoring it to its previous value after use (naughty!!).
* So the solution is, at the top of your Draw method, to add a line like so:
GraphicsDevice.DepthStencilState = DepthStencilState.Default;

Categories

Resources