Long Press Button issue on moving mouse - unity3d

I use a long press button, which works very well, on MouseDown and if I don't move the mouse, at the end of my delay, I have my action.
If I move the mouse (still pressing down and still on the button) it resets my button's delay, and I don't understand why.
if anyone has an idea, it would help me a lot.
Thx
Here's my code :
private bool _PointerDown;
public float DelaiReponse;
private float _PointerDownTimer;
private bool _IsValidate = false;
private float _Delai;
public void OnPointerDown(PointerEventData eventData)
{
_PointerDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
_PointerDown = false;
_PointerDownTimer = 0;
}
void Start()
{
_Delai = DelaiReponse;
}
private void Update()
{
if (_PointerDown) // Timer Button Validation Hold
{
_PointerDownTimer += Time.deltaTime;
if (_PointerDownTimer >= _Delai)
{
_IsValidate = true;
}
}
}enter code here

Using Input.GetMouseDown(0) and Input.GetMouseButtonUp(0) could fix the problem:
private void Update()
{
if (Input.GetMouseDown(0))
{
_PointerDown = true;
}
if (Input.GetMouseUp(0))
{
_PointerDown = false;
_PointerDownTimer = 0;
}
if (_PointerDown) // Timer Button Validation Hold
{
:
:
}
:
:
}

I finally found
OnMouseDown even worked outside my button, and I preferred the OnPointerDown method.
I added IDragHandler to my class, and create a bool _PointerDrag
private bool _PointerDown;
private bool _PointerDrag;
public float DelaiReponse;
private float _PointerDownTimer;
private bool _IsValidate = false;
private float _Delai;
public class LongClickButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IDragHandler
{
public void OnPointerDown(PointerEventData eventData)
{
_PointerDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
_PointerDown = false;
_PointerDownTimer = 0;
}
public void OnDrag(PointerEventData eventData)
{
_PointerDrag = true;
}
void Start()
{
_Delai = DelaiReponse;
}
private void Update()
{
if (_PointerDown || _PointerDrag) // Timer Button Validation Hold
{
_PointerDownTimer += Time.deltaTime;
if (_PointerDownTimer >= _Delai)
{
_IsValidate = true;
}
}
}
}
and it works.
Thanks for your time, Frenchy

Related

In Unity, line of code keeps blocking video in WebGL?

I want to play a video in WebGL but it keeps blocking my video due to one line of code and I don't know why or how to "repair" it. When clicking on play, only one frame is shown and then it stops. (Entire code below).
The issue is this particular line in my Update function:
if (video.isPlaying)
{
if (!video.isPrepared) return;
videoSlider.value = (float)NTime; //This line here!!!
}
If not commented out, the video wont play, for whatever reason.
NTime, which seems to cause the issue, is:
video.time/ ((ulong)(video.frameCount / video.frameRate)) //video is videoPlayer
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Video;
using TMPro;
public class SliderVideo : MonoBehaviour
{
[SerializeField] VideoPlayer video;
[SerializeField] Slider videoSlider;
[SerializeField] Slider volumeSlider;
[SerializeField] Button playButton;
[SerializeField] RawImage fullScreenImage;
[SerializeField] RectTransform buttons;
[SerializeField] Vector3 buttonsPos;
Vector3 buttonsPosCache;
[SerializeField] TextMeshProUGUI buttonLanguage;
[SerializeField] GameObject disableButton;
[SerializeField] GameObject videoRectangle;
int cacheWidth, cacheHeight;
float videoWidth, videoHeight;
float videoWidthCache, videoHeightCache;
double videoTimeCache;
bool fullScreen;
float timerMouse;
public bool languageChange = false;
public string videoFileName;
public string videoFileNameEN;
public string videoFileNameDE;
//Start
private void Start()
{
playButton.image.sprite = Resources.LoadAll<Sprite>("icons")[25];
videoRectangle.SetActive(false);
videoHeight = fullScreenImage.gameObject.GetComponent<RectTransform>().sizeDelta.y;
videoWidth = fullScreenImage.gameObject.GetComponent<RectTransform>().sizeDelta.x;
buttonsPosCache = buttons.anchoredPosition;
}
//Update
private void Update()
{
if (video.isPlaying)
{
if (!video.isPrepared) return;
videoSlider.value = (float)NTime;
video.SetDirectAudioVolume(0, volumeSlider.value);
}
if (fullScreen)
{
if (Input.GetAxis("Mouse X") != 0 || Input.GetAxis("Mouse Y") != 0)
{
timerMouse = 0;
buttons.gameObject.SetActive(true);
}
else
{
timerMouse += Time.deltaTime;
if (timerMouse > 3)
{
timerMouse = 3;
buttons.gameObject.SetActive(false);
}
}
}
}
public ulong Duration
{
get { return (ulong)(video.frameCount / video.frameRate); }
}
public double VideoTime
{
get { return video.time; }
}
public double NTime
{
get { return VideoTime / Duration; }
}
//Prepare Method
public void LoadVideo(string source)
{
video.url = System.IO.Path.Combine(Application.streamingAssetsPath, source);
video.Prepare();
}
//Methods for Buttons
public void PlayVideo()
{
//if (!IsPrepared && IsPlaying) return ;
video.Play();
}
public void PauseVideo()
{
if (!video.isPlaying) return;
video.Pause();
}
public void SeekSlider()
{
video.time = (videoSlider.value * Duration);
}
public void PauseResume()
{
//if (!IsPrepared) return ;
videoRectangle.SetActive(true);
if (video.isPlaying)
{
playButton.image.sprite = Resources.LoadAll<Sprite>("icons")[25];
PauseVideo();
}
else if (!video.isPlaying)
{
playButton.image.sprite = Resources.LoadAll<Sprite>("icons")[24];
PlayVideo();
}
}
public void FullScreen()
{
if (!fullScreen)
{
disableButton.SetActive(false);
fullScreenImage.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(1920, 1920);
buttons.anchoredPosition = buttonsPos;
fullScreen = true;
}
else
{
disableButton.SetActive(true);
fullScreenImage.gameObject.GetComponent<RectTransform>().sizeDelta = new Vector2(videoWidth, videoHeight);
buttons.anchoredPosition = buttonsPosCache;
fullScreen = false;
}
}
public void ChangeVideoLanguage()
{
if (!languageChange)
{
buttonLanguage.text = "EN";
videoFileName = videoFileNameDE;
video.Stop();
playButton.image.sprite = Resources.LoadAll<Sprite>("icons")[25];
LoadVideo(videoFileName);
languageChange = true;
}
else
{
buttonLanguage.text = "DE";
videoFileName = videoFileNameEN;
video.Stop();
playButton.image.sprite = Resources.LoadAll<Sprite>("icons")[25];
LoadVideo(videoFileName);
languageChange = false;
}
}
}

I can't jump and move at the same time unity2d

i made 2d character and 3 ui buttons and they worked well
but the problem is when moving to the right or left by the ui buttons i can't jump however when jump from the ui button i can move to right and left
this is the script
public class PlayerWalk : MonoBehaviour {
private PlayerAnimation playerAnim;
private Rigidbody2D myBody;
private SpriteRenderer spriteRenderer;
public float speed = 7f;
public float jumpForce = 7f;
private bool moveLeft; // determine if we move left or right
private bool dontMove; // determine if we are moving or not
private bool canJump; // we will test if we can jump
void Start () {
playerAnim = GetComponent<PlayerAnimation>();
myBody = GetComponent<Rigidbody2D>();
dontMove = true;
}
void Update () {
//DetectInput();
HandleMoving();
}
void HandleMoving() {
if (dontMove) {
StopMoving();
} else {
if (moveLeft) {
MoveLeft();
} else if (!moveLeft) {
MoveRight();
}
}
} // handle moving
public void AllowMovement(bool movement) {
dontMove = false;
moveLeft = movement;
}
public void DontAllowMovement() {
dontMove = true;
}
public void Jump() {
if(canJump) {
myBody.velocity = new Vector2(myBody.velocity.x, jumpForce);
//myBody.AddForce(Vector2.right * jumpForce);
}
}
// PREVIOUS FUNCTIONS
public void MoveLeft() {
myBody.velocity = new Vector2(-speed, myBody.velocity.y);
playerAnim.ZombieWalk(true, true);
}
public void MoveRight() {
myBody.velocity = new Vector2(speed, myBody.velocity.y);
playerAnim.ZombieWalk(true, false);
}
public void StopMoving() {
playerAnim.ZombieStop();
myBody.velocity = new Vector2(0f, myBody.velocity.y);
}
void DetectInput() {
float x = Input.GetAxisRaw("Horizontal");
if (x > 0)
{
MoveRight();
}
else if (x < 0)
{
MoveLeft();
}
else
{
StopMoving();
}
}
void OnCollisionEnter2D(Collision2D collision) {
if(collision.gameObject.tag == "Ground") {
canJump = true;
}
}
void OnCollisionExit2D(Collision2D collision) {
if (collision.gameObject.tag == "Ground") {
canJump = false;
}
}
} // class
the 2d character moves well and there is no bugs or problems with scripts
Any help??
I don't know where is the problem??
**Note ** i used unity5.6
I would say onTriggerEnter2D instead of using onCollisionEnter2D would be a better option in this scenario. You can read more about that here.
https://answers.unity.com/questions/875770/ontriggerenter-or-oncollisionenter-1.html#:~:text=OnCollisionEnter%20is%20called%20when%20two,with%20%22IsTrigger%22%20set).
Did you try to debug the value of canJump while you are trying to move left or right?

Unity Ads Stuck in Loop

I have a test ad setup in my unity game. I am calling the IntAd function from the GameManager Script after the game is over. But the problem is when I click the close button in the ad, the ad reappears again and again. Please help me how can stop IntAd function after showing the ad.
public class AdsManager : MonoBehaviour
{
public static AdsManager instance;
private string playStoreID = "000000";
private string intAd = "video";
private string rewardedAd = "rewardedVideo";
private string bannerAd = "bannerAd";
public bool isTargrtPlayStore;
public bool isTestAd;
public static int start;
void Awake()
{
DontDestroyOnLoad(this.gameObject);
if (instance == null)
{
instance = this;
}
else
{
Destroy(this.gameObject);
}
}
private void Start()
{
InitializeAdvertisement();
}
private void InitializeAdvertisement()
{
if (isTargrtPlayStore)
{
Advertisement.Initialize(playStoreID, isTestAd);
return;
}
}
public void IntAd()
{
if (Advertisement.IsReady(intAd))
{
Advertisement.Show(intAd);
}
}
}
Here is GameManager Script-
public class GameManager : MonoBehaviour
{
public static GameManager instance;
public bool gameOver;
void Awake()
{
if (instance == null){
instance = this;
}
}
// Start is called before the first frame update
void Start()
{
gameOver = false;
}
// Update is called once per frame
void Update()
{
}
public void StartGame()
{
UiManager.instance.GameStart();
UiManager.instance.StartScore1();
ScoreManager.instance.startScore();
GameObject.Find("PlatformSpawner").GetComponent<PlatformSpawner>().StartSpawningPlatforms();
//AdsManager.instance.BannerAd();
}
public void GameOver()
{
UiManager.instance.GameOver();
ScoreManager.instance.stopScore();
gameOver = true;
AdsManager.instance.IntAd();
}
}
code to call GameOver function
void Update()
{
if (!started)
{
if (Input.GetMouseButtonDown(0))
{
rb.velocity = new Vector3(speed, 0, 0);
started = true;
GameManager.instance.StartGame();
}
}
if (!Physics.Raycast(transform.position, Vector3.down, 1f))
{
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
GameManager.instance.GameOver();
}
The code you have calling GameManager.GameOver() is inside of Update() so it's going to get called every frame, and if !Physics.Raycast(transform.position, Vector3.down, 1f) is always true when the game is over (and not just true once), then it'll end up calling GameManager.GameOver() every frame which lines up with the behaviour that you're seeing.
You could resolve this by adding !gameOver to your if statement, that way it'll only go into the if statement once at the end of your game, and then upon gamestart you could flip gameOver back to false.
if (!Physics.Raycast(transform.position, Vector3.down, 1f) && !gameOver)
{
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
GameManager.instance.GameOver();
}
Just do an if statement with a bool named GameEnd. Set it to false. Play the ad only if GameEnd is false. Rite after the ad instantiates, set GameEnd to true.
if (!Physics.Raycast(transform.position, Vector3.down, 1f))
{
bool GameEnd = false;
gameOver = true;
rb.velocity = new Vector3(0, -25f, 0);
Camera.main.GetComponent<CameraFollow>().gameOver = true;
if(! GameEnd)
{
GameManager.instance.GameOver();
GameEnd = true;
}
}

Why the OnMouseDown() event on Rigidbody does not fire?

There is a dynamic Rigidbody that can be launched with the mouse. But at some point, Rigidbody stops reacting to the mouse for some reason. Rigidbody's speed is 0.
To a rigidbody attached two Spring joints.
The only way to awaken the body is to disable and re-enable Spring Joints when debugging.
public class Ball : MonoBehaviour
{
private Rigidbody2D rigidbodyBall;
public SpringJoint2D[] springJoints;
private GameObject speed;
public static Ball instance = null;
#region Life Cycle
void Awake()
{
speed = GameObject.Find("Velocity");
springJoints = GetComponents<SpringJoint2D>();
rigidbodyBall = GetComponent<Rigidbody2D>();
gameManager = GameObject.Find("GameManager").GetComponent<GameManager>();
}
private bool clickedOn = false;
void Update()
{
if (clickedOn)
{
Dragging();
UIManager.instance.pauseButton.SetActive(false);
UIManager.instance.totalScoreUI.gameObject.SetActive(false);
}
else
{
UIManager.instance.pauseButton.SetActive(true);
UIManager.instance.totalScoreUI.gameObject.SetActive(true);
}
}
#endregion
#region Launcher
#region Mouse
void OnMouseDown()
{
SpringJointDeactivate();
clickedOn = true;
}
void OnMouseUp()
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
void Dragging()
{
Vector3 mouseWorldPointStart = transform.position;
Vector3 mouseWorldPoint = Camera.main.ScreenToWorldPoint(Input.mousePosition);
mouseWorldPoint.z = 0f;
if (Boundary.ballInBoundary)
{
transform.position = mouseWorldPoint;
float diffX = mouseWorldPoint.x - mouseWorldPointStart.x;
//TODO
for (int i = 0; i < springJoints.Length; i++)
{
springJoints[i].connectedAnchor = new Vector2(springJoints[i].connectedAnchor.x + diffX, springJoints[i].connectedAnchor.y);
}
}
else
{
Debug.Log("Another situation!");
Debug.Log(Boundary.ballInBoundary);
}
}
#endregion
public void SpringJointActivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = true;
}
}
public void SpringJointDeactivate()
{
foreach (SpringJoint2D joint in springJoints)
{
joint.enabled = false;
}
}
public Vector3[] GetSpringJointsConnectedAnchorCoord()
{
Vector3[] springJointsCoord = new[] { Vector3.zero, Vector3.zero };
for (int i = 0; i < springJoints.Length; i++)
{
springJointsCoord[i] = springJoints[i].connectedAnchor;
}
return springJointsCoord;
}
#endregion
public void SetKinematicState(bool kinematicState)
{
rigidbodyBall.isKinematic = kinematicState;
}
}
What is the reason for this? How can this be corrected?
Replaced OnMouseDown() with Input.GetMouseButtonDown(0) and everything worked out.
void Update()
{
if (Input.GetMouseButtonDown(0))
{
SpringJointDeactivate();
clickedOn = true;
}
if (Input.GetMouseButtonUp(0))
{
SpringJointActivate();
clickedOn = false;
SetKinematicState(false);
Invoke("SpringJointDeactivate", 0.1f);
}
}

Drag and Drop In ScrollRect (ScrollView) in Unity3D

I want to implement drag and drop on contents of scroll view.
The problem is when you try drag items in scroll view you can't scroll the view.
First, I've tried to implement drag and drop by IDragHandler, IBeginDragHandler, IEndDragHandle and IDropHandler interfaces. In a first sight, It worked pretty good but the problem was you can't scroll the ScrollRect.
I think the problem is because of overriding, When I use event triggers that the same as scroll rect like drag, the parent one don't work properly.
So after that, I've thought by myself and implement it by IPointerDown, IPointerUp interfaces and specific time for holding drag-gable UI in ScrollRect and if you don't hold it in specific time the scrolling work well.
But the problem is by enabling DragHandler script that I wrote before the OnDrag, OnBeginDrag and OnEndDrag functions doesn't work when time of holding ended.
First I want to know there is any way to call these functions ?
Second is there any way to implement drag and drop UI without using drag interfaces ?
DragHandler :
using System;
using UnityEngine;
using UnityEngine.EventSystems;
public class DragHandler : MonoBehaviour, IDragHandler, IBeginDragHandler, IEndDragHandler
{
public static GameObject itemBeingDragged;
private Vector3 startPos;
private Transform startParent;
DragHandler dragHandler;
public void Awake()
{
dragHandler = GetComponent<DragHandler>();
}
public void OnBeginDrag(PointerEventData eventData)
{
Debug.Log("Begin");
itemBeingDragged = gameObject;
startPos = transform.position;
startParent = transform.parent;
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("Drag");
transform.position = Input.mousePosition;
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("End");
itemBeingDragged = null;
if (transform.parent == startParent)
{
dragHandler.enabled = false;
transform.SetParent(startParent);
transform.position = startPos;
}
}
}
ScrollRectController:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class ScrollRectController : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
{
public float holdTime;
public float maxVelocity;
private Transform scrollRectParent;
private DragHandler dragHandler;
private ScrollRect scrollRect;
private float timer;
private bool isHolding;
void Awake()
{
scrollRectParent = GameObject.FindGameObjectWithTag("rec_dlg").transform;
dragHandler = GetComponent<DragHandler>();
dragHandler.enabled = false;
}
// Use this for initialization
void Start()
{
timer = holdTime;
}
// Update is called once per frame
void Update()
{
}
public void OnPointerDown(PointerEventData eventData)
{
Debug.Log("Down");
scrollRect = scrollRectParent.GetComponent<ScrollRect>();
isHolding = true;
StartCoroutine(Holding());
}
public void OnPointerUp(PointerEventData eventData)
{
Debug.Log("Up");
isHolding = false;
}
IEnumerator Holding()
{
while (timer > 0)
{
//if (scrollRect.velocity.x >= maxVelocity)
//{
// isHolding = false;
//}
if (!isHolding)
{
timer = holdTime;
yield break;
}
timer -= Time.deltaTime;
Debug.Log(timer);
yield return null;
}
dragHandler.enabled = true;
//dragHandler.OnBeginDrag();
}
}
Slot:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Slot : MonoBehaviour, IDropHandler
{
public void OnDrop(PointerEventData eventData)
{
DragHandler.itemBeingDragged.transform.SetParent(transform);
}
}
Answer:
I wrote some codes that handle drag and drop in scrollRect(scrollView) without using DragHandler interfaces.
DragHandler:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragHandler : MonoBehaviour, IPointerExitHandler
{
public static GameObject itemBeingDragged;
public static bool isCustomerDragged;
public Transform customerScrollRect;
public Transform dragParent;
public float holdTime;
public float maxScrollVelocityInDrag;
private Transform startParent;
private ScrollRect scrollRect;
private float timer;
private bool isHolding;
private bool canDrag;
private bool isPointerOverGameObject;
private CanvasGroup canvasGroup;
private Vector3 startPos;
public Transform StartParent
{
get { return startParent; }
}
public Vector3 StartPos
{
get { return startPos; }
}
void Awake()
{
canvasGroup = GetComponent<CanvasGroup>();
}
// Use this for initialization
void Start()
{
timer = holdTime;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
//Debug.Log("Mouse Button Down");
scrollRect = customerScrollRect.GetComponent<ScrollRect>();
isPointerOverGameObject = true;
isHolding = true;
StartCoroutine(Holding());
}
}
if (Input.GetMouseButtonUp(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
//Debug.Log("Mouse Button Up");
isHolding = false;
if (canDrag)
{
itemBeingDragged = null;
isCustomerDragged = false;
if (transform.parent == dragParent)
{
canvasGroup.blocksRaycasts = true;
transform.SetParent(startParent);
transform.localPosition = startPos;
}
canDrag = false;
timer = holdTime;
}
}
}
if (Input.GetMouseButton(0))
{
if (EventSystem.current.currentSelectedGameObject == gameObject)
{
if (canDrag)
{
//Debug.Log("Mouse Button");
transform.position = Input.mousePosition;
}
else
{
if (!isPointerOverGameObject)
{
isHolding = false;
}
}
}
}
}
public void OnPointerExit(PointerEventData eventData)
{
isPointerOverGameObject = false;
}
IEnumerator Holding()
{
while (timer > 0)
{
if (scrollRect.velocity.x >= maxScrollVelocityInDrag)
{
isHolding = false;
}
if (!isHolding)
{
timer = holdTime;
yield break;
}
timer -= Time.deltaTime;
//Debug.Log("Time : " + timer);
yield return null;
}
isCustomerDragged = true;
itemBeingDragged = gameObject;
startPos = transform.localPosition;
startParent = transform.parent;
canDrag = true;
canvasGroup.blocksRaycasts = false;
transform.SetParent(dragParent);
}
public void Reset()
{
isHolding = false;
canDrag = false;
isPointerOverGameObject = false;
}
}
Some explanation for this piece of code :
Your draggable UI element need intractable option, for me, I used button.
You need to attach this script to your draggable item.
Also you need add Canvas Group component.
customerScrollRect is a ScrollRect parent of your items.
dragParent can be a empty GameObject which is used because of mask of view port.
Slot:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
public class Slot : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler
{
bool isEntered;
public void OnPointerEnter(PointerEventData eventData)
{
isEntered = true;
}
public void OnPointerExit(PointerEventData eventData)
{
isEntered = false;
}
void Update()
{
if (Input.GetMouseButtonUp(0))
{
if (isEntered)
{
if (DragHandler.itemBeingDragged)
{
GameObject draggedItem = DragHandler.itemBeingDragged;
DragHandler dragHandler = draggedItem.GetComponent<DragHandler>();
Vector3 childPos = draggedItem.transform.position;
//Debug.Log("On Pointer Enter");
draggedItem.transform.SetParent(dragHandler.StartParent);
draggedItem.transform.localPosition = dragHandler.StartPos;
draggedItem.transform.parent.SetParent(transform);
draggedItem.transform.parent.position = childPos;
isEntered = false;
}
}
}
}
}
Some explanation for this script:
1.Attach the script to the dropped item.
The easiest solution for this problem is actually to manually call the ScrollRect's events IF the user hasn't pressed long enough using ExecuteEvents.Execute. This solution has the least amount of additional code.
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragAndDropHandler : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerExitHandler, IDragHandler, IBeginDragHandler, IEndDragHandler
{
// Don't forget to set this to TRUE or expose it to the Inspector else it will always be false and the script will not work
public bool Draggable { get; set; }
private bool draggingSlot;
[SerializeField] private ScrollRect scrollRect;
public void OnPointerDown(PointerEventData eventData)
{
if (!Draggable)
{
return;
}
StartCoroutine(StartTimer());
}
public void OnPointerExit(PointerEventData eventData)
{
StopAllCoroutines();
}
public void OnPointerUp(PointerEventData eventData)
{
StopAllCoroutines();
}
private IEnumerator StartTimer()
{
yield return new WaitForSeconds(0.5f);
draggingSlot = true;
}
public void OnBeginDrag(PointerEventData eventData)
{
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.beginDragHandler);
}
public void OnDrag(PointerEventData eventData)
{
if (draggingSlot)
{
//DO YOUR DRAGGING HERE
} else
{
//OR DO THE SCROLLRECT'S
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.dragHandler);
}
}
public void OnEndDrag(PointerEventData eventData)
{
ExecuteEvents.Execute(scrollRect.gameObject, eventData, ExecuteEvents.endDragHandler);
if (draggingSlot)
{
//END YOUR DRAGGING HERE
draggingSlot = false;
}
}
}
I've managed to find an easier solution.
Maybe it must be customized by special needs, but if you put this script on your items and make the setup, it should work.
It's not easy from a prefab, but I let a controller make this.
I find all UIElementDragger inside a specified GameObject and add the needed GO instances programmatically.
But can use this code out of the box if you don't use prefabs.
using UnityEngine;
using UnityEngine.EventSystems;
public class UIElementDragger : MonoBehaviour, IPointerUpHandler, IPointerDownHandler
{
/// <summary>
/// Offset in pixels horizontally (positive to right, negative to left)
/// </summary>
[Range(40, 100)]
public float offsetX = 40;
/// <summary>
/// Offset in pixels vertically (positive to right, negative to left)
/// </summary>
[Range(40, 100)]
public float offsetY = 40;
/// <summary>
/// The Panel where the item will set as Child to during drag
/// </summary>
public Transform parentRect;
/// <summary>
/// The GameObject where the item is at start
/// </summary>
public Transform homeWrapper;
/// <summary>
/// The Object where the mouse must be when pointer is up, to put it in this panel
/// </summary>
public Transform targetRect;
/// <summary>
/// The GameObject where the item should live after dropping
/// </summary>
public Transform targetWrapper;
private int siblingIndex;
private bool dragging;
private void Start()
{
siblingIndex = transform.GetSiblingIndex();
}
private void Update()
{
if (dragging)
{
transform.position = new Vector2(Input.mousePosition.x + offsetX, Input.mousePosition.y + offsetY);
}
}
public void OnPointerDown(PointerEventData eventData)
{
transform.parent = parentRect;
dragging = true;
}
public void OnPointerUp(PointerEventData eventData)
{
if (eventData.pointerCurrentRaycast.gameObject.transform.IsChildOf(targetRect))
{
transform.parent = targetWrapper;
}
else
{
transform.parent = homeWrapper;
transform.SetSiblingIndex(siblingIndex);
}
dragging = false;
}
}
Here my solution, thank all.
I have to use a fake instance to keep the object over even if you move it down the list. I post a vertical and a horizontal solution. I hope it help
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
public class DragController : MonoBehaviour, IPointerDownHandler, IDragHandler, IPointerUpHandler
{
private RectTransform currentTransform;
private GameObject instancePrefab;
private GameObject mainContent;
private Vector3 initialePosition;
private int totalChild;
void Awake()
{
currentTransform = this.GetComponent<RectTransform>();
mainContent = currentTransform.parent.gameObject;
}
public void OnPointerDown(PointerEventData eventData)
{
initialePosition = currentTransform.position;
totalChild = mainContent.transform.childCount;
if (instancePrefab == null)
{
instancePrefab = Instantiate(this.gameObject, mainContent.transform.parent.transform);
instancePrefab.GetComponent<Image>().enabled = false;
}
}
public void OnDrag(PointerEventData eventData)
{
currentTransform.position = new Vector3(eventData.position.x, currentTransform.position.y, currentTransform.position.z);
if (instancePrefab != null)
{
instancePrefab.GetComponent<Image>().enabled = true;
currentTransform.GetComponent<Image>().enabled = false;
instancePrefab.transform.position = currentTransform.position;
}
for (int i = 0; i < totalChild; i++)
{
if (i != currentTransform.GetSiblingIndex())
{
Transform otherTransform = mainContent.transform.GetChild(i);
int distance = (int)Vector3.Distance(currentTransform.position, otherTransform.position);
if (distance <= 20)
{
Vector3 otherTransformOldPosition = otherTransform.position;
// Vertical
/*otherTransform.position = new Vector3(otherTransform.position.x, initialePosition.y,
otherTransform.position.z);
currentTransform.position = new Vector3(currentTransform.position.x, otherTransformOldPosition.y,
currentTransform.position.z);*/
// Horizontal
otherTransform.position = new Vector3(initialePosition.x, otherTransform.position.y,
otherTransform.position.z);
currentTransform.position = new Vector3(otherTransformOldPosition.x, currentTransform.position.y,
currentTransform.position.z);
currentTransform.SetSiblingIndex(otherTransform.GetSiblingIndex());
initialePosition = currentTransform.position;
}
}
}
}
public void OnPointerUp(PointerEventData eventData)
{
currentTransform.position = initialePosition;
instancePrefab.GetComponent<Image>().enabled = false;
currentTransform.GetComponent<Image>().enabled = true;
Destroy(instancePrefab);
instancePrefab = null;
}
}
You can just manually call ScrollRect events, because they are public. Smthing like this:
public void OnDrag(PointerEventData eventData)
{
_scrollRect.OnDrag(eventData);
}