Showing GUI Texture only when button is held down? - c#

This script controls the cameras FOV when "Fire2" is pressed as well as displaying a GUI texture. However, once the user presses the button once, the texture displays and does not disappear until the button is pressed again - I want it to only show when the button is held down? This script is attached to a prefab which is a child object of the player prefab. I have tried to just use GetButton but seeing as OnGUI() is called every frame as well as the Update() function it just made the texture flicker.
using UnityEngine;
using System.Collections;
public class awpScopeIn : MonoBehaviour {
public Texture scopeGUI;
private bool _isScoped = false;
public Color color = Color.black;
private Camera cam;
public GameObject awp_graphics;
void Start()
{
cam = GetComponentInParent( typeof(Camera) ) as Camera;
cam.clearFlags = CameraClearFlags.SolidColor;
cam.fieldOfView = 70f;
}
void OnGUI()
{
float width = 600;
float height = 600;
if (_isScoped) {
GUI.DrawTexture (new Rect ((Screen.width / 2) - (width/2), (Screen.height / 2) - (height/2), width, height), scopeGUI);
}
}
void Update()
{
if(Input.GetButtonDown("Fire2"))
{
_isScoped = !_isScoped;
cam.backgroundColor = color;
cam.fieldOfView = 45f;
awp_graphics.gameObject.SetActive(false);
}else if(Input.GetButtonUp("Fire2"))
{
cam.fieldOfView = 70f;
awp_graphics.gameObject.SetActive(true);
}
}
}

You are just changing the value when the button is pressed but you have to update the flag for showing texture when the button is released. So your Update method should be:
if(Input.GetButtonDown("Fire2"))
{
_isScoped = !_isScoped;
cam.backgroundColor = color;
cam.fieldOfView = 45f;
awp_graphics.gameObject.SetActive(false);
}else if(Input.GetButtonUp("Fire2"))
{
cam.fieldOfView = 70f;
awp_graphics.gameObject.SetActive(true);
_isScoped = false;
}

Related

I want to make Highlightable button while PointerEnter in Unity2D Canvas but that should be Unselectable

Buttons cannot be highlighted when they are selected in Unity Canvas. I only want mausehover/pointerEnter thing.
I am making a platform based 2D mobile game. Users can move their fingers without take off from the screen. So I don't need Pressed and Selected states.
The alpha of the button will be maximum when it is in PointerEnter state, and the alpha of the button will be like 100/255 when it is in PointerExit state. That's it.
Tried something like change Transition to Sprite Swap; like trying Toggle component instead of Button in Unity. But I'm stuck, I don't know solution is.
You could not use the Button component at all and rather have a simple component and "do it all yourself" - as you say using the IPonterEnterHandler / IPointerExitHandler interfaces
public class HoverButton : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
[SerializeField] private Image image;
[SerializeField] private Color normal = new Color(1f, 1f, 1f, 0.4f);
[SerializeField] private Color hover = Color.white;
// event called when pointer enters this button
public UnityEvent onEnter;
// event called once a frame while the button stays hovered
public UnityEvent whileHovered;
// event called when pointer exits this button
public UnityEvent onExit;
// wasn't sure if you still want fade effects
// if not you can of course skip all related stuff and just hard assign the image.color
[SerializeField][Min(0f)] private float fadeDuration = 0.2f;
private Coroutine currentRoutine;
private float currentFactor;
private void Awake()
{
if(!image) image = GetComponent<Image>();
}
private IEnumerator Fade(bool isHover)
{
var targetColor = isHover ? hover : normal;
var targetFactor = isHover ? 1f : 0f;
if(fadeDuration > 0f)
{
var step = (isHover ? (1 - currentFactor) : currentFactor) / fadeDuration;
while(!Mathf.Approximately(currentFactor, targetFactor))
{
currentFactor = Mathf.MoveTowards(currentFactor, targetFactor, step * Time.deltaTime);
image.color = Color.Lerp(normal, hover, currentFactor);
whileHovered.Invoke();
yield return null;
}
}
currentFactor = targetFactor;
image.color = targetColor;
// continue calling the whileHovered every frame
while(true)
{
whileHovered.Invoke();
yield return null;
}
}
public void OnPointerEnter(PointerEventData pointerEventData)
{
if(currentRoutine != null) StopCoroutine(currentRoutine);
currentRoutine = StartCoroutine(Fade(true));
onEnter.Invoke();
}
public void OnPointerExit(PointerEventData pointerEventData)
{
if(currentRoutine != null) StopCoroutine(currentRoutine);
currentRoutine = StartCoroutine(Fade(false));
onExit.Invoke();
}
}

Unity Pan and Zoom. Camera translate changes entirely once i click on screen

I'm trying to set Panning and zooming functions for my unity project. I got the codes i used from https://kylewbanks.com/blog/unity3d-panning-and-pinch-Ito-zoom-camera-with-touch-and-mouse-input. This is the code I used:
using UnityEngine;
using System.Collections;
public class CameraHandler : MonoBehaviour {
private static readonly float PanSpeed = 20f;
private static readonly float ZoomSpeedTouch = 0.1f;
private static readonly float ZoomSpeedMouse = 0.5f;
private static readonly float[] BoundsX = new float[]{-10f, 5f};
private static readonly float[] BoundsZ = new float[]{-18f, -4f};
private static readonly float[] ZoomBounds = new float[]{10f, 85f};
private Camera cam;
private Vector3 lastPanPosition;
private int panFingerId; // Touch mode only
private bool wasZoomingLastFrame; // Touch mode only
private Vector2[] lastZoomPositions; // Touch mode only
void Awake() {
cam = GetComponent<Camera>();
}
void Update() {
if (Input.touchSupported && Application.platform != RuntimePlatform.WebGLPlayer) {
HandleTouch();
} else {
HandleMouse();
}
}
void HandleTouch() {
switch(Input.touchCount) {
case 1: // Panning
wasZoomingLastFrame = false;
// If the touch began, capture its position and its finger ID.
// Otherwise, if the finger ID of the touch doesn't match, skip it.
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Began) {
lastPanPosition = touch.position;
panFingerId = touch.fingerId;
} else if (touch.fingerId == panFingerId && touch.phase == TouchPhase.Moved) {
PanCamera(touch.position);
}
break;
case 2: // Zooming
Vector2[] newPositions = new Vector2[]{Input.GetTouch(0).position, Input.GetTouch(1).position};
if (!wasZoomingLastFrame) {
lastZoomPositions = newPositions;
wasZoomingLastFrame = true;
} else {
// Zoom based on the distance between the new positions compared to the
// distance between the previous positions.
float newDistance = Vector2.Distance(newPositions[0], newPositions[1]);
float oldDistance = Vector2.Distance(lastZoomPositions[0], lastZoomPositions[1]);
float offset = newDistance - oldDistance;
ZoomCamera(offset, ZoomSpeedTouch);
lastZoomPositions = newPositions;
}
break;
default:
wasZoomingLastFrame = false;
break;
}
}
void HandleMouse() {
// On mouse down, capture it's position.
// Otherwise, if the mouse is still down, pan the camera.
if (Input.GetMouseButtonDown(0)) {
lastPanPosition = Input.mousePosition;
} else if (Input.GetMouseButton(0)) {
PanCamera(Input.mousePosition);
}
// Check for scrolling to zoom the camera
float scroll = Input.GetAxis("Mouse ScrollWheel");
ZoomCamera(scroll, ZoomSpeedMouse);
}
void PanCamera(Vector3 newPanPosition) {
// Determine how much to move the camera
Vector3 offset = cam.ScreenToViewportPoint(lastPanPosition - newPanPosition);
Vector3 move = new Vector3(offset.x * PanSpeed, 0, offset.y * PanSpeed);
// Perform the movement
transform.Translate(move, Space.World);
// Ensure the camera remains within bounds.
Vector3 pos = transform.position;
pos.x = Mathf.Clamp(transform.position.x, BoundsX[0], BoundsX[1]);
pos.z = Mathf.Clamp(transform.position.z, BoundsZ[0], BoundsZ[1]);
transform.position = pos;
// Cache the position
lastPanPosition = newPanPosition;
}
void ZoomCamera(float offset, float speed) {
if (offset == 0) {
return;
}
cam.fieldOfView = Mathf.Clamp(cam.fieldOfView - (offset * speed), ZoomBounds[0], ZoomBounds[1]);
}
}
The Panning and Zooming are working fine but only works when i make transform.position = pos; a comment. This line is what messes my entire panning and zooming system up. Once i make it a comment, The panning and zooming works, but without boundaries. And i need those boundaries. I'm using a terrain for my scene. that's where my entire project settles on.
What happens is when i press play on my unity editor, it all looks fine until i click on the screen. Once my mouse button touches the screen on play mode, my camera just faces an entirely different direction. The entire camera translate changes, i won't even see any of the Gameobjects on my scene anymore. Does anyone know where the problem could be coming from?

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);
}
}

unity Transform position setting boundries in object

I am trying to make a movement where sprites go down in a row inside a panel, and then they stop when reaching the bottom boundry of the panel. Problem is after i set the position of the objects where it has to stop moving, its taking me position.y = 0 as if it was the middle of the screen. How do i set it to stop moving, when reaching the bottom of its parent object (the panel). Thank you.
here is my code
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Transform_test : MonoBehaviour
{
[SerializeField]
SpriteRenderer[] Reels;
[SerializeField]
Transform[] ReelsTransform;
int speed;
bool drop;
[SerializeField]
GameObject Panel;
void Start()
{
Debug.Log(transform);
//transform.position = new Vector3 (10,0,0);
speed = 1;
drop = false;
}
// Update is called once per frame
void Update()
{
// test();
if (drop == false)
{
foreach (Transform Reels in ReelsTransform)//This Targets All Children Objects Of The Main Parent Object
{
Debug.Log("pos " + Reels.transform.position.y);
for (int i = 0;i<5;i++)
{
//Direction And Speed Of Movement
new WaitForSeconds(Random.Range(1, 3));
Reels.transform.Translate(Vector3.down * Time.smoothDeltaTime * speed, Space.World);
if (Reels.transform.position.y <= 0 )
{
Reels.transform.position = new Vector3(Reels.transform.position.x, Reels.transform.position.y + 58, Reels.transform.position.z);
}
}
}
}
}
}
Ok this is how i solved it. I created an empty sprite on the place where i want the reel to stop, then i set the if to match that position with the position of the first sprite in the reel. If the positions match. Turn moveto to true and stop the movement
public class transform2 : MonoBehaviour
{
public float speed;
public SpriteRenderer sprite1;
public SpriteRenderer[] sprites;
public SpriteRenderer cell1;
public GameObject Panel;
bool moveto;
void move()
{
if (moveto == false)
{
foreach (SpriteRenderer sprites in sprites)
{
sprites.transform.Translate(Vector3.down * Time.smoothDeltaTime * speed, Space.World);
if (sprite1.transform.position.y <= cell1.transform.position.y)
{
moveto = true;
sprite1.transform.position = cell1.transform.position;
}
Debug.Log("MOVE");
}
}
}
// Start is called before the first frame update
void Start()
{
speed = 20;
}
// Update is called once per frame
void Update()
{
move();
}
}

UI Panel Lerp Update

I have a couple of UI Panels that I wish to move into the screen area.
I have made a script to attach to each Panel but it does little when I do my changes in Update which I am now using LateUpdate instead which almost works.
The panel will move into the screen only very slightly as if LateUpdate was called only once.
Oddly, when I do the same with a second Panel, it's 'HidePanel' method then lets the first Panel come fully into view. Then the first Panel's 'HidePanel' method works correctly.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class DisplayPanel : MonoBehaviour {
private bool isMovingIn = false;
private bool isMovingOut = false;
private Vector2 posOut; //The panel's position hidden just outside the RH screen edge.
private Vector2 posIn; //The panel’s position shown just inside the RH screen edge.
private Vector2 pos; //The panel’s current position.
//Initialization
void Start () {
RectTransform rt = GetComponent<RectTransform>();
posOut = new Vector2 ((Screen.width + rt.rect.width)/2, 0); //To be hidden just outside the RH screen edge.
posIn = new Vector2 (posOut.x - rt.rect.width, 0); //To be visible just inside the RH screen edge.
pos = posOut;
rt.anchoredPosition = pos; //Move panel to the RH screen edge.
}
public void LateUpdate() {
RectTransform rt = GetComponent<RectTransform> ();
rt.anchoredPosition = pos; //Need this for start..
if (isMovingIn == true) {
if ((int)pos.x != (int)posIn.x) { //Casting floats to ints so we can eventually find equality.
pos = Vector2.Lerp (pos, posIn, 2*Time.deltaTime);
rt.anchoredPosition = pos;
}
else {
isMovingIn = false; }
}
else
if (isMovingOut == true) {
if ( (int)pos.x != (int)posOut.x) {
pos = Vector2.Lerp (pos, posOut, 2 * Time.deltaTime);
rt.anchoredPosition = pos; }
else {
isMovingOut = false; }
}
}
public void DisplayPanel(){
isMovingOut = false;
isMovingIn = true;
}
public void HidePanel(){
isMovingIn = false;
isMovingOut = true;
}
}//End class

Categories

Resources