My axes won't show up - c#

I'm trying to implement a class drawing a 3D indicator such as this one :
indicating the current rotation of the camera by drawing each axis at every frame as if it was in 3D.
However, when my code runs I just can't see anything being drawn. When I try to draw it in Update() nothing is appearing on the screen but I still can see "The axes have been drawn in Update" showing up in the console. I tried to do it in OnPostRender() but it doesn't seem to be triggered, "The axes have been drawn" doesn't show up in the console.
What could I be doing wrong ?
using UnityEngine;
using System.Collections;
using System.IO;
using UnityEngine.UI;
public class AxesManager : MonoBehaviour {
private static readonly int DEFAULT_AXIS_LENGTH = 100;
private Material _xMaterial;
private Material _yMaterial;
private Material _zMaterial;
private Vector3 _origin;
private int _length;
// Use this for initialization
void Start () {
UpdateMaterials();
_origin = GetAxesOrigin();
_length = DEFAULT_AXIS_LENGTH;
}
// Update is called once per frame
void Update () {
//ClearAxes();
//DrawAxes();
//Debug.Log("The axes have been drawn in Update");
}
void OnPostRender()
{
DrawAxes();
Debug.Log("The axes have been drawn");
}
private void DrawAxes()
{
//draw x axis
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
_xMaterial.SetPass(0);
GL.LoadOrtho();
GL.Begin(GL.LINES);
GL.Color(Color.green);
GL.Vertex(_origin);
GL.Vertex(new Vector3(_length, 0, 0));
GL.End();
GL.PopMatrix();
//draw y axis
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
_yMaterial.SetPass(0);
GL.LoadOrtho();
GL.Begin(GL.LINES);
GL.Color(Color.red);
GL.Vertex(_origin);
GL.Vertex(new Vector3(0, _length, 0));
GL.End();
GL.PopMatrix();
//draw z axis
GL.PushMatrix();
GL.MultMatrix(transform.localToWorldMatrix);
_zMaterial.SetPass(0);
GL.LoadOrtho();
GL.Begin(GL.LINES);
GL.Color(Color.blue);
GL.Vertex(_origin);
GL.Vertex(new Vector3(0, 0, _length));
GL.End();
GL.PopMatrix();
}
private void ClearAxes()
{
//clear the axes here
}
private Vector3 GetAxesOrigin()
{
return new Vector3(100,100,0);
}
private void UpdateMaterials()
{
_xMaterial = Resources.Load("Materials" + Path.DirectorySeparatorChar + "XAxisMaterial", typeof(Material)) as Material;
_yMaterial = Resources.Load("Materials" + Path.DirectorySeparatorChar + "YAxisMaterial", typeof(Material)) as Material;
_zMaterial = Resources.Load("Materials" + Path.DirectorySeparatorChar + "ZAxisMaterial", typeof(Material)) as Material;
}
}
EDIT : After having attached the script to a camera (rendering the top layer), I can now see OnPostRender() being triggered, but nothing shows up and no errors. What could it be ?

Related

Gap between objects (images) in unity

I am working on a clicker game, which implies the interaction of 2 players. One of the objects (images made with ui) becomes larger if one of the players taps more. But I ran into a problem, for some reason unity creates a gap between objects. Also, if the red object becomes larger than blue - the problem disappears. I have attached the code and video with the problem.
The problem isn't in random values.
Also i tried to fix it with Transform.SetSiblingIndex, and it didn't work either.
There's a link to screenshot with the problem
there's a link to video with the problem
The code from GameCore:
public void OnPointerClick(PointerEventData eventData)
{
ScaleEvents();
Vector3 clickPosition = Camera.main.ScreenToWorldPoint(eventData.position);
if (eventData.rawPointerPress == Player1)
{
Player1.transform.localScale += scaleChange;
Player2.transform.localScale -= scaleChange;
}
else if(eventData.rawPointerPress == Player2)
{
Player2.transform.localScale += scaleChange;
Player1.transform.localScale -= scaleChange;
Player1.transform.SetSiblingIndex(0);
}
Debug.Log(clickPosition);
Debug.Log(eventData.rawPointerPress);
Debug.Log(randomScaleChange);
}
private void ScaleEvents()
{
randomScaleChange = Random.Range(0.05f, 0.3f);
scaleChange = new Vector3(0.0f, randomScaleChange, 0f);
}
}
From what I understand, should you rather use RectTransform.deltaSize.y, and adjust the actual height of your UI elements, instead of the scale. Someone smarter than me can explain to you why. If I tried to explain it, I would probably cause more confusion.
Your blue element should be anchored to the top, and your red element should be anchored to the bottom. If you now add 50 pixel to the height of your blue element, and substract 50 from the height of your red element, it should work out, without a gap in between.
Also, please note that with your current solution, your red bar grows bigger than the amount of which your blue bar shrinks. So yes, you don't have a gap. But your Red bar is actually overdrawing over your blue bar.
Edit:
Below I present you a possible solution that hopefully gets you on the right track.
For it to work, blue needs to be anchored to the top of your screen. Anchors Min: 0, 1; Max; 1, 1; Pivot 0.5, 1.
Red needs to be anchored to the bottom of the screen. Anchors Min: 0,0; Max; 1, 0; Pivot 0.5, 0.
Set the hight for both elements so that they touch seamlessly.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickGame : MonoBehaviour, IPointerClickHandler
{
public RectTransform Player1;
public RectTransform Player2;
float randomScaleChange;
public void OnPointerClick(PointerEventData eventData)
{
ScaleEvents();
Vector3 clickPosition = Camera.main.ScreenToWorldPoint(eventData.position);
if (clickPosition.y > 0f) // Blue clicked
{
Player1.sizeDelta = new Vector2(100f, Player1.sizeDelta.y + randomScaleChange);
Player2.sizeDelta = new Vector2(100f, Player2.sizeDelta.y - randomScaleChange);
}
if (clickPosition.y < 0f) // Red clicked
{
Player2.sizeDelta = new Vector2(100f, Player2.sizeDelta.y + randomScaleChange);
Player1.sizeDelta = new Vector2(100f, Player1.sizeDelta.y - randomScaleChange);
}
}
private void ScaleEvents()
{
randomScaleChange = Random.Range(5f, 50f);
}
}
There's what a code looks like now and still didn't work:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickerZone : MonoBehaviour, IPointerClickHandler
{
[SerializeField] private GameObject _Player1;
[SerializeField] private GameObject _Player2;
private RectTransform _player1Rect;
private RectTransform _player2Rect;
private Vector3 _scaleChange;
private float _randomScaleChange;
private void Awake()
{
_player1Rect = _Player1.GetComponent<RectTransform>();
_player2Rect = _Player2.GetComponent<RectTransform>();
}
public void OnPointerClick(PointerEventData eventData)
{
ScaleEvents();
Vector3 clickPosition = Camera.main.ScreenToWorldPoint(eventData.position);
if (eventData.rawPointerPress == _Player1)
{
_Player1.transform.localScale += _scaleChange;
_player1Rect.sizeDelta = new Vector2(0f, _player1Rect.sizeDelta.y + _randomScaleChange);
_Player2.transform.localScale -= _scaleChange;
_player2Rect.sizeDelta = new Vector2(0f, _player2Rect.sizeDelta.y - _randomScaleChange);
}
else if(eventData.rawPointerPress == _Player2)
{
_Player2.transform.localScale += _scaleChange;
_player2Rect.sizeDelta = new Vector2(0f, _player2Rect.sizeDelta.y + _randomScaleChange);
_Player1.transform.localScale -= _scaleChange;
_player1Rect.sizeDelta = new Vector2(0f, _player1Rect.sizeDelta.y - _randomScaleChange);
}
Debug.Log(clickPosition);
Debug.Log(eventData.rawPointerPress);
Debug.Log(_randomScaleChange);
}
private void ScaleEvents()
{
_randomScaleChange = Random.Range(0.05f, 0.3f);
_scaleChange = new Vector3(0.0f, _randomScaleChange, 0f);
}
}

Draw GUI.Label to mouse position

Hey i wondered if you can draw GUI.Label to mouse position, and how you can do it?
I'am currently doing the script in Unity C#.
Script layout:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Test : MonoBehaviour {
public bool Hover = false;
void OnMouseOver()
{
Hover = true;
}
void OnMouseExit()
{
Hover = false;
}
void OnGUI()
{
if(Hover = true)
{
GUI.Label(new Rect(//Transform to mouse positon))
}
}
}
Use Input.mousePosition to create the Rect that is passed to GUI.Label. Note that both of these use screen coordinates but for Input.mousePosition the bottom-left of the screen is (0, 0), and for the Rect used by GUI.Label the top-left of the screen is (0, 0). Thus, you need to flip the y-values like this:
void OnGUI()
{
var mousePosition = Input.mousePosition;
float x = mousePosition.x;
float y = Screen.height - mousePosition.y;
float width = 200;
float height = 200;
var rect = new Rect(x, y, width, height);
GUI.Label(rect, "Test");
}
For more information, see Unity's documentation on Input.mousePosition and GUI.Label
You need to convert screen coordinates (mouse position) to GUI ones.
void OnGUI()
{
if(Hover = true)
{
Vector2 screenPos = Event.current.mousePosition;
Vector2 convertedGUIPos = GUIUtility.ScreenToGUIPoint(screenPos);
GUI.Label(new Rect(convertedGUIPos.x, convertedGUIPos.y, width, height))
}
}
I have not actually tested the code though.
More info here:
https://docs.unity3d.com/ScriptReference/GUIUtility.ScreenToGUIPoint.html

Updating Texture During Movement

I'm new to this so not completely sure whether I am posting this correctly, but I have been having a few issues when creating my game. My main goal is to create a topdown shooter styled game, using movement where the 'player' rotates based on the current position of the mouse and can press 'w' to move towards it at a set speed.
The main issue is, when the game loads, the movement works exactly how I want it to, but the texture itself is not moving, but only the drawRectangle.
Game1.cs:
player = new Player(Content, #"graphics\Player1", 500, 500, spritePosition);
spritePosition = new Vector2(player.CollisionRectangle.X, player.CollisionRectangle.Y);
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || Keyboard.GetState().IsKeyDown(Keys.Escape))
Exit();
KeyboardState keyboard = Keyboard.GetState();
MouseState mouse = Mouse.GetState();
IsMouseVisible = true;
distance.X = mouse.X - spritePosition.X;
distance.Y = mouse.Y - spritePosition.Y;
//Works out the rotation depending on how far away mouse is from sprite
rotation = (float)Math.Atan2(distance.Y, distance.X);
// TODO: Add your update logic here
spritePosition = spriteVelocity + spritePosition;
spriteOrigin = new Vector2(player.DrawRectangle.X / 2, player.DrawRectangle.Y / 2);
if (Keyboard.GetState().IsKeyDown(Keys.W))
{
spriteVelocity.X = (float)Math.Cos(rotation) * tangentialVelocity;
spriteVelocity.Y = (float)Math.Sin(rotation) * tangentialVelocity;
}
else if(spriteVelocity != Vector2.Zero)
{
Vector2 i = spriteVelocity;
spriteVelocity = i -= friction * i;
}
This is the main movement code from the Update function as well as where the new player has been created.
Player.cs:
class Player
{
Texture2D sprite;
Rectangle drawRectangle;
int health = 100;
public Player(ContentManager contentManager, string spriteName, int x , int y, Vector2 velocity)
{
LoadContent(contentManager, spriteName, x, y, velocity);
}
public Rectangle CollisionRectangle
{
get { return drawRectangle; }
}
public Rectangle DrawRectangle
{
get { return drawRectangle; }
set { drawRectangle = value; }
}
public int Health
{
get { return health; }
set {
health = value;
if (health <= 0)
health = 0;
if (health > 100)
health = 100;
}
}
public Vector2 Velocity
{
get { return Velocity; }
set { Velocity = value; }
}
public void Update(GameTime gameTime, KeyboardState keyboard, MouseState mouse)
{
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(sprite, drawRectangle, Color.White);
}
private void LoadContent(ContentManager contentManager, string spriteName, int x, int y, Vector2 velocity)
{
sprite = contentManager.Load<Texture2D>(spriteName);
drawRectangle = new Rectangle(x - sprite.Width / 2, y - sprite.Height / 2, sprite.Width, sprite.Height);
}
}
I didn't know what to include in the Update function of the player.cs, whether the code for movement should go in there or the main Game1.cs.
Hopefully this is enough code for you guys to be able to help. Sorry for there being quite a lot of code, but I'm just unsure where the error is occurring.
Thanks in advance
For the rotation you would want to use 'another' kind of spriteBatch.Draw, because the draw function can have more parameters than your currently using.
The full draw function is as followed:
SpriteBatch.Draw(Texture2D texture, Vector2 position, Rectangle sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerdepht)
As you can see, now we have a parameter for rotation that can be used.
So your code will look something like this:
spriteBatch.Draw(sprite, drawRectangle, null, Color.White, rotation, Vector2.Zero, 1, SpriteEffects.None, 0);
As for your question for where your code should go. It is good to learn yourself to put the code where it belongs, in this case the player. Because when your programs become bigger, it would be very messy to do it this way.
To call the update function in your player class, you can just simply call player.Update(gameTime, keyboard, mouse) in the Update of Game1.

How to detect mouse click on GUITexture in unity

I am trying to add controls through mouse in place of keyboard in the game.
I added 4 movement keys and 1 fire button through the GUI texture in unity.
In the game there is already a player controller which controls the player through keyboard strokes
I didnt get, how to make the player move if the direction button (GUITexture) is clicked
Button Script
using UnityEngine;
using System.Collections;
public class RightButton : MonoBehaviour {
public Texture2D bgTexture;
public Texture2D airBarTexture;
public int iconWidth = 32;
public Vector2 airOffset = new Vector2(10, 10);
void start(){
}
void OnGUI(){
int percent = 100;
DrawMeter (airOffset.x, airOffset.y, airBarTexture, bgTexture, percent);
}
void DrawMeter(float x, float y, Texture2D texture, Texture2D background, float percent){
var bgW = background.width;
var bgH = background.height;
GUI.DrawTexture (new Rect (x, y, bgW, bgH), background);
var nW = ((bgW - iconWidth) * percent) + iconWidth;
GUI.BeginGroup (new Rect (x, y, nW, bgH));
GUI.DrawTexture (new Rect (0, 0, bgW, bgH), texture);
GUI.EndGroup ();
}
}
I am unable to add the GUI Button in place of GUI.DrawTexture, its giving invalid argument error
and so i am unable to add how to check the button is clicked or not
Thanks
GUITexture is part of the legacy GUI system. An example of how to get this to work as a button is here.
using UnityEngine;
using System.Collections;
public class RightButton : MonoBehaviour {
public Texture bgTexture;
public Texture airBarTexture;
public int iconWidth = 32;
public Vector2 airOffset = new Vector2(10, 10);
void start(){
}
void OnGUI(){
int percent = 100;
DrawMeter (airOffset.x, airOffset.y, airBarTexture, bgTexture, percent);
}
void DrawMeter(float x, float y, Texture texture, Texture background, float percent){
var bgW = background.width;
var bgH = background.height;
if (GUI.Button (new Rect (x, y, bgW, bgH), background)){
// Handle button click event here
}
var nW = ((bgW - iconWidth) * percent) + iconWidth;
GUI.BeginGroup (new Rect (x, y, nW, bgH));
GUI.DrawTexture (new Rect (0, 0, bgW, bgH), texture);
GUI.EndGroup ();
}
}

GUI Label is staying on screen when camera facing away from object?

I have GUI Labels over NPC's in my game, and the labels display their name above their head. But when I walk away and go somewhere else, their name's stay on screen like it's mirrored or something?
Here's what I'm talking about:
This is how it looks normally
This is what happens when I walk out of view.
The Code:
using UnityEngine;
using System.Collections;
public class NPC : MonoBehaviour {
private float left;
private float top;
public float leftModifier;
public float topModifier;
private Vector3 NPCScreenPosition;
//FIX THE MIRRORING ISSUE
void Start () {
}
void Update () {
Vector3 NPCNameWorldPosition = (transform.position + new Vector3(0.0f, transform.lossyScale.y, 0.0f));
NPCScreenPosition = Camera.main.WorldToScreenPoint(NPCNameWorldPosition);
left = NPCScreenPosition.x + leftModifier;
top = Screen.height - (NPCScreenPosition.y + topModifier);
}
void OnGUI() {
GUI.Label(new Rect(left, top, 150, 25), gameObject.name.ToString());
}
}
The simplest solution to your issue would be to check the depth (z value) of the screen coordinates to see if the object is in front of the camera, i.e. if it's visible or not. If so, the value will be positive.
Being said, changing your draw call as below should do the trick:
void OnGUI
{
if(NPCScreenPosition.z >= Camera.main.nearClipPlane)
GUI.Label(new Rect(left, top, 150, 25), gameObject.name.ToString());
}

Categories

Resources