-
Notifications
You must be signed in to change notification settings - Fork 364
Examples
TouchScript comes with many example scenes, each of them demonstrates how to use various framework features.
- ScreenTransformGesture,
- Pointer limits,
- FullscreenLayer.
- Drag with one finger to move the camera,
- Drag with 2+ fingers to rotate the camera,
- Pinch to zoom,
- Rotate with 2 fingers to rotate around Z axis.
/Scene GameObject has the main logic and 3 TouchScript components:
- FullscreenLayer — layer which just gets all pointers without doing any raycasts into the scene and sets their target to the GameObject it is attached to, in this case /Scene. A FullscreenLayer is usually put in the bottom of layers hierarchy to catch all remaining pointers, but in this example it is the only layer because we are not interested in "touching" any objects.
-
ScreenTransformGesture which has Transform Type set to
Translation
only and Limit Pointers to1
. This gesture recognizes one-pointer pan movements only. - Another ScreenTransformGesture which has Transform Type to
Everything
and Limit Pointers to>=2
. This gesture recognizes all two-pointer transforms. - CameraController subscribes to ScreenTransformGestures and controls camera movement like so:
private void OnEnable()
{
TwoFingerMoveGesture.Transformed += twoFingerTransformHandler;
ManipulationGesture.Transformed += manipulationTransformedHandler;
}
private void OnDisable()
{
TwoFingerMoveGesture.Transformed -= twoFingerTransformHandler;
ManipulationGesture.Transformed -= manipulationTransformedHandler;
}
private void manipulationTransformedHandler(object sender, System.EventArgs e)
{
var rotation = Quaternion.Euler(ManipulationGesture.DeltaPosition.y/Screen.height*RotationSpeed,
-ManipulationGesture.DeltaPosition.x/Screen.width*RotationSpeed,
ManipulationGesture.DeltaRotation);
pivot.localRotation *= rotation;
cam.transform.localPosition += Vector3.forward*(ManipulationGesture.DeltaScale - 1f)*ZoomSpeed;
}
private void twoFingerTransformHandler(object sender, System.EventArgs e)
{
pivot.localPosition += pivot.rotation*TwoFingerMoveGesture.DeltaPosition*PanSpeed;
}
- TransformGesture,
- PinnedTransformGesture,
- Transformer,
- OverHelper,
- StandardLayer,
- GestureManager.Instance.GlobalGestureDelegate.
- Drag a figure to move it,
- Drag the board to rotate it,
- Hold to disable gestures on all but one piece.
/Scene/Camera GameObject has a StandardLayer with all options disabled but Hit 3D Objects
in Hit test options property to raycast only for 3D objects in the scene, since this scene doesn't have any 2D or UI objects.
/Scenes/Board GameObject has two components attached:
-
PinnedTransformGesture which has Transform Type set to
Rotation
and Projection toXZ Plane
which is the ground plane. It means that this gesture will project screen pointers onto this plane and calculate all transformations within this plane. - Board which listens to PinnedTransformGesture's events and rotates the board like so:
private void OnEnable()
{
gesture = GetComponent<PinnedTransformGesture>();
gesture.Transformed += transformedHandler;
}
private void OnDisable()
{
gesture.Transformed -= transformedHandler;
}
private void transformedHandler(object sender, System.EventArgs e)
{
transform.localRotation *= Quaternion.AngleAxis(gesture.DeltaRotation, gesture.RotationAxis);
}
/Scene/Board/Container/CheckerDark GameObjects have the following components attached:
-
TransformGesture which has Transform Type set to
Translation
and Projection toXZ Plane
. - Transformer which listens to TransformGesture's events and moves the object.
- OverHelper which dispatches an event when a pointer is over the object.
- Highlight which listens to OverHelper's events and changes the object color.
- Checker which listens to TransformGesture's events and disables or enables Rigidbody on this object, while actual movement is done by Transformer component.
/scene GameObject has Exclusive component attached to it which implements IGestureDelegate
interface and assigns itself to GestureManager.Instance.GlobalGestureDelegate
. When a user presses Space
this component prevents all gestures starting except the ones on Target
GameObject using this code:
public bool ShouldBegin(Gesture gesture)
{
if (exclusive) return gesture == Target;
return true;
}
public bool ShouldReceivePointer(Gesture gesture, Pointer pointer)
{
if (exclusive) return gesture == Target;
return true;
}
- 2D objects,
- Gesture.Cancel() to cancel a gesture and return its pointers to the system.
- Drag circles around. When overlapped they will spawn another circle of combined volume,
- Use two fingers to scale circles.
/Scene/Camera GameObject has a StandardLayer with all options disabled but Hit 2D Objects
in Hit test options property to raycast only for 2D objects in the scene, since this scene doesn't have any 3D or UI objects.
Circle prefab has the following components attached:
-
TransformGesture with Transform Type set to
Everything
so a user can move, scale and rotate circles (though rotating circles doesn't really make much sense). - Transformer which listens to TransformGesture's events.
-
Circle which handles circles intersection in
OnTriggerEnter2D
and uses this code to cancel currently active TransformGesture:
GetComponent<TransformGesture>().Cancel(true, true);
(true, true) means that the pointers should be returned to the system, like they were just pressed. At this point cancelled pointers are caught by the new (bigger) circle and its TransformGesture so the user can continue moving and resizing the new circle.
- TouchLayer.Delegate,
- Implementing a custom Input Source.
- Drag, scale, rotate the cat picture.
Notice how you are touching the Cube but are able to move the image far away in the scene.
This example shows how extensible TouchScript is. There's a cube in the scene which has a RenderTexture
from an offscreen camera assigned to its material. But you can still move and resize this image with your fingers.
/Scene/Scene Camera/Image GameObject has TransformGesture and Transformer components to move it around. This is the image you see on the Cube.
/Scene/Cube GameObject has the following components attached:
- MetaGesture which catches pointers on the object and dispatches events.
-
RedirectInput which listens to MetaGesture's events. But it also inherits from
InputSource
which means that it can inject pointers into the system. It does this like so:
private void pointerPressedHandler(object sender, MetaGestureEventArgs metaGestureEventArgs)
{
var pointer = metaGestureEventArgs.Pointer;
if (pointer.InputSource == (IInputSource)this) return;
If this pointer is generated by this script, stop processing it.
var newPointer = PointerFactory.Create(pointer.Type, this);
newPointer.CopyFrom(pointer);
newPointer.Position = processCoords(pointer.GetPressData().RaycastHit.textureCoord);
newPointer.Flags = pointer.Flags | Pointer.FLAG_ARTIFICIAL | Pointer.FLAG_INTERNAL;
addPointer(newPointer);
pressPointer(newPointer);
map.Add(pointer.Id, newPointer);
}
Next, the code creates a copy pointer, adds FLAG_INTERNAL
to hide it from Cursor Visualizer
, then adds and presses it. At this point the touch is injected into the system.
/Scene GameObject has the following components attached:
-
LayerDelegate which implements
ILayerDelegate
and is set toTouchLayer.Delegate
of all layers in the scene by Init script. - Init which sets up LayerDelegate.
This is the code inside LayerDelegate:
public RedirectInput Source;
public TouchLayer RenderTextureLayer;
public bool ShouldReceivePointer(TouchLayer layer, IPointer pointer)
{
if (layer == RenderTextureLayer)
return pointer.InputSource == (IInputSource)Source;
return pointer.InputSource != (IInputSource)Source;
}
Which basically says: "The layer on RenderTexture Camera should receive fake pointers, while others don't".
- Multiple layers,
- TapGesture.
- Drag halves of the screen,
- Drag checkers,
- Drag boards to rotate them,
- Tap Unity logos.
The scene contains 5 layers. Check TouchManager GameObject with TouchManager
script attached which has a list of layers. The layers must be sorted in the specific order: 2D, Right and Left 3D Camera, Right and Left Fullscreen layers. This is because layers are iterated from top to bottom when trying to determine what object a pointer hits.
/Scene/2D/Unity_Logo GameObjects have TapGesture on them which are used by Logo component to change color on tap.
/Scene/Left/Board and /Scene/Right/Board are the same as in Checkers
example.
- Working with UI controls,
- PressGesture,
- TransformGesture and Transformer.
- Move, scale and rotate photos,
- Tap ADD button to add photos,
- Tap colored buttons to change color.
/Scene/World Space Plane/World Space Canvas/Field/Image # GameObjects have the following components attached:
- TransformGesture and Transformer to move/scale/rotate cat images.
- PressGesture which is used to bring the pressed image up.
/Scene/World Space Plane/World Space Canvas/Field/Image #/Close is just a UI Button which TouchScript sends pointer input.
/Scene/ScreenSpace Canvas/Panel/Button is just a set of UI Buttons which interact with TouchScript. No special components or code is required.
- Gesture.Cancel(),
- TransformGesture and Transformer,
- LayerManager.SetExclusive().
- Press a Unity logo to spawn a planet,
- Drag a planet into portal.
This example demonstrates how to do the following:
- Cancel a gesture on some condition,
- "Give" pointers from one object to another.
/Game Canvas/Spawner# GameObjects have the following components attached:
- PressGesture which is used by Spawner.
- Spawner which creates a planet when logo is pressed and "gives" it pointer from PressGesture by doing the following:
var target = Instantiate(Prefab, Position.parent);
target.position = Position.position;
LayerManager.Instance.SetExclusive(target);
press.Cancel(true, true);
LayerManager.Instance.ClearExclusive();
This code creates an instance of Prefab
and sets it exclusive so no other object can receive pointers. After that the code cancels the gesture and returns its pointers to the system which immediately go our object.
/Scene/Camera/Stuff/Vortex has a script attached which calls planet.Fall();
on every planet which comes close. This method basically does the following:
var gesture = GetComponent<TransformGesture>();
if (gesture != null) gesture.Cancel();
It cancels the gesture but doesn't cancel its pointers, so the planes just fall into the vortex if the user doesn't catch them quickly.
- Pointer input.
- Touch the screen.
This example shows how to use raw pointer input with no gesture logic. /Scene/Camera has Spawner script attached which spawns prefab instances using this code:
private void OnEnable()
{
if (TouchManager.Instance != null)
TouchManager.Instance.PointersPressed += pointersPressedHandler;
}
private void OnDisable()
{
if (TouchManager.Instance != null)
TouchManager.Instance.PointersPressed -= pointersPressedHandler;
}
private void pointersPressedHandler(object sender, PointerEventArgs e)
{
foreach (var pointer in e.Pointers)
spawnPrefabAt(pointer.Position);
}
- TapGesture,
- LongPressGesture.
- Double tap the table to spawn a new crate,
- Tap a crate to kick it,
- Hold a crate to blow it up.
/Scene/Container/Cube GameObjects have the following components attached:
- LongPressGesture which is used by Break script to blow up the cube,
- PressGesture which is used by Break script to start the color tween,
- TapGesture which is used by Kick script to push the cube,
- Kick which kicks the cube on tap,
-
Break which breaks the cube into 8 small cubes. It shows how to use
StateChanged
event:
longPressGesture.StateChanged += longPressedHandler;
private void longPressedHandler(object sender, GestureStateChangeEventArgs e)
{
if (e.State == Gesture.GestureState.Recognized)
{
...
}
else if (e.State == Gesture.GestureState.Failed)
{
stopGrowing();
}
}
We use StateChanged
event here instead of simpler LongPressed
because we need to handle GestureState.Failed
.
/Scene/table_and_chair GameObject has a TapGesture component attached with Number of Taps Required set to Two
and Limit Time to 1 sec
. This means that we want a double-tab with 1 sec max interval between taps. Spawn component uses the TapGesture to spawn new cubes.
This example shows how to write and use custom gestures.
It is available as a separate tutorial.