How to Translate/move with limitation

I am a beginner in both Unity workflow and programming, and working on a project for mobile.
Managing touches is a bit tough, so I ended up using LeanTouch plugin to easily manage touches. The plugin has provided many examples and I used the one to tranlate/move object when user swipes the screen.
In the screenshot, I make 3 sprites that are children of an empty to move these sprites. The sprites will be like buttons that will direct to other scenes.


The problem is that I don’t know how to modify the script from the examples. It works fine, but what I want is to limit the movement so it won’t move aymore if it reaches some point. In the scene, I don’t want to make the sprites move in the Y axis, and limit the X axis at some point.

Here is the code of LeanTranslate:

using UnityEngine;

namespace Lean.Touch
{
    // This script allows you to transform the current GameObject
    public class LeanTranslate : MonoBehaviour
    {
        [Tooltip("Ignore fingers with StartedOverGui?")]
        public bool IgnoreGuiFingers = true;

        [Tooltip("Ignore fingers if the finger count doesn't match? (0 = any)")]
        public int RequiredFingerCount;

        [Tooltip("Does translation require an object to be selected?")]
        public LeanSelectable RequiredSelectable;

        [Tooltip("The camera the translation will be calculated using (default = MainCamera)")]
        public Camera Camera;

#if UNITY_EDITOR
        protected virtual void Reset()
        {
            Start();
        }
#endif

        protected virtual void Start()
        {
            if (RequiredSelectable == null)
            {
                RequiredSelectable = GetComponent<LeanSelectable>();
            }
        }

        protected virtual void Update()
        {
            // If we require a selectable and it isn't selected, cancel translation
            if (RequiredSelectable != null && RequiredSelectable.IsSelected == false)
            {
                return;
            }

            // Get the fingers we want to use
            var fingers = LeanTouch.GetFingers(IgnoreGuiFingers, RequiredFingerCount, RequiredSelectable);

            // Calculate the screenDelta value based on these fingers
            var screenDelta = LeanGesture.GetScreenDelta(fingers);

            // Perform the translation
            Translate(screenDelta);
        }

        private void Translate(Vector2 screenDelta)
        {
            // If camera is null, try and get the main camera, return true if a camera was found
            if (LeanTouch.GetCamera(ref Camera) == true)
            {
                // Screen position of the transform
                var screenPosition = Camera.WorldToScreenPoint(transform.position);

                // Add the deltaPosition
                screenPosition += (Vector3)screenDelta;

                // Convert back to world space
                transform.position = Camera.ScreenToWorldPoint(screenPosition);
            }
        }
    }
}

Please help.

Hey,

I would suggest adding a test to the Translate function to check if the screenDelta has a change in the Y-direction and another check if it moves the X-direction too much.

Something like this should work. This stops movement in the Y-direction and stops the user moving further than 100 in the X-direction

     private void Translate(Vector2 screenDelta)
        {
            // If camera is null, try and get the main camera, return true if a camera was found
            if (LeanTouch.GetCamera(ref Camera) == true)
            {
                // Screen position of the transform
                var screenPosition = Camera.WorldToScreenPoint(transform.position);

                if (screenPosition.x + screenDelta.x < 100 && screenDelta.y == 0) {
                    // Add the deltaPosition
                    screenPosition += (Vector3)screenDelta;
                }
                // Convert back to world space
                transform.position = Camera.ScreenToWorldPoint(screenPosition);
            }
        }

Let me know if you have any more questions.

What I understand is the Camera.WorldToScreenPoint(transform.position) convert transform.position into value in pixels and I tested it using Debug.Log(screenposition) and it got (580.3, 960.0, 0.0) as the object’s default position in pixels.
So when I used your code, it just can;t be moved, because the value of X is already beyond 100 at start. So I modified your code to:

if (screenPosition.x + screenDelta.x < 1000 && screenPosition.y == 960) {
                    // Add the deltaPosition
                    screenPosition += (Vector3)screenDelta;
                }

And the code makes it can’t be moved after I moved it on Y axis a bit, then I tried to understand this and it makes sense, because your code prevents the screenPosition += (Vector3)screenDelta; to be executed if Y is not 960. So intially when the Y axis is still 960 (default position in pixels), it passed the if condition and let me move the object in Y axis, and then in the next frame, the object’s Y is no longer 960 and then stops screenPosition += (Vector3)screenDelta; to be executed and the result is it stops/prevents me to move the object completely.
As I tested to modify the code, it stops me to translate the object if I remove the screenPosition += (Vector3)screenDelta;
The truth is I can’t understand the screenPosition += (Vector3)screenDelta; part, i don’t know how that works and what calculation it does, I know that screenPosition is Vector2, and so is screenDelta. So what is that (Vector3) after +=?

I think I found the solution after these days of frustation. :smile:
It’s to Clamp() the screenposition’s X and Y separately before we set the transform.position in the end of Translate(), so the value of screenPosition won’t go beyond the desired value.

private void Translate(Vector2 screenDelta)
        {
            // If camera is null, try and get the main camera, return true if a camera was found
            if (LeanTouch.GetCamera(ref Camera) == true)
            {
                // Screen position of the transform
                var screenPosition = Camera.WorldToScreenPoint(transform.position);

                // Add the deltaPosition
                screenPosition += (Vector3)screenDelta;

                screenPosition.y = Mathf.Clamp(screenPosition.y, 960, 960);
                screenPosition.x = Mathf.Clamp(screenPosition.x, 581, 2200);
//                Debug.Log ("screenPosition.x = " + screenPosition.x);

                // Convert back to world space
                transform.position = Camera.ScreenToWorldPoint(screenPosition);
            }
        }

But, since I used the clamp value in pixels, I am not sure if it will fit in different resolutions, because I tested it in 1080x1920 resolution. So right now, I don’t tag this post as [SOLVED] yet, so i’m going to test it in my own device that only has 480x854 LOL :stuck_out_tongue:

As I predicted, it turns out it works on certain resolution only, in my case it is 1080x1920. So when I tried the app on my device (that has smaller res), the object moved so far from the initial position I wanted.

Then I thought to Clamp the transform.position’s X and Y as below:

private void Translate(Vector2 screenDelta)
        {
            // If camera is null, try and get the main camera, return true if a camera was found
            if (LeanTouch.GetCamera(ref Camera) == true)
            {
                // Screen position of the transform
                var screenPosition = Camera.WorldToScreenPoint(transform.position);

                // Add the deltaPosition
                screenPosition += (Vector3)screenDelta;

                transform.position.y = Mathf.Clamp(transform.position.y, 0f, 0f);
                transform.position.x = Mathf.Clamp(transform.position.x, 0.21f, 8.7f);

                // Convert back to world space
                transform.position = Camera.ScreenToWorldPoint(screenPosition);
            }
        }

And turns out it got me an error:
3280331--253735--LeanTranslate with Clamp(transform.position) ERROR.png

Anybody can help, please?

Replace

transform.position.y = Mathf.Clamp(transform.position.y, 0f, 0f);
transform.position.y = Mathf.Clamp(transform.position.y, 0.21f, 8.7f);

By

float y = Mathf.Clamp(transform.position.y, 0f, 0f);
float x = Mathf.Clamp(transform.position.x, 0.21f, 8.7f);
transform.position = new Vector3(x, y, transform.position.z);

You cannot modify the fields of transform.position, if you want to modify it, you need to set it to a new value

Just to provide clarification on this, this is the compiler stopping you from writing a bug that can be hard to track down.

Vector3 is a struct, which is a value type.

This means if you were to try to write to transform.position.x, you’re actually setting the x value on a copy of the struct returned by transform.position. The copy is then discarded, the original is left untouched, and you’re left scratching your head why your code didn’t seem to work.

Its doesn’t work properly in AR Core. I want some solution about for it. Because, AR Core Camera malfunctioning.

maybe I can help with the modified code.
the result works fine, i can move the object without moving the value of Y.

but for lean that I use is the latest version.

for disY I use float variable = 0.5f, you can edit Y in hire
and work fine for AR

protected virtual void Translate(Vector2 screenDelta)
        {
            // Make sure the camera exists
            var camera = LeanTouch.GetCamera(Camera, gameObject);

            if (camera != null)
            {

                // Screen position of the transform
                var screenPoint = camera.WorldToScreenPoint(transform.position);

           
                    // Add the deltaPosition
                    screenPoint += (Vector3)screenDelta;
                
                    screenPoint.Set(screenPoint.x,
                        screenPoint.y,
                        screenPoint.z);
               
            

                // Convert back to world space

                Vector3 lastPost = camera.ScreenToWorldPoint(new Vector3(screenPoint.x, screenPoint.y, screenPoint.z));
                
                transform.position = new Vector3(lastPost.x,distY,lastPost.z);
               // transform.position = camera.ScreenToWorldPoint(screenPoint);

            }

I hope it helped you :slight_smile:

It was not…help me please,
I just want motion on the x axis