I wanted to create a quick "main menu" scene for my Google Tango project using Unity.This is the code I got:
using UnityEngine;
using System.Collections;
public class Main : MonoBehaviour {
public Object[] scenes;
void OnGUI () {
if (GUI.Button(new Rect(100, 200, 200, 100), "test Button")){}
for (int i = 0; i < scenes.Length; i++) {
if(GUI.Button(new Rect(0, i * Screen.height / scenes.Length, Screen.width, Screen.height / scenes.Length), "Load " + scenes[i].name)){
Application.LoadLevel(scenes[i].name);
}
}
}
}
This should (and does.. at least in the Editor) work just fine.However I can only see the single "test Button" on screen.
Why does this happen?
Related
I have a 3 toggle buttons in my playstate as follows:
public void ShowIt()
{
HydroElectric ec = new HydroElectric();
ec.t1Bool = GUI.Toggle (new Rect (25, 55, 100, 50), ec.t1Bool, "Turbina 2 MW");
ec.t2Bool = GUI.Toggle (new Rect (25, 95, 100, 50), ec.t2Bool, "Turbina 3 MW");
ec.t3Bool = GUI.Toggle (new Rect (25, 135, 100, 50), ec.t3Bool, "Turbina 1 MW");
GUI.Box (new Rect (Screen.width - 100, 60, 80, 25), ec.prod.ToString ()); // PRODUCED ENERGY
}
This buttons should change the value of t1Bool, t2Bool and t3Bool and those changes should be reflected in this script:
using System;
using UnityEngine;
namespace Assets.Code.PowerPlants
{
public class HydroElectric
{
public bool t1Bool;
public bool t2Bool;
public bool t3Bool;
public static int turbina1;
int turbina2;
int turbina3;
public float prod;
public HydroElectric ()
{
t1Bool = true;
t2Bool = true;
t3Bool = false;
prod = 0f;
}
public float HydroControlPanel ()
{
turbina1 = t1Bool ? 2 : 0;
turbina2 = t2Bool ? 3 : 0;
turbina3 = t3Bool ? 1 : 0;
prod = turbina1 + turbina2 + turbina3;
return prod;
}
}
}
I have no errors in the console but the toggle button simply does not work in play mode, like if the values are locked, I cannot check or uncheck the buttons, they just stay the way they start.
Do you have any idea why?
You are re-creating HydroElectric every time GUI-related functions are called, obviously changes are not reflected and you get the behavior you said.
Move this line of code out of that function to somewhere else such as in the constructor and it will behave properly.
I am currently creating a space shooter game. To this game I want a background with stars that keeps looping for eternity.
In order to create this, I made a tile based system that simply creates a rectangle for each texture. I have been able to make said textures kinda loop, but when they do I get a really weird bug.
As you can see, my tiles are sometimes generating a small gap between each other, and I am not sure as of why.
The problem probably lies within my Background.cs file, but I am unsure of where.
Also, I would like a better name for "Background.cs". Do you think that something like "Tile.cs" is better?
Background.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace SpaceShooter
{
class Background
{
public Texture2D texture;
public List<Rectangle> tiles = new List<Rectangle>();
public Color color;
public int tileSize;
public int speed;
GraphicsDevice graphicsDevice;
public Background(Texture2D texture, GraphicsDevice graphicsDevice, int tileSize)
{
this.texture = texture;
this.graphicsDevice = graphicsDevice;
this.tileSize = tileSize;
speed = 3;
this.color = Color.White;
CalculateTiles();
}
public void Update()
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y + speed, tiles[i].Width, tiles[i].Height);
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, 0 - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}
}
}
public void CalculateTiles()
{
if (tiles.Count() > 0)
{
for (int i = 0; i < tiles.Count(); i++)
{
tiles.Remove(tiles[i]);
}
}
int XT = (int)(graphicsDevice.Viewport.Width / (tileSize / 1.5f));
int YT = (int)(graphicsDevice.Viewport.Height / (tileSize / 1.5f));
for (int i = 0; i < XT; i++)
{
tiles.Add(new Rectangle(tileSize * i, 0, tileSize, tileSize));
for (int j = 0; j < YT; j++)
{
tiles.Add(new Rectangle(tileSize * i, tileSize * j, tileSize, tileSize));
}
}
}
public void Draw(SpriteBatch spriteBatch)
{
for (int i = 0; i < tiles.Count(); i++)
{
spriteBatch.Draw(texture, tiles[i], color);
}
}
}
}
Game.cs
public class Game1 : Microsoft.Xna.Framework.Game
{
Background background;
protected override void LoadContent()
{
// Assign Background
background = new Background(Content.Load<Texture2D>("Stars"),GraphicsDevice, 128);
}
protected override void Update(GameTime gameTime)
{
if(Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Escape))
this.Exit();
background.Update();
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(bgc);
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend);
// Call all drawing functions here
background.Draw(spriteBatch);
player1.Draw(spriteBatch);
player2.Draw(spriteBatch);
//
spriteBatch.End();
base.Draw(gameTime);
}
I think your problem can be easily solved with LinearWrap
if you do the following in your Game1.draw.
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.LinearWrap);
background.Draw(spriteBatch);
spriteBatch.End();
to get the scale simply do this calculation:
float scale = 128 / 512; // Where 128 is your desired size. and 512 your actual texture size.
and in your Background.cs draw method.
spriteBatch.Draw(texture, new Vector2(0,0), new Rectangle(pos.X, pos.Y, graphicsDevice.Viewport.Width / scale, graphicsDevice.Viewport.Height / scale), Color.White, 0, Vector2.Zero, scale, SpriteEffects.None, 0);
this should repeat your texture over the entire screen.
EDIT:
To make the image dynamic you could use a Camera. But using the system you have you would simply on Update do this :
pos += new Vector2(movementX, movementY);
Note that the spriteBatch.Draw has a parameter "Source Rectangle". If you change the position of this rectangle your texture will shift.
The problem has been solved.
I am now putting the tile up relative to the screen height instead of raw programming it to 0.
if (tiles[i].Y >= graphicsDevice.Viewport.Height)
{
tiles[i] = new Rectangle(tiles[i].X, tiles[i].Y - graphicsDevice.Viewport.Height - tiles[i].Height, tiles[i].Width, tiles[i].Height);
}
OnGui won't show up when I start the game for some reason. I've attached the script to a gameobject:
public class username : MonoBehaviour {
private static string user = "";
void OnGui()
{
GUI.Label(new Rect((Screen.width / 2), (Screen.height / 2), 300, 300), "Username");
user = GUI.TextField(new Rect(-4, 0, 100, 100), user);
if (GUI.Button(new Rect(-4, 0, 200, 30), "Continue"))
{
WWWForm form = new WWWForm();
form.AddField("", user);
WWW w = new WWW("http://site/register.php", form);
StartCoroutine(register(w));
}
}
Thanks
OnGui() is case-sensitive and needs to be OnGUI().
http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnGUI.html
I am trying to set up a health bar for a 2D game using OnGUI. I have an outside texture and an inside texture for the meter. The set up I have now works partially. I am able to change the scale of the inside meter so it looks like it is depleting, however the position along the x is changing as well. This causes an awkward effect as well as the meter moving outside its container.
void Update ()
{
score = EnemyScript.killCount * 100;
powerScale -= 1;
}
void OnGUI()
{
//Score and Power Containter
GUILayout.BeginArea(new Rect(Screen.width/8, Screen.height/8, 500, 200));
GUILayout.Label("Score: " + score, style);
GUI.DrawTexture(new Rect(-10,20,200,80),powerBoundry);
GUILayout.EndArea();
//Power Meter
GUILayout.BeginArea(new Rect(Screen.width/8, Screen.height/8, 450, 200));
GUI.DrawTexture(new Rect(-10,20,powerScale,80),powerFill, ScaleMode.ScaleAndCrop);
GUILayout.EndArea();
}
Is it possible to anchor it in place? Or perhaps make it a child of a game object to anchor it?
try using DrawTextureWithTexCoords.
void OnGUI()
{
GUILayout.BeginArea(new Rect(Screen.width / 8, Screen.height / 8, 500, 200));
GUI.DrawTexture(new Rect(-10, 20, 200, 80), powerBoundry);
GUI.DrawTextureWithTexCoords(new Rect(-10, 20, powerScale, 80), powerFill, new Rect(0f, 0f, (float)powerScale / 200f, 1f));
GUILayout.EndArea();
}
I was wondering how to approach creating a HUD.
I currently have health, mana, and experience bar drawn to the screen at set coordinates. Downside of this is that when the camera pans the bars stay at their set coordinates, I want them to adjust to the viewport or not be influenced by positions but just simply drawn to the screen.
Edit
I managed to get the HUD to adjust using the camera's x and y coordinates.
I've created a separate class for drawing the HUD, but now they don't adjust.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using GameOne.Components;
namespace GameOne.GameScreens
{
public class HUD : BaseGameState
{
Player player;
Texture2D HealthBar;
Texture2D HealthBarPositive;
Texture2D HealthBarNegative;
Texture2D ManaBar;
Texture2D ManaBarPositive;
Texture2D ManaBarNegative;
Texture2D ExpBar;
Texture2D ExpBarPositive;
int CurrentHealth = 100;
int CurrentMana = 45;
int CurrentExp = 0;
public HUD(Game game, GameStateManager manager)
: base(game, manager)
{
player = new Player(game);
}
public void LoadContent()
{
base.LoadContent();
HealthBar = Game.Content.Load<Texture2D>(#"GUI\healthBar");
HealthBarPositive = Game.Content.Load<Texture2D>(#"GUI\healthBarPositive");
HealthBarNegative = Game.Content.Load<Texture2D>(#"GUI\healthBarNegative");
ManaBar = Game.Content.Load<Texture2D>(#"GUI\manaBar");
ManaBarPositive = Game.Content.Load<Texture2D>(#"GUI\manaBarPositive");
ManaBarNegative = Game.Content.Load<Texture2D>(#"GUI\manaBarNegative");
ExpBar = Game.Content.Load<Texture2D>(#"GUI\expBar");
ExpBarPositive = Game.Content.Load<Texture2D>(#"GUI\expBarPositive");
}
public void Update(GameTime gameTime)
{
if (InputHandler.KeyDown(Keys.F1))
{
CurrentHealth += 1;
}
if (InputHandler.KeyDown(Keys.F2))
{
CurrentHealth -= 1;
}
if (InputHandler.KeyDown(Keys.F3))
{
CurrentMana += 1;
}
if (InputHandler.KeyDown(Keys.F4))
{
CurrentMana -= 1;
}
if (InputHandler.KeyDown(Keys.F5))
{
CurrentExp += 1;
}
if (InputHandler.KeyDown(Keys.F6))
{
CurrentExp -= 1;
}
CurrentHealth = (int)MathHelper.Clamp(CurrentHealth, 0, 100);
CurrentMana = (int)MathHelper.Clamp(CurrentMana, 0, 45);
CurrentExp = (int)MathHelper.Clamp(CurrentExp, 0, 500);
}
public void Draw(GameTime gameTime)
{
GameRef.SpriteBatch.Draw(
HealthBarNegative,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 630, 150, 15),
Color.White);
GameRef.SpriteBatch.Draw(
HealthBarPositive,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 630, 150 * (int)CurrentHealth / 100, 15),
Color.White);
GameRef.SpriteBatch.Draw(
HealthBar,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 630, 150, 15),
Color.White);
GameRef.SpriteBatch.Draw(
ManaBarNegative,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 650, 150, 15),
Color.White);
GameRef.SpriteBatch.Draw(
ManaBarPositive,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 650, 150 * (int)CurrentMana / 45, 15),
Color.White);
GameRef.SpriteBatch.Draw(
ManaBar,
new Rectangle((int)player.Camera.Position.X + 150, (int)player.Camera.Position.Y + 650, 150, 15),
Color.White);
GameRef.SpriteBatch.Draw(
ExpBarPositive,
new Rectangle((int)player.Camera.Position.X + 10, (int)player.Camera.Position.Y + 680, 1260 * (int)CurrentExp / 500, 15),
Color.White);
GameRef.SpriteBatch.Draw(
ExpBar,
new Rectangle((int)player.Camera.Position.X + 10, (int)player.Camera.Position.Y + 680, 1260, 15),
Color.White);
}
}
}
When you are drawing your Health bars, is it inside a Spritebatch.Begin( ... ) where you specify your camera matrix?
If you draw it in its own Spritebatch.Begin, without the camera, the position of the health bars will stay relative to the screen.
When you extend you class with DrawableGameComponent, you can use the property DrawOrder to set it topmost.
The class will be a bit different, you have to overload Update, draw and LoadContent, but it will be all the same.
This is only usefull if you use a HUD with SpriteBatch.