Search code examples
animationpathunity-game-engineitween

How to control an animation by touch position along a path in Unity3D?


I have a GameObject that I want to animate along a specific path/curve, but the animation should be controlled by mouse/touch position. So when I touch/click on the GameObject and move the finger/mouse on/near the path (or maybe its easier to just move down) the GameObject should follow its defined path.

I like iTween, but I think it is not possible to find a solution using it here, right?

edit: added image: enter image description here


Solution

  • It's quite a simpler task than what you might think.

    Basically it's a question of remapping a function (that takes the input as parameter) to another function (that express a position along a path). There are several ways of doing that, depending on the precise effect you want to implement.

    The most important choices you have to take are:

    • How the describe the path/curve
    • How to handle input

    Example

    For the path an easy and flexible way is to use some sort of spline curves, such as cubic Bézier curve. It's easy to implement and Unity3D provides built-in functions to draw them. Have a look at Handles.DrawBezier.

    Basically a Bézier function takes as input a parameter t in the domain [0,1] and return as a result a point in the space (2D or 3D as you prefer). B(0) gives the point at the begin of the curve, B(1) the end point. (Side note: the function is not linear so in the general case incrementing at a constant rate t doesn't produce a movement at constant speed along the curve. This paper might be useful).

    For what concern the input the simpler solution that comes up to my mind is the following:

    • Accumulate somewhere the vector describing the offset from the position when the touch started to the current touch position. (Here's how to handle touches, have a look at deltaPosition).

    Something like:

    if (Input.touchCount > 0 && Input.GetTouch(0).phase == TouchPhase.Moved) 
    {
      offsetFromStartPos += Input.GetTouch(0).deltaPosition;
    }
    

    Let's say you want to swipe up/down your finger for moving forward/back an object along a path.Choose a "travel" distance (the domain of the input function) for your finger in order to complete the movement along the curve and normalize the offset using such distance in order to remap the input into the [0,1] domain.

    float t = offsetFromStartPos.y / maxDistanceAlongYAxis;
    Vector3 pos = CalculateBezier(t);
    transform.position = pos;
    

    It's just an hint to put you in the right direction.