Unity paint circular healthbar dynamically - c#

I got a circular healthbar. It updates, when the current or max life changes.
healthBar.fillAmount = currentHealth / maxHealth;
So this bar looks boring. There are no borders between the "pieces". When I got eight lifepoints I want to see eight parts there.
Super Mario 64 should be an excellent example
Important would be having small borders showing the lifepoints. Is this even possible?
I don't have 8 lifepoints. The lifepoints are not constant. They are set by the value X. Otherwise I could use a Texture, yes. Furthermore I want to increase the max life in the game, so everything has to work dynamically.

The simplest solution would be to create a thin line in a graphics editor, import it into Unity as a sprite, then add the sprite as an Image object in your scene.
If you have eight health pieces, you need 4 border lines spaced 45 degrees apart. The code below will clone the image as many times as you need (set via the field pieces, instead of X as you said) and rotate each clone round the z-axis.
public GameObject line; //Set your line image via the inspector here
private int pieces = 8;
public void DrawLines()
{
int linecount = pieces/2;
float angle = 360 / linecount;
for(int i = 0; i < linecount; i++)
{
GameObject clone = Instantiate(line, Vector3.zero,
Quaternion.Euler(0,0,(angle*i)));
}
}

Related

2d runner same spacing between different sized gameobjects

my problem is keeping same spacing between different sized prefabs in randomly generated 2d runner.
i want to spawn new gameobject every second
let's say i have simple sprite called square
i am spawning it using coroutine and distance is always equal to 1s of movement
i added different sized arrays of squares as prefab and when i spawn it with 1 unit squares i would love to have same distance between prefabs as if i was spawning single squares one after another.
basically i would love to spawn different sized prefabs and spawn them at same interval by keeping same distance between different prefabs.
maybe the solution is to spawn prefabs based on measured distance between prefabs instead of spawning based on time
how would you aproach this problem?
can i calculate width of empty gameObject based on width of array of its children?
i hope you can understand what am i asking
thank you!
void Start() {
stvaranjeFunkc();
}
// Update is called once per frame
void Update() {
if (privremeniNiz.tag == "zamka")
{
if (privremeniNiz.transform.position.x + privremeniNiz.transform.localScale.x / 2 < stvarac.transform.position.x - vrijednostGranice)
stvaranjeFunkc();
}
if (privremeniNiz.tag == "nizPreprekaZamka")
{
// if ((privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.localScale.x / 2)
//> stvarac.transform.position.x - vrijednostGranice)
if ((privremeniNiz.gameObject.GetComponent<nizKutija>().niz[0].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[0].transform.localScale.x / 2)
> stvarac.transform.position.x - vrijednostGranice)
return;
// if (privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.position.x + privremeniNiz.GetComponent<nizKutija>().niz[privremeniNiz.GetComponent<nizKutija>().randomBrKutija].transform.localScale.x / 2 < stvarac.transform.position.x - vrijednostGranice)
stvaranjeFunkc();
}
//if (!cekanje)
// StartCoroutine(stvaranje());
//else return;
}
void stvaranjeFunkc()
{
int poz = Random.Range(0, prepreka.Length);
GameObject temp =Instantiate(prepreka[poz], stvarac.transform.position, stvarac.transform.rotation);
privremeniNiz = temp;
}
i got it working when i have simple gameobject (tag=zamka) but when i
spawn gameobject of tag nizPreprekaZamka which is empty gameobject that has script attached which creates array of simple objects spawner just spawns hundreds of gameobjects at once
You probably know the speed that your game horizontally scrolls. I'm assuming you're tracking the position of each block and you can tell what their widths are.
The trick is to spawn the blocks off-screen so you always have enough content to scroll into view to cover the next frame.
How much content is off-screen? I'm assuming you just append new blocks to the end of the array. That means the last block is always the furthest off-screen, which helps us. It also helps to know the size of the screen. In that case, you can calculate the amount of content off-screen as last block position + its length + fixed_space - screen size, where fixed_space is the amount of space you want after each block.
Check each frame if the scroll speed > the amount of content off-screen. If so, you need to generate a new block. Your block's starting position should be exactly where the content off-screen ended.
The position of a GameObject is located at its center, while is scale is his total size.
So the edge of an object is located at its position plus half the scale:
float distance = transform.position.x + (transform.scale.x / 2f);
So for each new prefab, you want to add the distance between the center and edge of both GameObject plus the distance that should seperate them.
public GameObject[] prefabs;
public float distanceBetweenObjects;
float newPosition = prefabs[0].transform.position.x;
newPosition += (prefabs[0].transform.scale.x / 2f);
newPosition += distanceBetweenObjects;
newPosition += (prefabs[1].transform.scale.x / 2f);

Moving and scaling an object according to hand position

I need some help with my college project. I have a cylinder and need it to act as a coil. For example, if I touched the cylinder's surface it's height will decrease (scaled in the y direction) as if pressing on a coil then when I remove my hand it returns back to its original size.
This is what I reached till now but I still have some problems that I can't solve.
public class Deformation : MonoBehaviour
{
Vector3 tempPos;
private void InteractionManager_SourceUpdated(InteractionSourceUpdatedEventArgs hand)
{
if (hand.state.source.kind == InteractionSourceKind.Hand)
{
Vector3 handPosition;
hand.state.sourcePose.TryGetPosition(out handPosition);
float negXRange = transform.position.x - transform.localScale.x;
float posXRange = transform.position.x + transform.localScale.x;
float negYRange = transform.position.y - (transform.localScale.y / 2);
float posYRange = transform.position.y + (transform.localScale.y / 2);
float negZRange = transform.position.z - transform.localScale.z;
float posZRange = transform.position.z + transform.localScale.z;
float handX = handPosition.x;
float handY = handPosition.y;
float handZ = handPosition.z;
if ((negXRange <= handX) && (handX <= posXRange) && (negYRange <= handY) && (handY <= posYRange) && (negZRange <= handZ) && (handZ <= posZRange))
{
tempPos.y = handPosition.y;
transform.localScale = tempPos;
}
else
{
tempPos.y = 0.3f;
transform.localScale = tempPos;
}
}
}
// Use this for initialization
void Start()
{
tempPos = transform.localScale;
InteractionManager.InteractionSourceUpdated += InteractionManager_SourceUpdated;
}
I attached two scripts to my object (cylinder) the TapToPlace script from the HoloToolKit and the deformation script stated above. The problem is when I deploy to my HoloLens to test, when I place the cylinder first to the needed place then try to deform it after that, it is placed but not deformed. If I tried it the other way around both work. Any ideas why does the deformation script does not work after the TapToPlace one?
The cylinder when viewed by my HoloLens is somehow transparent. I mean that I can see my hand through it. I need it to be more solid.
I wonder if there is something like a delay that I can use because when I use the deformation script stated above the cylinder is scaled to my hand position then scaled back to its default size very fast and appears as if blinking.
At first I place the cylinder on a setup (something as a table for example) then I begin to deform it. When I commented the else part in the deformation script stated above, it was scaled and left stable without returning to the original size. It is scaled symmetrically so its height is decreased from up and down resulting in the base of the cylinder becomes away from the table. I need the base of the cylinder to be always stable and touching the table under it.
Note: I am using Unity 2017.3.1f1 (64-bit) - HoloToolkit-Unity-2017.2.1.3
Thank you in advance.
1) Did you see the MRTK 2017.2.1.4 release? It has some useful features such as two handed resizing/scaling of objects. The BoundingBox code in the new MRTK release does moving and resizing in one component, it might be a better base to start from than the TapToPlace, or at least show how the two types of transform can work together.
2) What colour is your object? Hololens will render black as transparent, so try making the object bright white for testing. Also, just double check the brightness is turned up to full (the LHS buttons on the hololens). Finally, check your shader is the MRTK Standard shader. (again, the 2017.2.1.4 release has new shader code you might want to try.) . In a room without direct sunlight it should pretty much cover up your hand.
4) I'm not sure I follow completely, but the pivot point could be important here. If it is centred in the middle of the coil (as I'd imagine it is) then when you deform the coil down it will still stay centered at that central pivot point.
If you instead set the pivot point to the bottom of the coil, touching the table, you can scale and that point stays on the table and the top does all the moving.

Get Size of 3d mesh inside a Prefab in Unity?

I want to create a hexagon grid. I Have a 3D model which I made in blender with some dimensions.
I have a script in Unity which is supposed to generate a hex grid with a given hexagon.
The model of the hex is placed in a Prefab. I need the size "Real size not the scale" of that prefab in order to generate the grid.
How can I get the size of the model which is in a prefab.
public class GameWorld : MonoBehaviour
{
// Fields
public GameObject HexPrefab;
// Size of the map in terms of number of the objects
// This is not representative of the actual size of the map in units
public int Width = 20;
public int Height = 20;
void Start()
{
MeshRenderer[] asd = HexPrefab.GetComponentsInChildren<MeshRenderer>();
var a = asd[0].bounds;
Debug.Log(string.Format("x: - {0:f3}", a.size.x));
Debug.Log(string.Format("y: - {0:f3}", a.size.y));
Debug.Log(string.Format("z: - {0:f3}", a.size.z));
for (int x = 0; x < Width; x++)
{
for (int y = 0; y < Height; y++)
{
Instantiate(HexPrefab, new Vector3(x, 0, y), Quaternion.identity);
}
}
}
void Update()
{
}
}
Here are the dimensions from blender.
I don't want to hard code it because I will need to use hexagons of different sizes in the future!
This code gives me a size of 0.
The prefab consists of only one model and nothing else.
Thank you in advance!
My Prefab Consists of only the model.
Here is what it looks like.
And this is the properties of the model:
Then in the code I did the following:
Mesh mesh = HexPrefab.GetComponentsInChildren<MeshFilter>()[0].sharedMesh;
And now I can get the dimensions of the mesh like this:
mesh.bounds.size
In my case the prefab has a scale of 1 so the size of the model and the size of the prefab are the same but if you want to go the extra step you can multiply the size that we got from the model by the scale of the prefab.
Hope this helps someone who is having the same question!
Have a nice day!

How to draw a 2D graph on Canvas in Unity 5

I need to draw a graph for my decibel app that I am making with Unity. The solution below works but is not as exact as my employer would like. Could I make this graph look more professional and exact? Basically I want the lines to be of equal width and prevent the line from going almost invisible like in the following pic: http://puu.sh/qjSvO/a51c11cef5.png
I was thinking about making a 2D texture and using SetPixel, but I am not sure if that is the correct way.
The graph is drawn on a canvas as part of an scalable UI.
public class Graph : MonoBehaviour {
public float graphWidth;
public float graphHeight;
LineRenderer newLineRenderer;
List<int> decibels;
int vertexAmount = 50;
float xInterval;
GameObject parentCanvas;
// Use this for initialization
void Start ()
{
parentCanvas = GameObject.Find("Canvas");
graphWidth = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.width;
graphHeight = transform.Find("Linerenderer").GetComponent<RectTransform>().rect.height;
newLineRenderer = GetComponentInChildren<LineRenderer>();
newLineRenderer.SetVertexCount(vertexAmount);
xInterval = graphWidth / vertexAmount;
}
//Display 1 minute of data or as much as there is.
public void Draw(List<int> decibels)
{
if (decibels.Count == 0)
return;
float x = 0;
for (int i = 0; i < vertexAmount && i < decibels.Count; i++)
{
int _index = decibels.Count - i - 1;
float y = decibels[_index] * (graphHeight/130); //(Divide grapheight with the maximum value of decibels.
x = i * xInterval;
newLineRenderer.SetPosition(i, new Vector3(x - graphWidth / 2 , y - graphHeight / 2 , 0));
}
}
}
Using the editor, you can "cut" sprites into nine pieces, so that there is a texture for each side, a texture for each corner and a texture to fill it in. I would recommend using that to make it look good if you want it so. It is some time since i used it myself, but maybe you can find information on the Unity manual.

Jump animation using animation class

I need a little help in my little 2D game I want to create in XNA. I had almost no knowledge of programming before I got interested in XNA and C#, so maybe my problem is simple, but I just can't figure it out.
So basically, I have a base class, and I created an additional class Animation for animating sprites. I implemented some methods so that when the player presses "right" it would change the animation's current texture and increment X by a number of xf; anyway, the main idea is that I'm using just one instance of my class (basically, one object of type animation which changes its texture and properties based on what key is pressed).
So, I had no problems making it run right or left. Works out pretty well. The big problem started when I wanted to implement the jump sprite. So I created the 6 frames necessary for the sprite, but to animate it I have virtually no idea how to do it.
The only thing it does right now is to loop through the frames of the sprite, but the position (both .X and .Y) remain the same. The thing is, I have a Vector2 position which holds the animation's current position, and it's fine with running because I simply increment it. However, when it comes to jumping, I want it to increment .X, but the .Y should be decremented (thus going up) until frame number 3; after frame number 3, until the last frame, I want the .Y position to go down (thus fall) with the corresponding animations (erm, frames).
So, basically, I don't know how to modify the .X and .Y so that it would display the frames that I need in the time I need. I don't know if you really understood what I'm trying to say; basically when I press the "up" key, it loops through the frames but the position remains the same.
My idea was to use a reference to the actual Vector2 position which holds the animation's current position and pass it to the method in the other Animation.cs class, namely the PlayAnimJump, and modify the position after each frame and return it to the actual Game1.cs by reference. Even if I would do that (though I fail to see what good it would be), it wouldn't be updating the position as it should. So, any ideas?
Here is the code for the PlayAnimJump method from the Animation class:
public void PlayAnimJump(GameTime gameTime)
{
elapsed += (float)gameTime.ElapsedGameTime.Seconds;
sourceRect = new Rectangle(currentFrame * frameWidth, 0, frameWidth, frameHeight);
currentFrame = 0;
if (elapsed >= frameTime)
{
if (currentFrame <=3)
{
if (looping)
{
currentFrame++;
}
}
else if (currentFrame > 3)
{
currentFrame++;
}
elapsed = 0;
}
}
The default constructor for that class:
public Animation(ContentManager Content,string asset,float frameSpeed, int numbOfFrames, bool looping,Vector2 positionIT)
{
this.assetName = asset;
this.frameTime = frameSpeed;
this.numbOfFrames = numbOfFrames;
this.looping = looping;
this.animation = Content.Load<Texture2D>(asset);
frameWidth=(animation.Width / numbOfFrames);
frameHeight=animation.Height;
position = positionIT;
}
Here is the code (from the main) when the up key is pressed:
else if (up)
{
check = animation1.GetAsset();
if (check == "eright")
{
animation1.SetFrameSpeed(0.8f);
animation1.SetNumbOfFrames(6);
animation1.ChangeTexture(Content, "SarimCumVreJiorjica");
animation1.PlayAnimJump(gameTime);
/*position1.x +=2f;
position1.Y -=2f;
*/
}
So, I'm not sure how, but I'm supposed to change position1 according to the frame that's displayed by the animation in that second. Am I missing something?
If your animation class had a reference to the object that you wanted to move (i.e the object holding the position field) then you could modify it within the animation class, within the PlayAnimJump method.
Or, to reduce coupling, you could just have PlayAnimJump return a variable indicating how far into the jump you are (maybe a percentage of the jump, from 0 to 1). Then, you could use the percentage outside to set the objects position. So, if the jump is halfway done, the return value would be 0.5f, which you could use in an equation to determine the players y position. An example equation would be:
float percent = animation1.PlayAnimJump(gameTime);
float y = Math.Sin(percent * Math.PI) * maxJumpHeight;
player.positon.y = y;
This uses a sine wave to determine the players height throughout the jump animation. You would just need to write the code that determines the percentage of the way through the jump (currentFrame) in the PlayAnimJump method and return it.
Formula of the frŅƒefall for Y coordinate is
y = g * t ^ 2 / 2 + v0 * t + y0
Characters jump from height y0 vith start velocity v0 by Y axis and gravity gradually slows down and starts to fall.
Calculate deltaY using following formula
deltaY = g * t ^ 2 / 2 + v0 * t
First show the frame on which the character is pushed off the ground, then the frame on which it rises until it reaches the peak of the jump. Once the sign change deltaY from + to - show how the character change pose for fall. Something like that.

Categories