I want to create a health bar using information that I'm currently displaying in a GUItext. The behaviour I want is for the health to decrease over time (like a countdown timer), but increase by a small amount whenever the player collects an object.
Here is my current code:
using UnityEngine;
using System.Collections;
public class TimeText : MonoBehaviour {
public GUIText timeText;
//countdown
public float timer = 99.00f;
// Update is called once per frame
void Update ()
{
timer -= Time.deltaTime*5;
timeText.text = "Health: " + timer.ToString("0");
}
}
Here is what I would like my health bar to look like:
As #JoeBlow mentioned above, avoid the old GUI mechanics. They are super heavy, crude, and not performance-helpful.
#Serlite broke down the question for you. Those are what you need.
For the health-bar, I suggest using Unity UI's Image component. Use the image you want (possibly the same one you posted in your question?) for the health bar and change the fillAmount based on your timer variable (though personally, I would rename that to something like "health" to represent its purpose better).
It looks like you've already taken care of reducing the health over time.
To add to the health, use Colliders as triggers in the scene, and OnTriggerEnter or any of the similar default monobehavior methods on the appropriate objects.
I suggest going through a couple tutorials online, so that you get a better understanding of programming logic in Unity. I hope that helps!
Related
Hi I'm new to coding games and using Unity, when I switch Scenes in unity the objects 100x and the saturation gets weird
Here is my current script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
Pins += 1;
}
// Update is called once per frame
void Update()
{
if (Pins == 4)
{
SceneManager.LoadScene("Level 2", LoadSceneMode.Additive);
}
}
}
Welcome to Unity! There are a few issues I can see, so I will try to explain each one. The main issue you are currently having is you are loading a scene on top of itself using the LoadSceneMode.Additive. It is loading the scene Level 2 on top of itself as long as Pins is equal to 4, which I am guessing is every frame.
I would instead put this check inside of the OnCollisionEnter as it should only be called once. Your other issue is you are not checking what you are colliding with. You might want to check the object you hit by tag. If you are unfamiliar with tags, you can look at the docs. Adding a tag to your game called Pins and adding it to all of your objects that are pins will help resolve what you are colliding with.
Now to solve the near infinite amount of scenes you are spawning. As I mentioned, it is because your conditional check is in Update, which in Unity is called every frame. With the condition you are currently checking for, if pins is not reset, it will keep loading your scene. As you are also using the Scene.Additive, it will load the new scene on your old scene, so the variable pins will not reset unless you collide with something else. I would recommend changing your code to this example:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class Game_End : MonoBehaviour
{
int Pins = 0;
void OnCollisionEnter(Collision collision)
{
// we are only checking if the object we hit is tagged as 'Pins' to make sure we hit a pin
if(collision.gameObject.tag == "Pins")
{
// add to the pins
Pins += 1;
// destroy the pin we hit so the player can not hit it twice
Destroy(collision.gameObject);
// check our condition to load the new scene
if(Pins == 4)
{
SceneManager.LoadScene("Level 2");
}
}
}
}
Now that you are only checking if the collision is with an object tagged as Pin, the counter will only go up when you collect a pin. By adding the Destroy, you assure that each pin will only increase the count by 1. And finally, by putting your level check inside of this function, it will only check your condition when it increases the count. My one question is, do you want to use LoadSceneMode.Additive? It loads a scene directly over your current scene. I believe you'd want to load the scene normally so it loads your new scene. Would you mind clarifying how you want to load the new scene a bit more? In my example snippet I removed the additive as I believe you do not want to use it. The docs Unity has for LoadScene use it, so I assume you got it from there.
If you do not understand any of what I said, feel free to ask any questions in the comments. I can tweak the answer as needed to help you understand.
I am quite new in game development, I am using Unity in combination with C# with Models which are made in Blender.
I was wondering, if there is a way to "play" a scene from a certain point. For example, if I have a game (single scene for simplicity now) and like to test a certain part of the Game (e.g. I would like to test the 3rd of 5th quests within this scene, assuming that you can access the 2nd quest only if you successfully completed the 1st one, and so on).
But I really don't wanna to play through my scene for a while, just to reach the point which I originally wanted to test.
How can i achieve this? And if it is not possible in some simple way, is there some kind of workaround for this?
Thanks!
Not sure if I understood correctly, but if you want to jump from scene to scene, within your project, you can always use the sceneManager.
https://docs.unity3d.com/ScriptReference/SceneManagement.SceneManager.LoadScene.html
Hope that helps.
In your class, create a variable that holds the value for starting quest. e.g. 3.
Then for testing purpose, in the Start() method, you can check the value of that variable and write some code to change the elements in the scene to represent the corresponding quest(3 in this case) like the position of the character, or next objective or anything that is specific to the quest.
You can make this variable public so that you can change its value from unity instead of opening the script every time.
I am not sure if it is feasible for your game, but if you have a lot of things that change for each quest, it is best to have a different scene for each one of them.
Here is the sample code on how i did it.. hope this will help you..
Create a C# script called GoScene1
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GoScene1 : MonoBehaviour {
public void Scene1Change() {
Application.LoadLevel("GoScene1");
}
}
Then Create a C# Script Called GoScene2
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GoScene2 : MonoBehaviour {
public void Scene2Change() {
Application.LoadLevel("GoScene2");
}
}
Heres the Screen shot...
I have multiple enemies that move toward the player. I am trying to stop them from merging into each other, i.e maintain some type of minimum distance between each other. What I'm trying is this (from unity3d forums):
enemy1.transform.position = (enemy1.transform.position -
enemy2.transform.position).normalized * distance + enemy2.transform.position;
However, when I have >= 3 enemies they still seem to bunch up even when I apply this to every enemy combination.
I need a better method as this one does not work and does not scale.
What you do around your enemy prefab is place a quad box which in effect is a trigger element, then on you script for the enemy you set that if another enemy (using tag types, I imagine) comes within touching of the quad box then to run appropriate code to stop the enemy getting closer in and to prevent the enemy actually overlapping with this trigger box.
Your code you example in your question looks like it is referencing the enemy units specifically rather than as instance entitites which is very probably a bad way of coding, as you're finding, it's very inflexible dealing with not-specifically-named reference entities.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
private Transform otherEntity;
public float distance = 50.0f;
private Transform thisEntity;
void OnTriggerEnter(Collider other)
{
otherEntity = other.GetComponent<Transform>();
thisEntity = GetComponent<Transform>();
thisEntity.position = (thisEntity.position - otherEntity.position).normalized * distance + otherEntity.position;
}
}
I have not tested the above code but using the code you reference the values for the transform are loaded from the Game Component for the referenced entities, as this has changed ALOT in Unity since release of version 5.1 and your source for your code was an answer given in 2012!!
thisEntity is the object that the script is attached to, typically one of the enemy. The otherEntity is the object that comes within the quad trigger (please remember the quad needs to be referenced as a trigger element.
The values of the Entity variables need to be set once the trigger is entered, so that it always effects the correct other element.
(I may be totally wrong with my methodology but I hope this helps.)
I was following a unity tutorial started on Unity 4 but I am on Unity 5, and when I try to use the script seen (https://youtu.be/vwUahWrY9Jg?t=1337) and I try to use it, it gives an error:
Assets/Scripts/DestroyFinishedParticle.cs(18,17): error CS0246: The type or namespace name `Destroy' could not be found. Are you missing a using directive or an assembly reference?
this is the code:
using UnityEngine;
using System.Collections;
public class DestroyFinishedParticle : MonoBehaviour {
private ParticleSystem thisParticleSystem;
// Use this for initialization
void Start () {
thisParticleSystem = GetComponent<ParticleSystem>();
}
// Update is called once per frame
void Update() {
if (thisParticleSystem.isPlaying)
return;
Destroy (GameObject);
}
}
It can be because C# code for unity changed from 4 to 5? what should I change? The problem seems to be in the Update method.
There are couple of issues with this code.
First, you didn't mention to what exactly is it attached too? I assume it attached to the Particle System.
Secondly, use "gameObject", not "GameObject", since GameObject is the name of the class.
Third, I believe there's a much more efficient way to destroy the gameObject without checking every frame whether the particles system has finished or not, maybe set a small timer? or invoke the function with time?
Depending on how your event is set up would depend on the approach to checking if the particles are running. If you can setup a collider to when you walk in, you can trigger an event to know the particles are on. Upon exiting the collider, the particles will shut off.
I'm not 100% on the syntax of return in C# but seems like it should go after you destroy your game object. I think return works in a similar fashion as the break in that aspect.(Especially since you don't seem to be returning any values anyway why do you need it?)
I have started learning Unity and already have learned JavaScript for web development so I do have some programming experience.
While programming in unity I came across a few things involving classes that I didn't quite get.
1) When I wright code as a component of a unity object I write it inside the public class shown below. (name Mover is just an example.) However I never create an instance of this class so how does this work? All I see is the class being created.
using UnityEngine;
using System.Collections;
public class Mover : MonoBehaviour {
}
2) Also shown in the code above is MonoBehaviour. I read the api and it said it is a base class. I never came across this in JavaScript. What does this mean and what does it do to the class Mover?
Try this.
Go to your project in Unity, create a c# script, name it whatever you want. Create a cube in your scene. Drag and drop this script onto the object. Open the script and you should see a start method and an update method.
Type Debug.Log("Start"); in the void Start() function, same in the void Update() method but change to the string to whatever. Click play in unity and watch the console.
You should see the console printing stuff.
Anything that is a child of Monobehaviour enables you to do a lot in which I am not going to get into here.
https://docs.unity3d.com/Documentation/ScriptReference/
At the top, you can choose the language. Get used to that page. =D
Hope this leads you somewhere!
For the first question, you may attach the script to a gameobject in the scene to use it.
For example,
public class Mover : MonoBehaviour {
private bool started = false;
void Start () {
Debug.Log ("Mover Started");
started = true;
}
}
If you attach this script to a gameobject in your scene and play the scene. The script will run and print out "Mover Started" and set the private boolean to true.
This are many other ways to interact with other objects or scripts too. Hope it clears things up a little.
If you take a look at Unity's docs for MonoBehaviour you'll see that every JS file associated with your project automatically derives from MB. If you're coding c#, understand that not everything must be a MB. Objects in the game hierarchy may only attach component scripts that inherit from MB objects. Unity handles the construction of these objects, and a MB is actually something that you are forbidden from constructing yourself.
Also, I think you might be better off at unityAnswers for Unity related help.