Changing the image of long clicked Sprite - c#

I am trying to change the image of a sprite that's had a long click on it.
My below code works except in the LongPress method it changes the image of all sprites that have this script assigned as an inspector component. Additionally, the code triggers after long clicking anywhere onscreen, not isolating itself to just the sprites with the script assinged
OnMouseDownAsButton would solve a lot of the issues, however wrapping bits of my code in an OnMouseDownAsButton function to isolate the colliders seems to cancel out the update() method.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
public class LongClickButton : MonoBehaviour
{
public Sprite flagTexture;
public Sprite defaulttexture;
public float ClickDuration = 2;
public UnityEvent OnLongClick;
bool clicking = false;
float totalDownTime = 0;
void Update()
{
if (Input.GetMouseButtonDown(0))
{
totalDownTime = 0;
clicking = true;
}
if (clicking && Input.GetMouseButton(0))
{
totalDownTime += Time.deltaTime;
if (totalDownTime >= ClickDuration)
{
clicking = false;
OnLongClick.Invoke();
}
}
if (clicking && Input.GetMouseButtonUp(0))
{
clicking = false;
}
}
public void LongPress()
{
if (GetComponent<SpriteRenderer>().sprite == flagTexture)
{
GetComponent<SpriteRenderer>().sprite = defaulttexture;
}
else if(GetComponent<SpriteRenderer>().sprite == defaulttexture)
GetComponent<SpriteRenderer>().sprite = flagTexture;
}
}

Try using OnMouseDown functions and OnMouseUpAsButton. Your current issue seems that the Input detects of a mouse down anywhere on screen, which causes all scripts to activate, which causes the changes.
void OnMouseDown() {
clicking = true
}
void OnMouseUpAsButton(){
clicking = false
}
void Update() {
if(clicking){
//your time stuff
}
}

You could add a EventTrigger component to the gameobject with the "OnPointerEnter" and "OnPointerExit" events to check if the mouse is on that object (Make OnPointerEnter call a function that sets a boolean to true and OnPointerExit to set that boolean to false).

What you could do is make your script implement interafaces IPointerEnterHandler, IPointerExitHandler found in namespace UnityEngine.EventSystems. Inside onPointerEnter and onPointerExit you could set a value of boolean variable.

Related

(Unity - C#) Problems with buttons triggering other events

I'm developing a 2D mobile game where the player should tap on the screen to go up. I just added a pause button recently and I've noticed that when I click the button it counts as a tap on the screen, so the player goes up. Basically, in the same exact moment that I press the pause button, the player jumps and then the game freezes while he is in mid-air. Is there a way I could make so the button wouldn't count as a tap?
Here's the part of the player script that makes him move:
if (Input.GetMouseButtonDown (0) && isDead == false && isKnifeDead == false && UiStartScript.uiInstance.firstClickUi == true) {
rb.velocity = Vector2.up * velocity;
}
Heres's the part of the UI script for the pause button:
public void PauseGame()
{
Time.timeScale = 0;
}
My EventSystem:
EventSystem
My Button:
Button
An easy with no code required is to remove the code about detecting tap on screen and instead place a button that covers the whole screen (invisible button).
That button event would trigger the screen movement.
You can add extra buttons on top and Unity will automatically discard the tap from any other button below.
This way you can start adding UI all over without checking in code which should be considered.
In U. I script add
public GameObject PlayerConrtollerScript;
In your U.I Script, under the class Pausgame()
Add this code.
GameObject.PlayerControllerScript.SetActive = false;
When unpaused you need to add to your script that has the
Time. timeScale =1;
Add this code.
GameObject.PlayerControllerScript.SetActive = true;
After you have added the code mentioned above. Don't forget to add the player game object from your hierarchy into the Inspector with the U. I script, the space will be available to add a game object when you scroll down to your U. I script.
That will stop your player from moving around during pause.
This is the approach that I been done. I create a cople of tricks using Event System and Canvas for take advantage of the Mouse Input, you don't need the use of Updates functions for do the basic gameplay.
Here's my example project: TapAndJump on Github
Check the GameObjects called "Click Panel" and "Pause Button" and
respective linked methods.
JumpWithTap.cs
using UnityEngine;
public class JumpWithTap : MonoBehaviour
{
[SerializeField] private UIHandler uiHandler;
[SerializeField] private float jumpPower = 5f;
private Rigidbody2D rb2D;
private int counter;
#region Class Logic
public void Jump()
{
rb2D.velocity = Vector2.up * jumpPower;
uiHandler.SetNumberToCounter(++counter);
}
#endregion
#region MonoBehaviour API
private void Awake()
{
rb2D = GetComponent<Rigidbody2D>();
}
#endregion
}
UIHandler.cs
using UnityEngine;
using UnityEngine.UI;
public class UIHandler : MonoBehaviour
{
[SerializeField] private Text counterText;
[SerializeField] private Text pauseText;
[SerializeField] private Image clickPanel;
private bool isPaused = false;
public bool IsPaused
{
get { return isPaused; }
set
{
pauseText.gameObject.SetActive(value);
isPaused = value;
}
}
#region Class Logic
public void SetNumberToCounter(int number) => counterText.text = number.ToString();
public void DisableClickPanel() => clickPanel.raycastTarget = !clickPanel.raycastTarget;
public void PauseGame()
{
IsPaused = !IsPaused;
DisableClickPanel();
// Time.timeScale = IsPaused == true ? 0 : 1; // If you want keep the Physics (ball fall) don't stop the time.
}
#endregion
}
I guided by your code example and so on; be free that modify and request any issue.

How to create a menu on click of GameObject? (Unity)

I want to be able to hover over a GameObject (agent) and on either right or left click, create a floating menu similar to the windows right click menu. I have tried using a combination of OnGUI() and OnMouseOver() but I either don't get the behaviour I need or get nothing at all. Here is what I have so far:
private void OnMouseOver()
{
mouseOver = true;
mousePos = Input.mousePosition;
}
private void OnMouseExit()
{
mouseOver = false;
}
private void OnGUI()
{
if (mouseOver && Input.GetMouseButtonDown(0))
{
GUI.Box(new Rect(mousePos.x, mousePos.y, 200f, 100f), "this is a test");
}
}
mouseOver and mousePos are initialy set to false.
Input.GetMouseButtonDown() only executes for a single frame so the GUI.Box is being drawn but only for a single frame.
To fix this Input.GetMouseButton() can be used instead as it executes for as long as the button is pressed.
What I do is create my desired menu in a Canvas, add an animator controller and an animation and put it outside of the camera view (the animation moves the menu inside the camera view), finally add a bool condition trigger to hide or show the menu
Then i just attach a click function into a button to fire the animation when somebody clicks it
public class ShowMenu : MonoBehaviour
{
public Animator ObjectBtnAnimations;
public void HideObjControls()
{
if (ObjectBtnAnimations.GetBool("hide"))
{
ObjectBtnAnimations.SetBool("hide", false);
}
else
{
ObjectBtnAnimations.SetBool("hide", true);
}
}
}

How can I switch toggle Input.GetKeyDown in unity?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DroidMove : MonoBehaviour
{
public GameObject droid;
private void Start()
{
droid.SetActive(false);
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.D))
{
droid.transform.position = droid.transform.position - transform.forward;
droid.SetActive(true);
}
}
}
I want that once I click on D it will show the Droid and also when I move the camera(transform) the droid will follow the camera.
And when I click once again on D set the droid active to false so each time I click on D it will toggle between SetActive false and true.
For toggling an object you should use something like this. PSEUDO
if (Input.GetKeyDown(KeyCode.D))
{
droid.enabled = !droid.enabled;
}
This will allow you to toggle your gameObject each time you press the button D.
In KeyDown
droid.transform.position = droid.transform.position - transform.forward;
This will work only once (One Frame). So you can use a bool or check if your gameObject is active to follow your camera. In Update you can use the following
if (droid.activeInHierarchy == true) // or you can use a bool here
{
droid.transform.position = droid.transform.position - transform.forward;
}
Hope this helps. Cheers!

how to make an ammo limit decrease from its current value, after it has been increased in C#, Unity?

my character shoots arrows. She starts without zero arrows and cannot shoot any until she picks up an arrow icon. Arrow icons have a value of 3. After this she can shoot arrows. That code works fine. Now I have to make it so these arrows decrease in value through the UI text display. The UI text value changes from 0 to 3 when an arrow icon is picked up, but it doesn't decrease when I shoot an arrow. I have another game object with a script that will detect when an arrow is shot. when this happens, it tells that main script that, "hey, an arrow was just shot." The focus is on getting the Text to decrease when I shoot an arrow.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class arrowManager : MonoBehaviour {
private Text text;
public static int arrowCount;
public static int arrowRecount;
private int maxArrows = 99;
void Start ()
{
text = GetComponent<Text> ();
arrowCount = 0;
}
void Update ()
{
FullQuiver ();
arrowCounter ();
}
void arrowCounter()
{
if (arrowCount < 0) {
arrowCount = 0;
text.text = "" + arrowCount;
}
if (arrowCount > 0)
text.text = "" + arrowCount;
}
public static void AddPoints(int pointsToAdd)
{
arrowCount += pointsToAdd;
}
public static void SubtractPoints(int pointsToSubtract)
{
arrowCount -= pointsToSubtract;
}
public void FullQuiver()
{
if (arrowCount >= maxArrows)
{
arrowCount = maxArrows;
}
}
}
the game object with the script that detects arrows looks like this.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class arrowDetector : MonoBehaviour {
public int pointsToSubtract;
void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "arrow")
{
arrowManager.SubtractPoints (pointsToSubtract);
}
}
}
Forgive me if I've misunderstood, but it looks to me like you are subtracting from the wrong variable.
Since you are displaying the 'arrowCount' variable, I imagine that's what should be subtracted from.
public static void SubtractPoints(int pointsToSubtract)
{
if (arrowCount > 0) {
arrowCount -= pointsToSubtract;//pointsToSubtract is an int value passed to this script from my player script whenever she shoots an arrow.
}
}
In SubtractPoints method you are detracting from the variable "arrowRecount".
Wouldn't you want to be subtracting from "arrowCount" instead? If you used "arrowCount" your text value should update properly.
I figured it out. Before, I was trying to get it to detect my arrows whenever a bool became true from my player script. That wasn't working so I said screw it and just made an empty that detects gameobjects with the tag "arrow." Then I updated the script in here to reflect that. I was dead tired last night after not getting any sleep for two days so I forgot to put in a value of pointsToSubtract in the hierarchy. Thanks everyone for their responses.

Jump Button in Unity for Canvas

I am looking for a code or script in C# or Java to make my cube tagged as a Player jump, in below script.
I have written some code and attached it to a button on canvas, but the problem is when I press and hold the button, it keeps jumping and makes an infinitly high jump.
Here is my script written in C#
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class DownstateButton : Button
{
public void Update()
{
//A public function in the selectable class which button inherits from.
if(IsPressed())
{
WhilePressed();
}
}
public void WhilePressed()
{
var player =GameObject.FindWithTag("Player");
player.transform.Translate(0, 1, 0);
//It was for jump
}
}
Hook the PointerDown (called when the button is pressed down) and PointerUp (button has been let go again) events from the UIButton and weight the translation of the position with Time.deltaTime, and you should be good to go. (player.transform.Translate(0,1 * Time.deltaTime, 0), optionally multiply it with another factor for speed modulation.) References: http://unity3d.com/learn/tutorials/modules/beginner/ui/ui-events-and-event-triggers
EDIT: Yeah, some example code. First, I have an EventTrigger component on the button. I use this sothat I can hook the PointerDown and PointerUp events as described before. It looks like this in the inspector:
(Use the "Add New Event Type" button to redirect the event calls.)
Then, I have this script on the button. The code speaks for itself.
using UnityEngine;
using UnityEngine.EventSystems;
public class JumpButton : MonoBehaviour {
private bool shouldJump = false;
// Update is called once per frame
void Update () {
//Find the player
var player = GameObject.FindGameObjectWithTag("Player");
//No player? exit out.
if (player == null)
return;
//Is the jump button currently being pressed?
if (shouldJump)
{
//Translate it upwards with time.
player.transform.Translate(new Vector3(0, Time.deltaTime * 5, 0));
//Make sure the Rigidbody is kinematic, or gravity will pull us down again
if (player.GetComponent<Rigidbody>().isKinematic == false)
player.GetComponent<Rigidbody>().isKinematic = true;
}
//Not jumping anymore? reset the Rigidbody.
else
player.GetComponent<Rigidbody>().isKinematic = false;
}
//When the button is being pressed down, this function is called.
public void ButtonPressedDown(BaseEventData e)
{
shouldJump = true;
}
//When the button is released again, this function is called.
public void ButtonPressedUp(BaseEventData e)
{
shouldJump = false;
}
}
The thing with switching to a kinematic rigidbody is optional, though. Also the speed can be adjusted with the multiplicative constant in the Translate() call. I tested this code with a standard cube, that has the Player tag and a Rigidbody on it, and it works fine.
Happy coding.
You could use a unity coroutine.
At the start of the routine, you'd set (for example) "isJumping" (a bool), and then before you start your loop bit, you'd check if you are jumping by checking 'isJumping'.
If not "isJumping", set isJumping to true, do your jump, and then on the completion of the routine, set isJumping to false.
//untested (uncompiled) code written on the fly
bool isJumping = false;
IEnumerator doJump()
{
if (!isJumping) {
isJumping = true;
// do jump (probably a loop)
while (jumpCondition) {
// jump instructions
yield return
}
//unset isJumping, inside 'if' but after yield return
isJumping = false
}
}
Note : code after yield return in a coroutine will only (probably) be run once, and only run as the coroutine exists (because no more yielding means the coroutine is at an end)

Categories

Resources