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);
}
}
}
}
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);
}
}
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 preventsthe 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.
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
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);
}
}
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.
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);
}