The operation of the toggle switch is to move between the lower and upper edges of the menu bar on the canvas. These edges will be determined by the height of the panel itself. And so, after completing the configuration of the canvas elements, you can proceed to the program part.
Let's create a new Custom Slider script inherited from the UIBehaviour class, this class can be found by connecting the EventSystem library.
- using UnityEngine.EventSystem;
- public sealed class CustomSlider : UIBehaviour {}
Далее объявим новую переменную fillRect, которая будет ссылаться на RectTransform панели меню.
- using UnityEngine.EventSystem;
- public sealed class CustomSlider : UIBehaviour {
- public RectTransform fillRect;
- }
Now add the
Custom Slider script to the toggle switch and place the menu bar in the fillRect field.
Since we will move the toggle switch itself across the canvas by dragging it across the screen, we will need to use additional tools for handling touch events. To do this, the UI system has a dozen interfaces that will help process every user action, including touching, moving, clicking, and so on. In this example, we will need only three of them, these are IBeginDragHandler – to handle the drag start event, IDragHandler - to handle the drag itself, and IEndDragHandler - to handle the end of dragging the element.
We inherit the Custom Slider script from each of the three selected interfaces and then implement all their methods.
- using UnityEngine.EventSystem;
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- public void OnBeginDrag(PointerEventData eventData) {}
- public void OnDrag(PointerEventData eventData) {}
- public void OnEndDrag(PointerEventData eventData) {}
- }
The OnBeginDrag method will work before dragging the toggle switch, the onDrag method will handle the dragging process itself, and the OnEndDrag method will work after we finish dragging the element.
Each method takes a PointerEventData parameter, this class contains a lot of useful data from each event, but we will only need two of them: this is the camera from which the touch event was received and the touch position itself.
To check the script's operability, let's try to move the toggle switch in the onDrag method. To do this, you will only need to translate the touch position on the screen to the world point on the stage, and then to the local point relative to the canvas, it looks like this:
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- public void OnBeginDrag(PointerEventData eventData) {}
- public void OnDrag(PointerEventData eventData) {
- Camera eventCam = eventData.pressEventCamera;
- Vector2 worldPoint = eventCam.ScreenToWorldPoint(eventData.position);
- Vector2 localPoint = this.canvas.transform.InverseTransformPoint(worldPoint);
- this.transform.localPosition = localPoint;
- }
- public void OnEndDrag(PointerEventData eventData) {}
- }
Having obtained the local position of the localPoint using the InverseTransformPoint Transform canvas method, we apply these coordinates of the toggle switch Transform. Now you can start and try to “move” the toggle switch on the screen.
Great, everything works – events are processed correctly, you can continue working with the script.
To begin with, we will erase everything that we wrote in the onDrag method and add a few new variables: canvasRect and RectTransform, which will point to the canvas and toggle switch Transforms.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- public void OnBeginDrag(PointerEventData eventData) {}
- public void OnDrag(PointerEventData eventData) {}
- public void OnEndDrag(PointerEventData eventData) {}
- }
Next, we will need to store the height of the menu bar in the fill Height variable, the height of the imageHeight toggle switch image, the lower limit in the minPosY variable, the upper limit in maxPosY and the current toggle switch height in the targetPosY variable.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
-
- public RectTransform fillRect;
-
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, imageHeight, minPosY, maxPosY, targetPosY;
-
- public void OnBeginDrag(PointerEventData eventData) {}
- public void OnDrag(PointerEventData eventData) {}
- public void OnEndDrag(PointerEventData eventData) {}
-
- }
These variables will be enough for us to start. Next, in the Start method, we will collect data.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- protected override void Start() {}
- /*…остальной код…*/
- }
Let's start by defining the variables Transform canvas and toggle switch. In order to find the canvas, we will use the GetComponentInParent method.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- protected override void Start() {
- Canvas canvas = GetComponentInParent<Canvas>();
- this.canvasRect = canvas.transform as RectTransform;
- this.rectTransform = this.transform as RectTransform;
- }
- /*…остальной код…*/
- }
Next, in the Start method, we will determine the dimensions of the menu bar and toggle switch, but we will do this in two different ways.
The fact is that the toggle switch in the settings of the RectTransform component specifies its length and height (Width and Height), and the menu bar only has left, top, right and bottom margins (Left, top, right and bottom), that is, the panel will always, regardless of the size of the screen, fill the maximum of the parent space (in this case, the entire canvas). Therefore, it will not work to find out the dimensions of the panel through the length and height, like a toggle switch, for this you will have to use a different approach, namely, to find the location of the edges of the panel on the canvas.
And so, let's start with the height of the toggle switch, everything is simple here – we use the sizeDelta property of its Transform.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- protected override void Start() {
- Canvas canvas = GetComponentInParent<Canvas>();
- this.canvasRect = canvas.transform as RectTransform;
- this.rectTransform = this.transform as RectTransform;
- this.imageHeight = this.rectTransform.sizeDelta.y;
- }
- /*…остальной код…*/
- }
To find the edges of the menu bar, we need a small array of Vector3 vectors and the GetLocalCorners method, which will return all four corners of the Transform panel.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- protected override void Start() {
- Canvas canvas = GetComponentInParent<Canvas>();
- this.canvasRect = canvas.transform as RectTransform;
- this.rectTransform = this.transform as RectTransform;
- this.imageHeight = this.rectTransform.sizeDelta.y;
- Vector3[] fillCorners = new Vector3[4];
- this.fillRect.GetLocalCorners(fillCorners);
- }
- /*…остальной код…*/
- }
In general, all corners of any UI element are arranged clockwise starting from the lower left edge of the element.
Now, using the edges of the panel, we will determine its dimensions, as well as the lower and upper limits.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- protected override void Start() {
- Canvas canvas = GetComponentInParent<Canvas>();
- this.canvasRect = canvas.transform as RectTransform;
- this.rectTransform = this.transform as RectTransform;
- this.imageHeight = this.rectTransform.sizeDelta.y;
- Vector3[] fillCorners = new Vector3[4];
- this.fillRect.GetLocalCorners(fillCorners);
- this.fillHeight = Mathf.Abs(fillCorners[0].y * 2f);
- this.maxPosY = fillCorners[0].y + this.imageHeight / 2f;
- this.minPosY = fillCorners[1].y – this.imageHeight / 2f;
- }
- /*…остальной код…*/
- }
For the fillHeight height, we use the lower left corner of the panel under the index 0 of the fillCorners array multiplied by 2. The lower limit of minPosY will be located in the lower left corner of the panel, the upper limit of maxPosY - in the upper left corner, respectively.
That's it, after executing the Start method, we will get all the necessary data about the panel and toggle switch elements.
The very movement of the toggle switch will now be handled in the Update method, since, unlike the onDrag method, the Update method always works, and not only when we perform the "drag" action. Therefore, we will add a new Update method, and two additional methods for handling the movement of the updatePosition toggle switch and filling the UpdateFill panel.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- /*…остальной код…*/
- private void Update() {
- UpdateFill();
- UpdatePosition();
- }
- private void UpdateFill() {}
- private void UpdatePosition() {}
- /*…остальной код…*/
- }
To move the toggle switch, we will use the variable target PosY, which we will fill in the Ondraw method.
- public sealed class CustomSlider : UIBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler {
- public RectTransform fillRect;
- private RectTransform canvasRect, rectTransform;
- private float fillHeight, minPosY, maxPosY, imageHeight, targetPosY;
- /*…остальной код…*/
- private void Update() {
- UpdateFill();
- UpdatePosition();
- }
- private void UpdateFill() {}
- private void UpdatePosition() {}
- public void OnDrag(PointerEventData eventData) {
- Camera eventCam = eventData.pressEventCamera;
- Vector2 worldPoint = eventCam.ScreenToWorldPoint(eventData.position);
- Vector2 localPoint = this.canvasRect.InverseTransformPoint(worldPoint);
- this.targetPosY = localPoint.y;
- }
- /*…остальной код…*/
- }