Search Unity

  1. Are you interested in providing feedback directly to Unity teams? Sign up to become a member of Unity Pulse, our new product feedback and research community.
    Dismiss Notice

LEAN ⚡️ Touch / GUI / Texture / Localization / Transition / Pool

Discussion in 'Assets and Asset Store' started by Darkcoder, Aug 1, 2019.

  1. Qhuhuit

    Qhuhuit

    Joined:
    Feb 17, 2018
    Posts:
    29
    @Darkcoder Thanks for the reply, indeed uncommenting this line fixed the issue.

    I don't understand why it is commented in the first place though? Event changing a slider in the inspector panel makes the camera move. So adjusting the lighting or an object position based on an In-Game specific camera position is almost impossible by default. I'd like to know if you have another point of view :)

    To avoid checking the condition in runtime, I've just wrapped it in a preprocessor directive like this
    Code (CSharp):
    1.      // Is the mouse within the screen?
    2. #if UNITY_EDITOR
    3.     if (new Rect(0, 0, Screen.width, Screen.height).Contains(mousePosition) == true)
    4. #endif
    5.         AddFinger(MOUSE_FINGER_INDEX, mousePosition, 1.0f, mouseSet);
     
  2. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    Some users expect to be able to drag the mouse outside the window and still have it work, and since Unity provides this data in this scenario I provide it by default.
     
  3. pako

    pako

    Joined:
    Nov 21, 2012
    Posts:
    87
     
  4. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    You probably want to use the OnDelta event which gives a Vector2 which is .x and .y for horizontal + vertical. I don't see why you would want to use the world space values. If you had to then you would have to define the horizontal axis e.g. using a Quaternion then you could rotate your Vector3 by this and then the .x and .y could be used, depending on your axis of rotation. It's a little complex to understand I guess, so you should look up quaternion and vector maths.
     
    pako likes this.
  5. pako

    pako

    Joined:
    Nov 21, 2012
    Posts:
    87
    I'll try that, thanks!
     
    Darkcoder likes this.
  6. Veteran66

    Veteran66

    Joined:
    Jul 12, 2015
    Posts:
    34
    hi

    how can i zoom the Camera with Touch Keys
     
  7. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    You can connect a UI button to the LeanPinchCamera component's IncrementZoom or MultiplyZoom methods.
     
  8. JesterGameCraft

    JesterGameCraft

    Joined:
    Feb 26, 2013
    Posts:
    180
    Hi. I wanted to ask for your advice about UI in my mobile game. I have all the examples including LeanTouch+.

    The controls are simple, two thumbs on the phone in horizontal phone orientation. The right thumb will just be pressing on the screen and off as input. The left thumb I would like to have press on/off and up/down/left/right swipes as input, but only on the left side of the screen. There are no UI buttons just player pressing on the screen. I was wondering if there is a particular example or config that you would recommend I use for this UI.

    Thank You very much for providing this framework.

    Regards...
     
  9. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    Take a look at the Lean GUI asset. This comes with examples of on screen buttons, and joysticks, this should do exactly what you describe :)
     
  10. JesterGameCraft

    JesterGameCraft

    Joined:
    Feb 26, 2013
    Posts:
    180
    Thank You. I'll check that out...
     
    Darkcoder likes this.
  11. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146
    I am wondering about how Lean Pool would handle the following scenario:

    I spawn a bunch of objects.

    I parent (group) those objects under an existing empty GameObject.

    Do those objects still utilize the performance of the pool or are they somehow disconnected or lost from the pool once I start adding them to existing parent objects?
     
    Last edited: Jun 6, 2021
  12. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146
    I have an unrelated question/issue. For the first time, I decided to use Lean Pool and Lean Transition together. Lean Pool gets installed fine but when I try to import Lean Transition - it won't allow me to import folders like the Examples or Documentation (in the Common folder) as the folder structure is the same as Lean Pool. What should I do here to get both fully installed at the same time?
     
    Last edited: Jun 6, 2021
  13. JesterGameCraft

    JesterGameCraft

    Joined:
    Feb 26, 2013
    Posts:
    180
    Just a question about Ignore Started Over GUI and Ignore Is Over GUI. The documentation is a bit vague on these I think and maybe they're self explanatory but I would just like to confirm my understanding of these flags.

    So if you take a script like LeanFingerUp for example. If it's added agains a canvas and in the canvas I have a button. If I touch the button and IgnoreStarteOverGUI is selected the LeanFingerUp will not fire, is that correct? If I have the flag cleared then it will? And IsOverGUI would behave the same I guess but while I'm moving the finger over the button?

    What if the LeanFingerUp is against RectTransform and not a canvas? Is there some example or documentation that covers these flags and use cases for them in more detail?
     
  14. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    Pooling only improves the performance of spawning and despawning objects, since they don't have to be fully instantiated/destroyed. What you do with these objects after spawn or before despawn doesn't matter.

    Try deleting the package manager download cache/packages, backing up your project, deleting these assets, and reinstalling them. Older versions of Unity have this stupid package manager bug where it doesn't actually download the latest version. So in your scenario you are probably trying to install an old version of one asset with a new version of another. I changed the folder structure a while back so this difference is important.

    Yes that is correct. The GUI is considered to be any raycastable EventSystem object that is that is on a layer specified by the LeanTouch component's GuiLayers setting, which by default is every Graphic (e.g. Image) inside the Canvas. This can also work for 3D & 2D objects with a PhysicsRaycaster & Physics2DRaycaster. A RectTransform on its own isn't raycastable so no, you would have to at least add an invisible Image to it.
     
  15. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146
    Darkcoder likes this.
  16. Nsingh13

    Nsingh13

    Joined:
    Dec 17, 2014
    Posts:
    35
    Hi! I'm getting errors when importing LeanPool into my project after having imported both LeanTouch+ and LeanGUI. I'm running Unity 2020.2.1f.

    upload_2021-6-10_15-6-40.png
     
  17. Sandro_iXtenda

    Sandro_iXtenda

    Joined:
    May 2, 2019
    Posts:
    4
    Hello everyone,

    I am using Lean Localization and I was wondering if there is a feature to retrieve a translation text for a phrase in a specific language, even when this language is not the selected one. Basically LeanLocalization.GetTranslationText(), but not for the current language, but for a language I can specify.
    I searched the docs, but couldn't find anything. Maybe somebody here has an idea.
     
  18. JesterGameCraft

    JesterGameCraft

    Joined:
    Feb 26, 2013
    Posts:
    180
    Thank You for the answer :)
     
    Darkcoder likes this.
  19. kypronite

    kypronite

    Joined:
    Apr 15, 2013
    Posts:
    13
    I'm using LeanPool and notice if I spawn 5 projectiles prefab in the scene all at one time,
    I got 5 projectiles spawned
    but when all projectiles are despawned,all 5 projectiles are inactive.
    I don't have performance issue with garbage collection which what I intend.

    But what if I use LeanPool to spawn many different type objects(etc: enemies,projectiles) and all these objects are despawned which mean I have all these inactive object hogging up all the memory.
    I always assume that there's some code under the hood that will clean up inactive object
    if not used for certain duration.
    etc: if fireball projectile are despawned(inactive) and not spawned in one minutes, LeanPool will automatically destroy despawned(inactive) fireball projectile...freeing up memory.

    Or this is by design, the decision to call up clean(ie: destroy despawned clones) is left to the user?
     
  20. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    172
    Hi, recently bought LeanTouch+ and very happy so far. I am stuck with a problem though:
    I want to support gameplay scenarios:
    1. Tile is selected by tap
    2. Tile is zoomed-in by double tap

    I have 1. implemented as it was nicely presented in "Tap to Select" example but I am struggling with 2. Qestion: how to detect Tap or double Tap as exclusive actions. When implementing 1 I used LeanSelectByFinger and LeanSelectableByFinger but this does not seem to be useful for implementing 2.
     
  21. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    You have mismatched versions installed. Delete your package manager download cache, delete the Lean folder, and then reimport to make it work.

    You can get a reference to a LeanPhrase component and access its Entries list, which stores everything. This doesn't work for CSV since that data won't be loaded, and there's no built in methods to access this because it's not a standard use case.


    There's currently no feature like this. Despawned objects don't store any additional data like despawned time, so it would require some modification.


    This can be done using the LeanFIngerTap or LeanFingerTapQuick components. This has the RequiredSelectable component, which can be set to your tile so it only activates when that specific object is selected. So in your case if you set RequiredTapCount = 2, you can use the OnFinger event to trigger your zoom in function (probably would require a custom script of some sort).
     
    kypronite likes this.
  22. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    172
    Thanks, problem is I still don't know how to configure exclusive gestures, meaning receiving 1 tap OR 2 Tap. I added LeanFigerTap 2 times, one is configured with RequiredTapCount to 1 other to 2, problem is the second one is not cancelling the first one (as the work independently) so I am receiving 2 events when performing double tap (1-tap and 2-tap events).
     
  23. khalidfathy

    khalidfathy

    Joined:
    Mar 12, 2018
    Posts:
    6
    Hi,
    I have used Lean Touch+ for Unity 2019.4 and it worked perfectly fine (both 2.1.3 and 2.3.2 versions). However, when I use the same exact setup on Unity 2020.3 the selection scripts just don't work. I can't find what I am doing wrong.
     
  24. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    36
    Oh right thanks.
     
  25. khalidfathy

    khalidfathy

    Joined:
    Mar 12, 2018
    Posts:
    6
    I have set the Input handling to "Both" as it produced an error when it was by default "New Input System", but it does not work as well.
     
  26. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146
    Has anyone done any comparisons between DoTween (PRO) and Lean Transition? My assumption is that Lean Transition is likely more performant (with less garbage)?
     
  27. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Trade-off between performance and flexibility. DOTween's Tweener and Sequence objects can be reused without allocating more memory, BUT this is not enabled by default. DOTween's defaultAutoKill setting is TRUE and defaultRecyclable is FALSE if you don't specify otherwise. The 4 most frustrating parts of DOTween's way is:
    - Each Tweener has to (re)start at a specific position (default at the current position at the Tweener is created, can be specified), so that means when you (re)start a tweener, your target transform will teleport to the Tweener's start position. Lean Transition's transform move is origin-agnostic unless you tells it to start from a certain point with a 0-second delay transition.
    - For some reason, Tweeners that move targets along a specific axis (MoveX, MoveY, MoveZ) can't be restarted. You have to use DOMove specifying coordinates of all 3 axes to have it restartable.
    - DOTween has no Editor preview like Lean Transition, you have to enter Play mode to see how your tweens look like in action.
    - DOTween's paths can be saved as prefabs to reuse, but due to the lack of target alias like Lean Transition, it's pretty much a 1-to-1 mapping between path prefab and target.
    Use it if you want predefined movements that don't change on demand, use DOTween.

    Use Lean Transition if you want more flexibility.
     
    Last edited: Sep 5, 2021
  28. TeohRIK

    TeohRIK

    Joined:
    Jan 22, 2014
    Posts:
    105
    Hi, I not sure anyone report this before or it just my issue.

    I noticed the LeanLocalization.GetFirstCurrentLanguage() function didn't return anything if the phone default language set to language that not supported.

    Example the app support English and but default phone language is chinese, the function will return empty
     
  29. cwennchen

    cwennchen

    Joined:
    Nov 22, 2019
    Posts:
    7
    Android Device, set Input.multiTouchEnabled=false, will trigger OnFingerUp, how to fix it?
     
  30. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146

    Very insightful and a great help. Thank you kindly @tonygiang !
     
  31. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hi.
    I'd like to make a feature request for Lean Touch and Lean Transition.

    For Lean Touch: Please provide a version of LeanDragTranslate, LeanTwistRotate (and other classes that may modify an object's transform) that move RigidBody and RigidBody2D via their respective.MovePosition and MoveRotation methods.

    For Lean Transition: Same request for any transition that may modify an object's transform. The Rigidbody and RigidBody2D equivalences of transform transitions would strictly take RigidBody and RigidBody2D as targets.

    These Rigidbody-targeted components would accommodate use cases such as dragging a ball through a group of pins and still have them simulate physics properly as if the ball is being pushed by a natural force. (Yes, if you're thinking this use case sounds like what a god game would need, you're 100% on point)
     
  32. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    So for my immediate need, I created a sample LeanDragTranslateRigidbody implementation, mostly based on the existing LeanDragTranslate. Sharing it here in case anybody also needs it before the author provides an official implementation:

    Code (CSharp):
    1. using UnityEngine;
    2. using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute;
    3. using Lean.Common;
    4.  
    5. namespace Lean.Touch
    6. {
    7.     /// <summary>This component allows you to translate the attached Rigidbody relative to the camera using the finger drag gesture.</summary>
    8.     [AddComponentMenu(LeanTouch.ComponentPathPrefix + "Drag Translate Rigidbody")]
    9.     public class LeanDragTranslateRigidbody : MonoBehaviour
    10.     {
    11.         public new Rigidbody rigidbody;
    12.         /// <summary>The method used to find fingers to use with this component. See LeanFingerFilter documentation for more information.</summary>
    13.         public LeanFingerFilter Use = new LeanFingerFilter(true);
    14.  
    15.         /// <summary>The camera the translation will be calculated using.
    16.         /// None/null = MainCamera.</summary>
    17.         public Camera Camera { set { _camera = value; } get { return _camera; } }
    18.         [FSA("Camera")] [SerializeField] private Camera _camera;
    19.  
    20.         /// <summary>The movement speed will be multiplied by this.
    21.         /// -1 = Inverted Controls.</summary>
    22.         public float Sensitivity { set { sensitivity = value; } get { return sensitivity; } }
    23.         [FSA("Sensitivity")] [SerializeField] private float sensitivity = 1.0f;
    24.  
    25.         /// <summary>If you want this component to change smoothly over time, then this allows you to control how quick the changes reach their target value.
    26.         /// -1 = Instantly change.
    27.         /// 1 = Slowly change.
    28.         /// 10 = Quickly change.</summary>
    29.         public float Damping { set { damping = value; } get { return damping; } }
    30.         [FSA("Damping")] [FSA("Dampening")] [SerializeField] private float damping = -1.0f;
    31.  
    32.         /// <summary>This allows you to control how much momentum is retained when the dragging fingers are all released.
    33.         /// NOTE: This requires <b>Dampening</b> to be above 0.</summary>
    34.         public float Inertia { set { inertia = value; } get { return inertia; } }
    35.         [FSA("Inertia")] [SerializeField] [Range(0.0f, 1.0f)] private float inertia;
    36.  
    37.         [SerializeField]
    38.         private Vector3 remainingTranslation;
    39.  
    40.         /// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually add a finger.</summary>
    41.         public void AddFinger(LeanFinger finger)
    42.         {
    43.             Use.AddFinger(finger);
    44.         }
    45.  
    46.         /// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove a finger.</summary>
    47.         public void RemoveFinger(LeanFinger finger)
    48.         {
    49.             Use.RemoveFinger(finger);
    50.         }
    51.  
    52.         /// <summary>If you've set Use to ManuallyAddedFingers, then you can call this method to manually remove all fingers.</summary>
    53.         public void RemoveAllFingers()
    54.         {
    55.             Use.RemoveAllFingers();
    56.         }
    57.  
    58. #if UNITY_EDITOR
    59.         protected virtual void Reset()
    60.         {
    61.             Use.UpdateRequiredSelectable(gameObject);
    62.         }
    63. #endif
    64.  
    65.         protected virtual void Awake()
    66.         {
    67.             Use.UpdateRequiredSelectable(gameObject);
    68.             this.rigidbody = GetComponent<Rigidbody>();
    69.         }
    70.  
    71.         protected virtual void FixedUpdate()
    72.         {
    73.             // Store
    74.             var oldPosition = rigidbody.position;
    75.  
    76.             // Get the fingers we want to use
    77.             var fingers = Use.UpdateAndGetFingers();
    78.  
    79.             // Calculate the screenDelta value based on these fingers
    80.             var screenDelta = LeanGesture.GetScreenDelta(fingers);
    81.  
    82.             Vector3 newPosition = rigidbody.position;
    83.  
    84.             if (screenDelta != Vector2.zero)
    85.             {
    86.                 // Make sure the camera exists
    87.                 var camera = LeanHelper.GetCamera(this._camera, gameObject);
    88.  
    89.                 if (camera != null)
    90.                 {
    91.                     // Screen position of the rigidbody
    92.                     var screenPoint = camera.WorldToScreenPoint(rigidbody.position);
    93.  
    94.                     // Add the deltaPosition
    95.                     screenPoint += (Vector3)screenDelta * Sensitivity;
    96.  
    97.                     // Convert back to world space
    98.                     newPosition = camera.ScreenToWorldPoint(screenPoint);
    99.                 }
    100.                 else
    101.                 {
    102.                     Debug.LogError("Failed to find camera. Either tag your camera as MainCamera, or set one in this component.", this);
    103.                 }
    104.             }
    105.  
    106.             // Increment
    107.             remainingTranslation += newPosition - oldPosition;
    108.  
    109.             // Get t value
    110.             var factor = LeanHelper.GetDampenFactor(Damping, Time.deltaTime);
    111.  
    112.             // Dampen remainingDelta
    113.             var newRemainingTranslation = Vector3.Lerp(remainingTranslation, Vector3.zero, factor);
    114.  
    115.             // Shift this rigidbody by the change in delta
    116.             newPosition += remainingTranslation - newRemainingTranslation;
    117.             if (newPosition != rigidbody.position) rigidbody.MovePosition(newPosition);
    118.  
    119.             if (fingers.Count == 0 && Inertia > 0.0f && Damping > 0.0f)
    120.             {
    121.                 newRemainingTranslation = Vector3.Lerp(newRemainingTranslation, remainingTranslation, Inertia);
    122.             }
    123.  
    124.             // Update remainingDelta with the dampened value
    125.             remainingTranslation = newRemainingTranslation;
    126.         }
    127.     }
    128. }
    129.  
     
    Last edited: Jul 20, 2021
  33. starfoxy

    starfoxy

    Joined:
    Apr 24, 2016
    Posts:
    146

    Super cool and thank you for sharing! Great work @tonygiang !
     
  34. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    This can be done using the LeanFingerTapExpired component, see the "Lean/Touch+/Examples/03 Finger Tap Expired" demo scene.


    Does this issue occur in a new project with only LeanTouch+ with the example scenes? If not, try to compare them and see what the difference is. Also keep in mind Version 2.2.0 of LeanTouch (Version 2.3.0 of LeanTouch+) rewrote the selection system. LeanSelect is now LeanSelectByFinger, and LeanSelectable is now LeanSelectableByFinger, etc.


    CurrentLanguage will update once LeanLocalization activates (the UpdateTranslations method via OnEnable). Before it activates, it will be set to whatever you have it set to in your scene (e.g. null/empty). During activation the UpdateCurrentLanguage method is run, which at the end (e.g. if it fails to detect the language) will use the 'DefaultLanguage' you have set (English). Therefore, this code should be working as expected.

    Make sure you hook into the LeanLocalization.OnLocalizationChanged event and run your code there. If you run your code before LeanLocalization activates or just once then it's very easy to get issues like this.


    You mean while touching the screen you want to disable touch? If so, OnFingerUp should be invoked as expected. Maybe I'm misunderstanding what issue you're talking about?


    LeanTouch+ includes a component by this exact name :) Although with my implementation I modify the velocity so the physics system deals with the movement, and this also allows for inertia on release (maybe MovePosition does too?).
     
  35. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    I have another feature request and a sample implementation for LineRenderer's startColor and endColor properties. Below is an implementation of the transition for both properties mostly based on LeanSpriteRendererColor:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace Lean.Transition.Method
    5. {
    6.     /// <summary>This component allows you to transition the specified <b>LineRenderer.startColor</b> and <b>LineRenderer.endColor</b> to the target value.</summary>
    7.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "LineRenderer/LineRenderer.startColor & endColor" + LeanTransition.MethodsMenuSuffix + "(LeanLineRendererStartEndColors)")]
    8.     public class LeanLineRendererStartEndColors : LeanMethodWithStateAndTarget
    9.     {
    10.         public override System.Type GetTargetType()
    11.         {
    12.             return typeof(LineRenderer);
    13.         }
    14.  
    15.         public override void Register()
    16.         {
    17.             PreviousState = Register(GetAliasedTarget(Data.Target), Data.StartColor, Data.EndColor, Data.Duration, Data.Ease);
    18.         }
    19.  
    20.         public static LeanState Register(LineRenderer target, Color startColor, Color endColor, float duration, LeanEase ease = LeanEase.Smooth)
    21.         {
    22.             var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    23.  
    24.             state.StartColor = startColor;
    25.             state.EndColor = endColor;
    26.             state.Ease = ease;
    27.  
    28.             return LeanTransition.Register(state, duration);
    29.         }
    30.  
    31.         [System.Serializable]
    32.         public class State : LeanStateWithTarget<LineRenderer>
    33.         {
    34.             [Tooltip("The start color we will transition to.")]
    35.             public Color StartColor = Color.white;
    36.  
    37.             [Tooltip("The end color we will transition to.")]
    38.             public Color EndColor = Color.white;
    39.  
    40.             [Tooltip("The ease method that will be used for the transition.")]
    41.             public LeanEase Ease = LeanEase.Smooth;
    42.  
    43.             [System.NonSerialized] private Color oldStartColor = new Color();
    44.             [System.NonSerialized] private Color oldEndColor = new Color();
    45.  
    46.             public override int CanFill
    47.             {
    48.                 get
    49.                 {
    50.                     return Target != null && (Target.startColor != StartColor || Target.endColor != EndColor) ? 1 : 0;
    51.                 }
    52.             }
    53.  
    54.             public override void FillWithTarget()
    55.             {
    56.                 StartColor = Target.startColor;
    57.                 EndColor = Target.endColor;
    58.             }
    59.  
    60.             public override void BeginWithTarget()
    61.             {
    62.                 oldStartColor = Target.startColor;
    63.                 oldEndColor = Target.endColor;
    64.             }
    65.  
    66.             public override void UpdateWithTarget(float progress)
    67.             {
    68.                 Target.startColor = UnityEngine.Color.LerpUnclamped(oldStartColor, StartColor, Smooth(Ease, progress));
    69.                 Target.endColor = UnityEngine.Color.LerpUnclamped(oldEndColor, EndColor, Smooth(Ease, progress));
    70.             }
    71.  
    72.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    73.         }
    74.  
    75.         public State Data;
    76.     }
    77. }
    78.  
    79. namespace Lean.Transition
    80. {
    81.     public static partial class LeanExtensions
    82.     {
    83.         public static LineRenderer startEndColorsTransition(this LineRenderer target, Color startColor, Color endColor, float duration, LeanEase ease = LeanEase.Smooth)
    84.         {
    85.             Method.LeanLineRendererStartEndColors.Register(target, startColor, endColor, duration, ease); return target;
    86.         }
    87.     }
    88. }
    Individual transitions for startColor and endColor can be easily created based on this. I'm tempted to try to implement gradient transition, but Unity wanted to play hard balls with LineRenderer. Setting key colors directly won't work. Setting the key array of the LineRenderer's gradient won't work. Only setting a whole new Gradient instance works, but Gradient is a reference type, unlikely to be performant when we create a new one each frame. So I'm just requesting for the inclusion of startColor and endColor transitions for now.
     
  36. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Is there going to be a more convenient/efficient way to programmatically set the target to the aliases of a transition object?

    I mean, this kinda works as an ad-hoc solution:

    Code (CSharp):
    1. using System.Linq;
    2. using Lean.Transition;
    3.  
    4. public static partial class Extensions
    5. {
    6.   public static LeanPlayer SetAliasTarget(this LeanPlayer source,
    7.     string alias,
    8.     UnityEngine.Object target)
    9.   {
    10.     var matchingAliases = source.Entries.SelectMany(e => e.Aliases)
    11.       .Where(a => a.Key == alias);
    12.     foreach (var a in matchingAliases) a.Obj = target;
    13.     return source;
    14.   }
    15. }
    16.  
    But this can't be the only way to programmatically set the targets to aliases, can it?
     
  37. Nsingh13

    Nsingh13

    Joined:
    Dec 17, 2014
    Posts:
    35
    What order should I import the assets after deleting everything?
     
  38. McPeppergames

    McPeppergames

    Joined:
    Feb 15, 2019
    Posts:
    74
    Hi! Great stuff... but I have one question:

    With
    if (finger.IsOverGui)
    I can detect if the finger is over a GUI element BUT how can I get the element itself after I have detected it?

    Any help welcome.
     
  39. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    So I noticed this changelog just now. It mentions a "transition builder tool". What is this? The official documentation has nothing about this tool. Buried within the Assets menu, I found 2 new ScriptableObjects - Builder and Template - that appear to be what this builder tool is supposed to be, but there's very little clue about how these assets are supposed to work.
     
  40. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hey, the component you attached does work but since I think following transform's position and rotation can and should be separate use cases, I splitted this component into 2 separate transitions:
    LeanTransformPositionFollow:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace Lean.Transition.Method
    5. {
    6.     /// <summary>This component allows you to transition the specified Transform.position to the target value.</summary>
    7.     [HelpURL(LeanTransition.HelpUrlPrefix + "LeanTransformPositionFollow")]
    8.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Transform/Transform.position Follow" + LeanTransition.MethodsMenuSuffix + "(LeanTransformPositionFollow)")]
    9.     public class LeanTransformPositionFollow : LeanMethodWithStateAndTarget
    10.     {
    11.         public override System.Type GetTargetType()
    12.         {
    13.             return typeof(Transform);
    14.         }
    15.  
    16.         public override void Register()
    17.         {
    18.             PreviousState = Register(GetAliasedTarget(Data.Target), Data.Destination, Data.Offset, Data.Duration, Data.Ease);
    19.         }
    20.  
    21.         public static LeanState Register(Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    22.         {
    23.             return Register(target, destination, Vector3.zero, duration, ease);
    24.         }
    25.  
    26.         public static LeanState Register(Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    27.         {
    28.             var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    29.  
    30.             state.Destination = destination;
    31.             state.Ease        = ease;
    32.             state.Offset      = offset;
    33.  
    34.             return LeanTransition.Register(state, duration);
    35.         }
    36.  
    37.         [System.Serializable]
    38.         public class State : LeanStateWithTarget<Transform>
    39.         {
    40.             [Tooltip("The Transform we will transition position to.")]
    41.             public Transform Destination;
    42.  
    43.             [Tooltip("The position offset.")]
    44.             public Vector3 Offset;
    45.  
    46.             [Tooltip("The ease method that will be used for the transition.")]
    47.             public LeanEase Ease = LeanEase.Smooth;
    48.  
    49.             [System.NonSerialized] private Vector3 oldPosition;
    50.  
    51.             public override int CanFill
    52.             {
    53.                 get
    54.                 {
    55.                     return 0;
    56.                 }
    57.             }
    58.  
    59.             public override void FillWithTarget()
    60.             {
    61.             }
    62.  
    63.             public override void BeginWithTarget()
    64.             {
    65.                 oldPosition = Target.position;
    66.             }
    67.  
    68.             public override void UpdateWithTarget(float progress)
    69.             {
    70.                 Target.position = Vector3.LerpUnclamped(oldPosition, Destination.position + Offset, Smooth(Ease, progress));
    71.             }
    72.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    73.         }
    74.  
    75.         public State Data;
    76.     }
    77. }
    78.  
    79. namespace Lean.Transition
    80. {
    81.     public static partial class LeanExtensions
    82.     {
    83.         public static Transform PositionFollowTransition(this Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    84.         {
    85.             Method.LeanTransformPositionFollow.Register(target, destination, duration, ease); return target;
    86.         }
    87.  
    88.         public static Transform PositionFollowTransition(this Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    89.         {
    90.             Method.LeanTransformPositionFollow.Register(target, destination, offset, duration, ease); return target;
    91.         }
    92.     }
    93. }
    LeanTransformRotationFollow:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace Lean.Transition.Method
    5. {
    6.     /// <summary>This component allows you to transition the specified Transform.rotation to the target value.</summary>
    7.     [HelpURL(LeanTransition.HelpUrlPrefix + "LeanTransformRotationFollow")]
    8.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Transform/Transform.rotation Follow" + LeanTransition.MethodsMenuSuffix + "(LeanTransformRotationFollow)")]
    9.     public class LeanTransformRotationFollow : LeanMethodWithStateAndTarget
    10.     {
    11.         public override System.Type GetTargetType()
    12.         {
    13.             return typeof(Transform);
    14.         }
    15.  
    16.         public override void Register()
    17.         {
    18.             PreviousState = Register(GetAliasedTarget(Data.Target), Data.Destination, Data.Offset, Data.Duration, Data.Ease);
    19.         }
    20.  
    21.         public static LeanState Register(Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    22.         {
    23.             return Register(target, destination, Vector3.zero, duration, ease);
    24.         }
    25.  
    26.         public static LeanState Register(Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    27.         {
    28.             var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    29.  
    30.             state.Destination = destination;
    31.             state.Ease        = ease;
    32.             state.Offset      = offset;
    33.  
    34.             return LeanTransition.Register(state, duration);
    35.         }
    36.  
    37.         [System.Serializable]
    38.         public class State : LeanStateWithTarget<Transform>
    39.         {
    40.             [Tooltip("The Transform we will transition rotation to.")]
    41.             public Transform Destination;
    42.  
    43.             [Tooltip("The rotation offset.")]
    44.             public Vector3 Offset;
    45.  
    46.             [Tooltip("The ease method that will be used for the transition.")]
    47.             public LeanEase Ease = LeanEase.Smooth;
    48.  
    49.             [System.NonSerialized] private Quaternion oldRotation;
    50.  
    51.             Quaternion finalRotation;
    52.  
    53.             public override int CanFill
    54.             {
    55.                 get
    56.                 {
    57.                     return 0;
    58.                 }
    59.             }
    60.  
    61.             public override void FillWithTarget()
    62.             {
    63.             }
    64.  
    65.             public override void BeginWithTarget()
    66.             {
    67.                 oldRotation = Target.rotation;
    68.                 finalRotation = Quaternion.Euler(Destination.rotation.eulerAngles + Offset);
    69.             }
    70.  
    71.             public override void UpdateWithTarget(float progress)
    72.             {
    73.                 Target.rotation = Quaternion.LerpUnclamped(oldRotation, Destination.rotation, Smooth(Ease, progress));
    74.             }
    75.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    76.         }
    77.  
    78.         public State Data;
    79.     }
    80. }
    81.  
    82. namespace Lean.Transition
    83. {
    84.     public static partial class LeanExtensions
    85.     {
    86.         public static Transform RotationFollowTransition(this Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    87.         {
    88.             Method.LeanTransformRotationFollow.Register(target, destination, duration, ease); return target;
    89.         }
    90.  
    91.         public static Transform RotationFollowTransition(this Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    92.         {
    93.             Method.LeanTransformRotationFollow.Register(target, destination, offset, duration, ease); return target;
    94.         }
    95.     }
    96. }
    Looking forward to see these methods being made official.

    Edit: looks like the default registration method of LeanTransformFollow has not taken the Offset value into account, so I'm modifying my position and rotation methods to fix this bug.

    Edit 2: The original LeanTransformFollow doesn't follow the localScale property, so I might as well write a LeanTransformLocalScaleFollow:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace Lean.Transition.Method
    5. {
    6.     /// <summary>This component allows you to transition the specified Transform.localScale to the target value.</summary>
    7.     [HelpURL(LeanTransition.HelpUrlPrefix + "LeanTransformLocalScaleFollow")]
    8.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Transform/Transform.localScale Follow" + LeanTransition.MethodsMenuSuffix + "(LeanTransformLocalScaleFollow)")]
    9.     public class LeanTransformLocalScaleFollow : LeanMethodWithStateAndTarget
    10.     {
    11.         public override System.Type GetTargetType()
    12.         {
    13.             return typeof(Transform);
    14.         }
    15.  
    16.         public override void Register()
    17.         {
    18.             PreviousState = Register(GetAliasedTarget(Data.Target), Data.Destination, Data.Offset, Data.Duration, Data.Ease);
    19.         }
    20.  
    21.         public static LeanState Register(Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    22.         {
    23.             return Register(target, destination, Vector3.zero, duration, ease);
    24.         }
    25.  
    26.         public static LeanState Register(Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    27.         {
    28.             var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    29.  
    30.             state.Destination = destination;
    31.             state.Ease        = ease;
    32.             state.Offset      = offset;
    33.  
    34.             return LeanTransition.Register(state, duration);
    35.         }
    36.  
    37.         [System.Serializable]
    38.         public class State : LeanStateWithTarget<Transform>
    39.         {
    40.             [Tooltip("The Transform we will transition localScale to.")]
    41.             public Transform Destination;
    42.  
    43.             [Tooltip("The localScale offset.")]
    44.             public Vector3 Offset;
    45.  
    46.             [Tooltip("The ease method that will be used for the transition.")]
    47.             public LeanEase Ease = LeanEase.Smooth;
    48.  
    49.             [System.NonSerialized] private Vector3 oldLocalScale;
    50.  
    51.             public override int CanFill
    52.             {
    53.                 get
    54.                 {
    55.                     return 0;
    56.                 }
    57.             }
    58.  
    59.             public override void FillWithTarget()
    60.             {
    61.             }
    62.  
    63.             public override void BeginWithTarget()
    64.             {
    65.                 oldLocalScale = Target.localScale;
    66.             }
    67.  
    68.             public override void UpdateWithTarget(float progress)
    69.             {
    70.                 Target.localScale = Vector3.LerpUnclamped(oldLocalScale, Destination.localScale + Offset, Smooth(Ease, progress));
    71.             }
    72.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    73.         }
    74.  
    75.         public State Data;
    76.     }
    77. }
    78.  
    79. namespace Lean.Transition
    80. {
    81.     public static partial class LeanExtensions
    82.     {
    83.         public static Transform LocalScaleFollowTransition(this Transform target, Transform destination, float duration, LeanEase ease = LeanEase.Smooth)
    84.         {
    85.             Method.LeanTransformPositionFollow.Register(target, destination, duration, ease); return target;
    86.         }
    87.  
    88.         public static Transform LocalScaleFollowTransition(this Transform target, Transform destination, Vector3 offset, float duration, LeanEase ease = LeanEase.Smooth)
    89.         {
    90.             Method.LeanTransformPositionFollow.Register(target, destination, offset, duration, ease); return target;
    91.         }
    92.     }
    93. }
     
    Last edited: Jul 5, 2021
  41. Sherwinnie

    Sherwinnie

    Joined:
    Jan 24, 2020
    Posts:
    19
    Hi, I want to ask a question on latency. Would Event-Based system (OnFingerDown, OnFingerUp...etc) have better latency than LeanTouch.Fingers?
     
  42. slimshader

    slimshader

    Joined:
    Jun 11, 2013
    Posts:
    172
    Checked it before asking the question, still not clear on how to make different gesture recognizes mutually exclusive in generic way. Anyways, Fingers package turned out to be easy in that regard so went with that. Thanks for the assistance still.
     
  43. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hey, I have a feature request for the inclusion of a LeanEventTarget method in the official package. It's just LeanEvent but with a target as an argument. You can take my implementation below:
    Code (CSharp):
    1.  
    2. using UnityEngine;
    3. using UnityEngine.Events;
    4. using System.Collections.Generic;
    5.  
    6. namespace Lean.Transition.Method
    7. {
    8.   /// <summary>This component allows you to invoke a custom action with one UnityEngine.Object as argument after the specified duration.</summary>
    9.   [HelpURL(LeanTransition.HelpUrlPrefix + "LeanEventTarget")]
    10.   [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Event Target" + LeanTransition.MethodsMenuSuffix + "(LeanEventTarget)")]
    11.   public class LeanEventTarget : LeanMethodWithStateAndTarget
    12.   {
    13.     public override System.Type GetTargetType()
    14.     {
    15.       return typeof(UnityEngine.Object);
    16.     }
    17.  
    18.     public override void Register()
    19.     {
    20.       PreviousState = Register(GetAliasedTarget(Data.Target), Data.Event, Data.Duration);
    21.     }
    22.  
    23.     public static LeanState Register(UnityEngine.Object target, System.Action<UnityEngine.Object> action, float duration)
    24.     {
    25.       var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    26.  
    27.       state.Action = action;
    28.       state.Event  = null;
    29.  
    30.       return LeanTransition.Register(state, duration);
    31.     }
    32.  
    33.     public static LeanState Register(UnityEngine.Object target, UnityEventUnityObject action, float duration)
    34.     {
    35.       var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    36.  
    37.       state.Action = null;
    38.       state.Event  = action;
    39.  
    40.       return LeanTransition.Register(state, duration);
    41.     }
    42.  
    43.     [System.Serializable]
    44.     public class State : LeanStateWithTarget<UnityEngine.Object>
    45.     {
    46.       [Tooltip("The event that will be invoked.")]
    47.       public UnityEventUnityObject Event;
    48.  
    49.       [System.NonSerialized]
    50.       public System.Action<UnityEngine.Object> Action;
    51.      
    52.       public override ConflictType Conflict
    53.       {
    54.         get
    55.         {
    56.           return ConflictType.None;
    57.         }
    58.       }
    59.  
    60.       public override void Begin()
    61.       {
    62.         // No state to begin from
    63.       }
    64.  
    65.       public override void Update(float progress)
    66.       {
    67.         if (progress == 1.0f)
    68.         {
    69.           Debug.Log($"Target is null? {Target == null}");
    70.           if (Event != null)
    71.           {
    72.             Event.Invoke(Target);
    73.           }
    74.  
    75.           if (Action != null)
    76.           {
    77.             Action.Invoke(Target);
    78.           }
    79.         }
    80.       }
    81.  
    82.       public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    83.     }
    84.  
    85.     public State Data;
    86.   }
    87.  
    88.   [System.Serializable]
    89.   public class UnityEventUnityObject : UnityEvent<UnityEngine.Object> { }
    90. }
    91.  
    92. namespace Lean.Transition
    93. {
    94.   public static partial class LeanExtensions
    95.   {
    96.     public static T EventTargetTransition<T>(this T target, System.Action<UnityEngine.Object> action, float duration = 0.0f)
    97.       where T : UnityEngine.Object
    98.     {
    99.       Method.LeanEventTarget.Register(target, action, duration); return target;
    100.     }
    101.  
    102.     public static UnityEngine.Object EventTargetTransition(this UnityEngine.Object target, System.Action<UnityEngine.Object> action, float duration = 0.0f)
    103.     {
    104.       Method.LeanEventTarget.Register(target, action, duration); return target;
    105.     }
    106.   }
    107. }
    108.  
     
    Last edited: Jul 5, 2021
  44. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hey, I want to report a bug with Lean Transition. This actually affects Lean GUI as well. The bug is as follows:

    So LeanPlayer depends on the LeanTransition.AddAliasTypePairs method to find the aliases of all transition methods from a Transform. Now, because Lean Transition supports branching, as exemplified in the #4 example scene, a transition-containing transform will join to the transitions underneath it in the scene Hierarchy. But because LeanTransition.AddAliasTypePairs find aliases using a GetComponents call, the aliases used by the child transitions will not be found and displayed on the Inspector. My proposed fix is to change the method to find aliases inside LeanTransition.AddAliasTypePairs to GetComponentsInChildren.

    Several Lean GUI components such as LeanToggle, LeanWindow and LeanButton use LeanPlayer and therefore have the same issue.
     
  45. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hey, I have a feature request for LeanRectTransformAnchoredPositionTranslate. It's LeanTransformTranslate but for RectTransform.anchoredPosition. You can take my implementation below:
    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections.Generic;
    3.  
    4. namespace Lean.Transition.Method
    5. {
    6.     /// <summary>This component allows you to transition the specified Transform.anchoredPosition to the target value.</summary>
    7.     [HelpURL(LeanTransition.HelpUrlPrefix + "LeanRectTransformAnchoredPositionTranslate")]
    8.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Transform/Transform.anchoredPosition Translate" + LeanTransition.MethodsMenuSuffix + "(LeanRectTransformAnchoredPositionTranslate)")]
    9.     public class LeanRectTransformAnchoredPositionTranslate : LeanMethodWithStateAndTarget
    10.     {
    11.         public override System.Type GetTargetType()
    12.         {
    13.             return typeof(RectTransform);
    14.         }
    15.  
    16.         public override void Register()
    17.         {
    18.             PreviousState = Register(GetAliasedTarget(Data.Target), Data.Translation, Data.Duration, Data.Ease);
    19.         }
    20.  
    21.         public static LeanState Register(RectTransform target, Vector2 translation, float duration, LeanEase ease = LeanEase.Smooth)
    22.         {
    23.             var state = LeanTransition.SpawnWithTarget(State.Pool, target);
    24.  
    25.             state.Translation = translation;
    26.             state.Ease        = ease;
    27.  
    28.             return LeanTransition.Register(state, duration);
    29.         }
    30.  
    31.         [System.Serializable]
    32.         public class State : LeanStateWithTarget<RectTransform>
    33.         {
    34.             [Tooltip("The amount we will translate.")]
    35.             public Vector2 Translation;
    36.  
    37.             [Tooltip("The ease method that will be used for the transition.")]
    38.             public LeanEase Ease = LeanEase.Smooth;
    39.  
    40.             [System.NonSerialized] private Vector2 oldAnchoredPosition;
    41.  
    42.             public override ConflictType Conflict
    43.             {
    44.                 get
    45.                 {
    46.                     return ConflictType.None;
    47.                 }
    48.             }
    49.  
    50.             public override void BeginWithTarget()
    51.             {
    52.                 oldAnchoredPosition = Target.anchoredPosition;
    53.             }
    54.  
    55.             public override void UpdateWithTarget(float progress)
    56.             {
    57.                 Target.anchoredPosition = Vector2.LerpUnclamped(oldAnchoredPosition, oldAnchoredPosition + Translation, Smooth(Ease, progress));
    58.             }
    59.  
    60.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    61.         }
    62.  
    63.         public State Data;
    64.     }
    65. }
    66.  
    67. namespace Lean.Transition
    68. {
    69.     public static partial class LeanExtensions
    70.     {
    71.         public static RectTransform anchoredPositionTranslateTransition(this RectTransform target, float x, float y, float duration, LeanEase ease = LeanEase.Smooth)
    72.         {
    73.             Method.LeanRectTransformAnchoredPositionTranslate.Register(target, new Vector2(x, y), duration, ease); return target;
    74.         }
    75.  
    76.         public static RectTransform anchoredPositionTranslateTransition(this RectTransform target, Vector2 translation, float duration, LeanEase ease = LeanEase.Smooth)
    77.         {
    78.             Method.LeanRectTransformAnchoredPositionTranslate.Register(target, translation, duration, ease); return target;
    79.         }
    80.     }
    81. }
    (At this point, you can treat these feature requests as if they are pull requests even though this is not officially an open-source project)
     
    Last edited: Jul 6, 2021
  46. Darkcoder

    Darkcoder

    Joined:
    Apr 13, 2011
    Posts:
    2,665
    Entry's AddAlias method can be used to do this, as it already overwrites any existing key value.

    As long as all Lean assets are up to date the import order shouldn't matter, as the shared libraries will be the same.


    You must manually call LeanTouch.RaycastGui (e.g. at yourFinger.ScreenPosition) to get more information like this.


    I haven't had time to write a tutorial for this as it's a little advanced. Inside the Lean/Transition/Methods folders you can see a ScriptableObject with the full name of the class it builds transitions for. This object has the Entries list, which allows you to set which properties you want to build transitions for, and the property specific settings required to build it. For example:

    upload_2021-7-9_7-19-17.png

    This builds a transition for the AudioSource's panStereo setting using the Float template and a Range slider. For floats like this it's fairly easy, but it gets a little more complex for vector properties and such. Programming knowledge is required as these bits of text get directly pasted into code.


    In terms of frames there's no difference as long as LeanTouch updates first via script execution order. If you have many scripts in Update then there may be a gap between when LeanTouch updates and your script does, so you may want to make sure they're next to each other in the script execution order, or use the events.

    Thanks for deep diving into the code! I'm currently really busy going through a support request backlog and updating all my assets for SRP support and various other things so I don't have any time to look into these issues though :(
     
  47. Volkerku

    Volkerku

    Joined:
    Nov 23, 2016
    Posts:
    100
    I'm using Lean TwistRotateAxis and LeanDragAlong, which work great.
    Question, how can I fire an event (I would like to trigger haptic feedback) when the rotation or the drag starts and ends?
     
  48. el_Guero

    el_Guero

    Joined:
    Sep 15, 2017
    Posts:
    119
    Hi!

    I am trying to find out if I can make LeanTouch Finger Swipe work continously without having to lift the finger. Meaning, when I swipe left-right-left etc, the gameobject moves in the same way on that particular axis (respectively an event is triggered with each direction change). Or maybe the question is: can I put the script into listener mode again by calling a function instead of having to lift the finger and tap again?

    Edit 1: or put it into listener automatically as soon as the first swipe is triggered?

    Edit 2: So in connection to the above, I actually realized that the swipe triggers the event when the finger is lifted, how is it possible to trigger an event as soon as a minimum distance is executed?

    All these questions in reality come because the swipe as it is setup in the demo scene is not very intuitive on touch devices. When people play a game they normally don't lift the finger when they swipe.

    Thanks.
     
    Last edited: Jul 14, 2021
  49. tonygiang

    tonygiang

    Joined:
    Jun 13, 2017
    Posts:
    42
    Hey! Feature request/Pull request for LeanEventEasedFloat. This component doesn't actually transition any target, it just takes a value eased from a start and end and pipe it into an event that will invoke in the state's update loop throughout its transition period. Sample implementation below:

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Events;
    3. using System.Collections.Generic;
    4.  
    5. namespace Lean.Transition.Method
    6. {
    7.     /// <summary>This component allows you to invoke a custom action with an eased float value during the transition period.</summary>
    8.     [HelpURL(LeanTransition.HelpUrlPrefix + "LeanEventEasedFloat")]
    9.     [AddComponentMenu(LeanTransition.MethodsMenuPrefix + "Event Eased Float" + LeanTransition.MethodsMenuSuffix + "(LeanEventEasedFloat)")]
    10.     public class LeanEventEasedFloat : LeanMethodWithState
    11.     {
    12.         public override void Register()
    13.         {
    14.             PreviousState = Register(Data.StartValue, Data.EndValue, Data.Event, Data.Duration, Data.Ease);
    15.         }
    16.  
    17.         public static LeanState Register(float startValue, float endValue, System.Action<float> action, float duration, LeanEase ease = LeanEase.Smooth)
    18.         {
    19.             var state = LeanTransition.Spawn(State.Pool);
    20.  
    21.             state.StartValue = startValue;
    22.             state.EndValue   = endValue;
    23.             state.Action     = action;
    24.             state.Event      = null;
    25.             state.Ease       = ease;
    26.  
    27.             return LeanTransition.Register(state, duration);
    28.         }
    29.  
    30.         public static LeanState Register(float startValue, float endValue, UnityEventFloat action, float duration, LeanEase ease = LeanEase.Smooth)
    31.         {
    32.             var state = LeanTransition.Spawn(State.Pool);
    33.  
    34.             state.StartValue = startValue;
    35.             state.EndValue   = endValue;
    36.             state.Action     = null;
    37.             state.Event      = action;
    38.             state.Ease       = ease;
    39.  
    40.             return LeanTransition.Register(state, duration);
    41.         }
    42.  
    43.         public void SetStateStartValue(float value) { Data.StartValue = value; }
    44.  
    45.         public void SetStateEndValue(float value) { Data.EndValue = value; }
    46.  
    47.         [System.Serializable]
    48.         public class State : LeanState
    49.         {
    50.             [Tooltip("The start argument for the update Lerp function.")]
    51.             public float StartValue;
    52.  
    53.             [Tooltip("The end argument for the update Lerp function.")]
    54.             public float EndValue;
    55.  
    56.             [Tooltip("The event that will be invoked.")]
    57.             public UnityEventFloat Event;
    58.  
    59.             [System.NonSerialized]
    60.             public System.Action<float> Action;
    61.  
    62.             [Tooltip("The ease method that will be used for the transition.")]
    63.             public LeanEase Ease = LeanEase.Smooth;
    64.  
    65.             public override ConflictType Conflict
    66.             {
    67.                 get
    68.                 {
    69.                     return ConflictType.None;
    70.                 }
    71.             }
    72.  
    73.             public override void Begin()
    74.             {
    75.                 // No state to begin from
    76.             }
    77.  
    78.             public override void Update(float progress)
    79.             {
    80.                 if (Event != null)
    81.                 {
    82.                     Event.Invoke(Mathf.LerpUnclamped(StartValue, EndValue, Smooth(Ease, progress)));
    83.                 }
    84.  
    85.                 if (Action != null)
    86.                 {
    87.                     Action.Invoke(Mathf.LerpUnclamped(StartValue, EndValue, Smooth(Ease, progress)));
    88.                 }
    89.             }
    90.  
    91.             public static Stack<State> Pool = new Stack<State>(); public override void Despawn() { Pool.Push(this); }
    92.         }
    93.  
    94.         public State Data;
    95.     }
    96.  
    97.     [System.Serializable] public class UnityEventFloat : UnityEvent<float> { }
    98. }
    99.  
    100. namespace Lean.Transition
    101. {
    102.     public static partial class LeanExtensions
    103.     {
    104.         public static T EventEasedFloatTransition<T>(this T target, float startValue, float endValue, System.Action<float> action, float duration, LeanEase ease = LeanEase.Smooth)
    105.             where T : Component
    106.         {
    107.             Method.LeanEventEasedFloat.Register(startValue, endValue, action, duration, ease); return target;
    108.         }
    109.  
    110.         public static GameObject EventEasedFloatTransition(this GameObject target, float startValue, float endValue, System.Action<float> action, float duration, LeanEase ease = LeanEase.Smooth)
    111.         {
    112.             Method.LeanEventEasedFloat.Register(startValue, endValue, action, duration, ease); return target;
    113.         }
    114.     }
    115. }
    Theoretically, a variant of this method can be created for other types like Vector2, Vector3, Color, etc... if you just replace the type of StartValue and EndValue with those types. An overall base type that doesn't have an UnityEngine.Object-based Target may even be created to cut down on the boilerplate.

    I initially created this method to gradually accelerate/decelerate objects that each has its own moving direction, but this potentially can replace a lot of existing transition methods and future use cases as well. An agnostic event plays nice with whatever custom classes you have in your project.
     
  50. bhdev

    bhdev

    Joined:
    Jul 15, 2021
    Posts:
    1
    Hi, I'm trying to make Lean Pinch Camera work with a Cinemachine virtual camera - tried to adjust the script directly but seem unable to access Cinemachine namespace. Any idea how I can modify it to access the m_Lens.FieldOfView field?
     
unityunity