Search Unity

How to Translate/move with limitation

Discussion in 'Scripting' started by yassir_amry, Nov 6, 2017.

  1. yassir_amry

    yassir_amry

    Joined:
    Oct 29, 2017
    Posts:
    5
    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.
    3 Sprites.png
    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:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Lean.Touch
    4. {
    5.     // This script allows you to transform the current GameObject
    6.     public class LeanTranslate : MonoBehaviour
    7.     {
    8.         [Tooltip("Ignore fingers with StartedOverGui?")]
    9.         public bool IgnoreGuiFingers = true;
    10.  
    11.         [Tooltip("Ignore fingers if the finger count doesn't match? (0 = any)")]
    12.         public int RequiredFingerCount;
    13.  
    14.         [Tooltip("Does translation require an object to be selected?")]
    15.         public LeanSelectable RequiredSelectable;
    16.  
    17.         [Tooltip("The camera the translation will be calculated using (default = MainCamera)")]
    18.         public Camera Camera;
    19.  
    20. #if UNITY_EDITOR
    21.         protected virtual void Reset()
    22.         {
    23.             Start();
    24.         }
    25. #endif
    26.  
    27.         protected virtual void Start()
    28.         {
    29.             if (RequiredSelectable == null)
    30.             {
    31.                 RequiredSelectable = GetComponent<LeanSelectable>();
    32.             }
    33.         }
    34.  
    35.         protected virtual void Update()
    36.         {
    37.             // If we require a selectable and it isn't selected, cancel translation
    38.             if (RequiredSelectable != null && RequiredSelectable.IsSelected == false)
    39.             {
    40.                 return;
    41.             }
    42.  
    43.             // Get the fingers we want to use
    44.             var fingers = LeanTouch.GetFingers(IgnoreGuiFingers, RequiredFingerCount, RequiredSelectable);
    45.  
    46.             // Calculate the screenDelta value based on these fingers
    47.             var screenDelta = LeanGesture.GetScreenDelta(fingers);
    48.  
    49.             // Perform the translation
    50.             Translate(screenDelta);
    51.         }
    52.  
    53.         private void Translate(Vector2 screenDelta)
    54.         {
    55.             // If camera is null, try and get the main camera, return true if a camera was found
    56.             if (LeanTouch.GetCamera(ref Camera) == true)
    57.             {
    58.                 // Screen position of the transform
    59.                 var screenPosition = Camera.WorldToScreenPoint(transform.position);
    60.  
    61.                 // Add the deltaPosition
    62.                 screenPosition += (Vector3)screenDelta;
    63.  
    64.                 // Convert back to world space
    65.                 transform.position = Camera.ScreenToWorldPoint(screenPosition);
    66.             }
    67.         }
    68.     }
    69. }
    Please help.
     
  2. Mojachieee

    Mojachieee

    Joined:
    Jul 4, 2017
    Posts:
    49
    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

    Code (CSharp):
    1.      private void Translate(Vector2 screenDelta)
    2.         {
    3.             // If camera is null, try and get the main camera, return true if a camera was found
    4.             if (LeanTouch.GetCamera(ref Camera) == true)
    5.             {
    6.                 // Screen position of the transform
    7.                 var screenPosition = Camera.WorldToScreenPoint(transform.position);
    8.  
    9.                 if (screenPosition.x + screenDelta.x < 100 && screenDelta.y == 0) {
    10.                     // Add the deltaPosition
    11.                     screenPosition += (Vector3)screenDelta;
    12.                 }
    13.                 // Convert back to world space
    14.                 transform.position = Camera.ScreenToWorldPoint(screenPosition);
    15.             }
    16.         }
    Let me know if you have any more questions.
     
  3. yassir_amry

    yassir_amry

    Joined:
    Oct 29, 2017
    Posts:
    5
    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:
    Code (CSharp):
    1.  
    2. if (screenPosition.x + screenDelta.x < 1000 && screenPosition.y == 960) {
    3.                     // Add the deltaPosition
    4.                     screenPosition += (Vector3)screenDelta;
    5.                 }
    6.  
    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 +=?
     
  4. yassir_amry

    yassir_amry

    Joined:
    Oct 29, 2017
    Posts:
    5
    I think I found the solution after these days of frustation. :D
    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.

    Code (CSharp):
    1. private void Translate(Vector2 screenDelta)
    2.         {
    3.             // If camera is null, try and get the main camera, return true if a camera was found
    4.             if (LeanTouch.GetCamera(ref Camera) == true)
    5.             {
    6.                 // Screen position of the transform
    7.                 var screenPosition = Camera.WorldToScreenPoint(transform.position);
    8.  
    9.                 // Add the deltaPosition
    10.                 screenPosition += (Vector3)screenDelta;
    11.  
    12.                 screenPosition.y = Mathf.Clamp(screenPosition.y, 960, 960);
    13.                 screenPosition.x = Mathf.Clamp(screenPosition.x, 581, 2200);
    14. //                Debug.Log ("screenPosition.x = " + screenPosition.x);
    15.  
    16.                 // Convert back to world space
    17.                 transform.position = Camera.ScreenToWorldPoint(screenPosition);
    18.             }
    19.         }
    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 :p
     
  5. yassir_amry

    yassir_amry

    Joined:
    Oct 29, 2017
    Posts:
    5
    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:
    Code (CSharp):
    1. private void Translate(Vector2 screenDelta)
    2.         {
    3.             // If camera is null, try and get the main camera, return true if a camera was found
    4.             if (LeanTouch.GetCamera(ref Camera) == true)
    5.             {
    6.                 // Screen position of the transform
    7.                 var screenPosition = Camera.WorldToScreenPoint(transform.position);
    8.  
    9.                 // Add the deltaPosition
    10.                 screenPosition += (Vector3)screenDelta;
    11.  
    12.                 transform.position.y = Mathf.Clamp(transform.position.y, 0f, 0f);
    13.                 transform.position.x = Mathf.Clamp(transform.position.x, 0.21f, 8.7f);
    14.  
    15.                 // Convert back to world space
    16.                 transform.position = Camera.ScreenToWorldPoint(screenPosition);
    17.             }
    18.         }
    And turns out it got me an error:
    LeanTranslate with Clamp(transform.position) ERROR.png

    Anybody can help, please?
     
  6. Enyss

    Enyss

    Joined:
    Oct 4, 2016
    Posts:
    7
    Replace

    Code (csharp):
    1. transform.position.y = Mathf.Clamp(transform.position.y, 0f, 0f);
    2. transform.position.y = Mathf.Clamp(transform.position.y, 0.21f, 8.7f);
    By

    Code (csharp):
    1. float y = Mathf.Clamp(transform.position.y, 0f, 0f);
    2. float x = Mathf.Clamp(transform.position.x, 0.21f, 8.7f);
    3. 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
     
  7. BlackPete

    BlackPete

    Joined:
    Nov 16, 2016
    Posts:
    970
    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.
     
  8. SyedImranUnity

    SyedImranUnity

    Joined:
    Apr 4, 2018
    Posts:
    16
    Its doesn't work properly in AR Core. I want some solution about for it. Because, AR Core Camera malfunctioning.
     
  9. rifqi6969

    rifqi6969

    Joined:
    Dec 8, 2016
    Posts:
    1
    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

    Code (CSharp):
    1. protected virtual void Translate(Vector2 screenDelta)
    2.         {
    3.             // Make sure the camera exists
    4.             var camera = LeanTouch.GetCamera(Camera, gameObject);
    5.  
    6.             if (camera != null)
    7.             {
    8.  
    9.                 // Screen position of the transform
    10.                 var screenPoint = camera.WorldToScreenPoint(transform.position);
    11.  
    12.            
    13.                     // Add the deltaPosition
    14.                     screenPoint += (Vector3)screenDelta;
    15.                
    16.                     screenPoint.Set(screenPoint.x,
    17.                         screenPoint.y,
    18.                         screenPoint.z);
    19.                
    20.            
    21.  
    22.                 // Convert back to world space
    23.  
    24.                 Vector3 lastPost = camera.ScreenToWorldPoint(new Vector3(screenPoint.x, screenPoint.y, screenPoint.z));
    25.                
    26.                 transform.position = new Vector3(lastPost.x,distY,lastPost.z);
    27.                // transform.position = camera.ScreenToWorldPoint(screenPoint);
    28.  
    29.             }
    I hope it helped you :)
     
    Last edited: May 30, 2018
  10. dncgogo

    dncgogo

    Joined:
    May 30, 2018
    Posts:
    1
    It was not..help me please,
    I just want motion on the x axis