- Home /
Swipe/Drag to move Camera along Path/Track
Hello all,
I'm having trouble finding some specific information in regards to this question, and I would greatly appreciate it if anyone could spare to time to explain. Thanks in advance!
I'm looking to move the Camera along a path when touch/drag input has been received. I understand you can move the camera along a certain axis, but what about a predefined track so that the camera can't be dragged off into oblivion?
My scene is like this: There is a wall which meanders around a house with various points of interest along the wall. Here is a sketch to explain a little further:
Sometimes the roof is a point of interest, so the camera needs to be able to look up but sometimes the roof isn't present so it needs to in some places be locked to only view the walls.
Does anyone know how to give the camera a certain 'allowed' track that it can stick to? Can this be
Here is an example of the swipe feature i'm looking for
If anyone has any idea how to do this and can explain your code as you go that would be incredible! Thank you all!
GREAT question, with EXCELLENT explanatory image material. All immediately understandable; a lot of askers on this site could learn from you. :)
Answer by CHPedersen · Dec 08, 2014 at 10:33 AM
Here's an idea that might help you:
To solve this one, you could define a number of control points along the floor, following the edge of the wall. These would define a curve that determines the cameras's sandbox: the area within which it is allowed to navigate. Each control should consist of a position (Vector3) and a rotation (Quaternion). You could define a struct or a class called "CameraNavigationControlPoint" or "CamNavControlPoint" or whatever you wish, to combine these two pieces of data.
The total navigable area would thus comprise a list of these. The idea is to maintain an index into this list that determines the two control points in the curve, between which the camera is currently located. A linear interpolation between the position and rotation of these two control points will then tell you what the camera's current position and rotation should be.
I cooked up a script briefly which, while it certainly compiles, is untested and serves only to demonstrate my idea in code:
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public struct CamNavControlPoint
{
public Vector3 Position;
public Quaternion Rotation;
}
public class CameraNavigation : MonoBehaviour {
// A floating point 'index' into the list of ControlPoints. Use this to lerp your camera's position and rotation out of the list!
private float curCamIdx = 0;
private List<CamNavControlPoint> ControlPoints = new List<CamNavControlPoint>();
// Use this for initialization
void Start ()
{
// Add control points that define the curve in front of the wall, as well as a series of rotations that represent pointing the forward vector at the wall
// This is all example data, your positions and rotations are for you to figure out
ControlPoints.Add(new CamNavControlPoint() { Position = new Vector3(0, 0, 0), Rotation = Quaternion.Euler(Vector3.zero) });
ControlPoints.Add(new CamNavControlPoint() { Position = new Vector3(1, 0, 0), Rotation = Quaternion.Euler(Vector3.zero) });
ControlPoints.Add(new CamNavControlPoint() { Position = new Vector3(2, 0, 0), Rotation = Quaternion.Euler(Vector3.zero) });
// etc...
}
Vector2 swipeThreshold = new Vector2(0, 0); // Whatever
// Update is called once per frame
void Update ()
{
Touch t = Input.GetTouch(0); // Only one touch?
if (t.deltaPosition.magnitude > swipeThreshold.magnitude)
Swipe(t.deltaPosition.x); // I'm guessing this is negative if left, positive if right
}
private void Swipe(float swipeVal)
{
curCamIdx += swipeVal;
int floored = Mathf.FloorToInt(curCamIdx);
int ceilinged = Mathf.CeilToInt(curCamIdx);
Camera.main.transform.position = Vector3.Lerp(ControlPoints[floored].Position, ControlPoints[ceilinged].Position, curCamIdx - floored);
Camera.main.transform.rotation = Quaternion.Lerp(ControlPoints[floored].Rotation, ControlPoints[ceilinged].Rotation, curCamIdx - floored);
}
}
Take a look at that and try and understand what that code does. It's pretty simple. :) Hopefully it leads you on the right track, at least. Bear in mind, like I said, that this script demonstrates the idea only. I did not, for example, set the swipeThreshold, which is the minimum distance we want the user's finger to have travelled before triggering the swipe. In addition, I took the liberty to assume that the swipe direction will have negative x to the left and positive to the right. Maybe that isn't the case. Similarly, the x distance swiped probably doesn't translate directly to how far the controls should interpolated between each consecutive points in the sequence. You'll have to play with those values yourself.
The neat thing about this idea is that it will automatically interpolate a smooth transition between two right-angled rotations when two walls meet at a corner. You can play with putting points closer together there than elsewhere, to precisely define the bend, for example.