I have a setup that includes a joystick + button ( that implements IPointerUpHandler and IPointerDownHandler )
IPointerUpHandler Is not called sometimes when i'm dragging the joystick at the same time ( mobile of course)
Anyone have a solution?
I tried moving the button to a different canvas, did not work.
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ControllerButton : UIBehaviour, IPointerDownHandler, IPointerUpHandler
{
public UnityAction<bool> onClick;
public RawImage icon;
//Detect current clicks on the GameObject (the one with the script attached)
public void OnPointerDown(PointerEventData pointerEventData)
{
//Output the name of the GameObject that is being clicked
onClick?.Invoke(true);
Debug.Log(name + "Game Object Click in Progress");
}
//Detect if clicks are no longer registering
public void OnPointerUp(PointerEventData pointerEventData)
{
onClick?.Invoke(false);
Debug.Log(name + "No longer being clicked");
}
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
}
}
Related
I'm quite new to Unity and just started learning UI and made a volume slider in a settings scene. I've learnt how to use those 2 functions to save the PlayerPref of the volume so whenever the player enters the settings scene again, the volume will be saved from last time.
However, I wonder how you can change it so it will do the same but on the main menu? So that way the player doesn't need to go back to settings for it to apply.
The code:
`using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;
using UnityEngine.SceneManagement;
public class SettingsMenu : MonoBehaviour
{
public Slider volumeSlider;
void Start()
{
keepVolumeValue();
GameObject.FindGameObjectWithTag("Music").GetComponent<MusicManager>().playMusic();
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
SceneManager.LoadScene("MainMenu");
}
private void OnDisable()
{
PlayerPrefs.SetFloat("volume", volumeSlider.value);
}
public void keepVolumeValue()
{
volumeSlider.value = PlayerPrefs.GetFloat("volume", volumeSlider.value);
}
public void setVolume(float volume)
{
mainMixer.SetFloat("volume", Mathf.Log10(volume)*30f);
}`
Ty for any help
I wrote a simple script for the button and threw it in the" On Click " in the button, but my Button1 function is not displayed there. How to solve this problem?
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class Nikita : MonoBehaviour
{
public void Button1()
{
Debug.Log("button clicked");
}
// Start is called before the first frame update
void Start()
{
Debug.Log("started");
}
// Update is called once per frame
void Update()
{
}
}
you want to set the button by: public Button ButtonName;
then in start you want to add listener: ButtonName.onClick.AddListener(ButtonFunction);
then add button function :void ButtonFunction()
{
Debug.Log("string here")
}
then you just drag the button to the inspector, set the onclick in inspector and the option would be under the name Nikita-ButtonName
I would try to implement IPointerClickHandler
"Event System exists in the Scene to allow click detection" as adviced in the docs.
You can check this example.
For your case could be something like (not debugged):
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
public class Nikita : MonoBehaviour, IPointerClickHandler
{
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log("button clicked");
}
// Start is called before the first frame update
void Start()
{
Debug.Log("started");
}
// Update is called once per frame
void Update()
{
}
}
Unity has a new inputsystem where the old OnMouseDown() {} no longer works.
In the migration guide they mention replacing this with Mouse.current.leftButton.isPressed.
And in other forum posts they mention using an InputAction.
The problem is that these options detect mouse clicks anywhere in the scene, instead of just on the object:
public InputAction clickAction;
void Awake() {
clickAction.performed += ctx => OnClickedTest();
}
void OnClickedTest(){
Debug.Log("You clicked anywhere on the screen!");
}
// this doesn't work anymore in the new system
void OnMouseDown(){
Debug.Log("You clicked on this specific object!");
}
How can I detect mouse clicks on a specific gameObject with the new input system in Unity?
With this code somewhere in your scene:
using UnityEngine.InputSystem;
using UnityEngine;
public class MouseClicks : MonoBehaviour
{
[SerializeField]
private Camera gameCamera;
private InputAction click;
void Awake()
{
click = new InputAction(binding: "<Mouse>/leftButton");
click.performed += ctx => {
RaycastHit hit;
Vector3 coor = Mouse.current.position.ReadValue();
if (Physics.Raycast(gameCamera.ScreenPointToRay(coor), out hit))
{
hit.collider.GetComponent<IClickable>()?.OnClick();
}
};
click.Enable();
}
}
You can add an IClickable Interface to all GameObjects that want to respond to clicks:
public interface IClickable
{
void OnClick();
}
and
using UnityEngine;
public class ClickableObject : MonoBehaviour, IClickable
{
public void OnClick()
{
Debug.Log("somebody clicked me");
}
}
Make sure you have a an EventSystem with an InputSystemUIInputModule in the scene and a PhysicsRaycaster or Physics2DRaycaster on your Camera, and then use the IPointerClickHandler interface on the object with a collider on itself or its children:
using UnityEngine;
using UnityEngine.EventSystems;
public class MyClass : MonoBehaviour, IPointerClickHandler {
public void OnPointerClick (PointerEventData eventData)
{
Debug.Log ("clicked");
}
}
in my Unity scene I'm trying to activate a portal animation when you pick up all the coins on that level, but the problem is that my portal script does not detect when the coin counter value is equal to 6 (that's the total number of coins in that level).
I have this script which is the script that is attached to the coins and increases the coin counter value.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MonedaScript2 : MonoBehaviour
{
public GameObject moneda;
public AudioClip clip;
public Vector3 PosicionMoneda;
public void Update ()
{
transform.Rotate (0, 90 * Time.deltaTime, 0);
}
public void OnTriggerEnter(Collider other)
{
if (other.name == "Player")
{
AudioSource.PlayClipAtPoint(clip, PosicionMoneda, 1f);
AparecerPortalNivel9.ContadorMonedas += 1;
Destroy(moneda);
}
}
}
And then i have the portal script which sould detect ewhen you pick all the coins. It is attached to the PanelPortal gameobject.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class AparecerPortalNivel9 : MonoBehaviour
{
public Animator anim;
public GameObject PanelPortal;
//public ScoringSystem SS;
public bool DeberiaAparecer = true;
public static int ContadorMonedas;
void Start()
{
//SS = GameObject.FindGameObjectWithTag("SistemaDeScore").GetComponent; ScoringSystem();
PanelPortal.gameObject.SetActive(false);
}
void Update()
{
if (ContadorMonedas == 6f)
{
Debug.Log("FuncionaHostia");
PanelPortal.gameObject.SetActive(true);
anim.SetBool("Aparecer",true);
DeberiaAparecer = false;
}
}
}
Could someone help me on what should i do so my portal script detects when the coins picked up are 6 and then run all the functions inside the IF method?
Thanks everyone
A MonoBehaviour's Update will never run while the gameobject it is on is disabled.
Because AparecerPortalNivel9 is attached to PanelPortal, when you do this you are preventing the Update method from being called:
PanelPortal.gameObject.SetActive(false);
The easiest solution here is to move AparecerPortalNivel9 to a different gameobject.
Basically, I am designing a game where I need a canvas image element to respond quickly and move along when it is dragged. So for that, I am implementing IDragHandler interface. But the method OnDrag gets called after a delay of about half second.
public class InputHandler : MonoBehaviour, IDragHandler
{
public void OnDrag(PointerEventData eventData)
{
// this gets logged after about 500 milliseconds
Debug.Log("mouse dragged");
}
}
I've attached this script on the same image element that I want to move along with the drag. This element has raycast target on and the graphic raycast component is enabled for its parent canvas. The image element falls behind the touch point initially but catch up later on because of which it feels like there is some lag in the input. Is there a way to remove/minimize this delay?
The lag might be due to the DragThreshold that is active by default. You can disable it this way:
public class OnDragScript : MonoBehaviour, IDragHandler, IInitializePotentialDragHandler
{
public void OnDrag(PointerEventData ped)
{
transform.Translate(ped.delta);
}
public void OnInitializePotentialDrag(PointerEventData ped)
{
ped.useDragThreshold = false;
}
}
Although I am not finding any delay. Perhaps you should start with 3 functions (begin, drag and end) to find out what exactly is happening.
Also, the IDragHandler works only for canvas elements. So your pointer should be within the boundaries of UI element while you begin your drag.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class InputHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public void OnDrag(PointerEventData eventData)
{
Debug.Log("OnDrag");
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("Drag Begin");
}
public void OnEndDrag(PointerEventData eventData)
{
print("Drag End");
}
}