EDIT: Added my swipe class, which detects swipes and stores swipe speed, swipe direction, swipe started/ended etc…it seems that this code slows my FPS down by 5-10fps. I use the stored values of this class from another class, to decide what actions to take.
using UnityEngine;
using System.Collections;
public class Swipe : MonoBehaviour {
// Singleton access
private static Swipe _instance = null;
public static Swipe Instance
{
get{
if( _instance == null )
{
_instance = FindObjectOfType( typeof( Swipe )) as Swipe;
if( !_instance )
_instance = new GameObject( "Swipe" ).AddComponent<Swipe>();
}
return _instance;
}
}
// Enums
public enum SwipeType
{
HORIZONTAL,
VERTICAL,
BOTH
}
public SwipeType swipeType;
private enum SwipeDirection
{
NONE,
SWIPE_LEFT,
SWIPE_RIGHT,
SWIPE_UP,
SWIPE_DOWN
}
private SwipeDirection swipeDirection = SwipeDirection.NONE;
// Public vars accessible in editor
public bool constantDetection = false; // Turn on to always detect swipes anywhere, not just on specific UI element
public float swipeSpeed = 1f;
public float minSwipeDistance = 0.65f;
public float swipeDeadZone = 0.1f;
public string eventName;
public Camera customUICam;
// Private variables
private Vector2 _touchStart, _touchEnd, _lastPos,
_currentTouch, _moveAmount;
private float _comfortZone;
private float _swipeVelocity;
private float _swipeDist;
private float _minSwipeDist;
private GameObject _swipeObj;
private bool _couldBeSwipe;
private bool _swipeSuccess;
private bool _touchEnded;
private bool _swipeEnded;
private bool _touchControls, _mouseControls;
#region Getter and Setters
public Vector2 CurrentTouchPos
{
get{ return _currentTouch; }
}
public Vector2 TouchStart
{
get{ return _touchStart; }
set{ _touchStart = value; }
}
public Vector2 TouchEnd
{
get{ return _touchEnd; }
}
public Vector2 MoveAmount
{
get{ return _moveAmount; }
set{ _moveAmount = value; }
}
public float SwipeVelocity
{
get{ return _swipeVelocity; }
set{ _swipeVelocity = value; }
}
public float ComfortZone
{
get{ return _comfortZone; }
}
public float SwipeDist {
get{ return _swipeDist; }
}
public float MinSwipeDist
{
get{ return _minSwipeDist; }
}
public GameObject SwipeObj
{
get{ return _swipeObj; }
}
public bool SwipingLeft { get{ return ( swipeDirection == SwipeDirection.SWIPE_LEFT ); }}
public bool SwipingRight { get{ return ( swipeDirection == SwipeDirection.SWIPE_RIGHT ); }}
public bool SwipingUp { get{ return ( swipeDirection == SwipeDirection.SWIPE_UP ); }}
public bool SwipingDown { get{ return ( swipeDirection == SwipeDirection.SWIPE_DOWN ); }}
public bool CouldBeSwipe
{
get{ return _couldBeSwipe; }
set{ _couldBeSwipe = value; }
}
public bool SwipeSuccess
{
get{ return _swipeSuccess; }
}
public bool TouchEnded
{
get{ return _touchEnded; }
}
public bool SwipeEnded
{
get{ return _swipeEnded; }
}
#endregion
void OnEnable()
{
_instance = this;
}
// =============================================== AWAKE FUNCTION =============================================== //
void Awake()
{
if( !_instance ) _instance = this;
// Set correct control types depending on platform
if( Application.platform == RuntimePlatform.IPhonePlayer ||
Application.platform == RuntimePlatform.Android )
{
_touchControls = true;
_mouseControls = false;
}
else
{
_touchControls = false;
_mouseControls = true;
}
if( !UICamera.mainCamera )
{
if( !customUICam )
{
customUICam = FindObjectOfType( typeof( Camera )) as Camera;
if( !customUICam )
{
Debug.Log("There are no cameras in the scene! In this case, the Swipe won't check for ray collision with gameObjects.");
}
}
}
}
// =============================================== START FUNCTION =============================================== //
void Start()
{
// Initialize class members
_currentTouch = Vector2.zero;
_touchStart = Vector2.zero;
_touchEnd = Vector2.zero;
_lastPos = Vector2.zero;
_moveAmount = Vector2.zero;
_swipeVelocity = 0f;
_comfortZone = Screen.width * swipeDeadZone;
_minSwipeDist = Screen.width * minSwipeDistance;
_couldBeSwipe = false;
_swipeSuccess = false;
_touchEnded = false;
_swipeEnded = false;
}
// =============================================== UPDATE FUNCTION =============================================== //
void Update ()
{
if( constantDetection ) DetectSwipe( _comfortZone, _minSwipeDist, swipeType );
}
// ================================================================================================================================ //
// ======================================================= CUSTOM FUNCTIONS ======================================================= //
// ================================================================================================================================ //
// =============================================== SWIPE HORIZONTAL FUNCTION =============================================== //
private void DetectSwipe( float deadZone, float minSwipeDist, SwipeType sType )
{
// ********* TOUCH INPUTS ********* //
if( _touchControls )
{
// Stop if no touches are happening
if( Input.touches == null ) return;
// Iterate through all touches
foreach( Touch touch in Input.touches )
{
// Store the swipe distance
_swipeDist = ( touch.position - _touchStart ).magnitude;
switch( touch.phase )
{
case TouchPhase.Began:
ResetSwipeStates( true );
_touchStart = touch.position;
_lastPos = touch.position;
break;
case TouchPhase.Moved:
if( Mathf.Abs( _swipeDist ) > deadZone )
{
_swipeObj = GetSwipedObject( touch.position );
_swipeVelocity = touch.deltaPosition.magnitude * touch.deltaTime * 10;
_couldBeSwipe = true;
_swipeEnded = false;
_touchEnd = touch.position;
// Track touch position to see how much we move
_moveAmount += touch.deltaPosition * swipeSpeed;
_moveAmount.x *= (( Screen.width - _swipeDist ) / Screen.width ) * Time.deltaTime;
// Are we swipping left or right?
swipeDirection = GetSwipeDirection( sType, touch.deltaPosition );
// print("USING TOUCH FOR SWIPE");
}
//print("Swipe Distance: " + _swipeDist );
//print("Move Amount: " + _moveAmount );
//print("Touch Range: " + Mathf.Abs( touch.position.x - _touchStart.x) );
break;
case TouchPhase.Stationary:
_moveAmount = Vector2.zero;
_swipeEnded = true;
break;
case TouchPhase.Ended:
// Check how long the swipe was, and check the swipe direction
if( _couldBeSwipe )
{
_moveAmount = Vector2.zero;
_swipeEnded = true;
// When swipe ends, get the swipe direction again, but this time use
// the start position of the touch to calculate the swipe direction.
// This is required for events that take place AFTER the swipe ended,
// like the Level Select Screen which changes screen depending on the
// swipe direction.
swipeDirection = GetSwipeDirection( sType, touch.position, _touchStart );
// Check how long the swipe was, and check the swipe direction
// Debug.Log("_swipeDist: " + Mathf.Abs( _swipeDist ) + " | minsSwipeDist: " + minSwipeDist);
if( _swipeDist > minSwipeDist )
{
_swipeSuccess = true;
}
else
{
print("SWIPE NOT LONG ENOUGH");
_swipeSuccess = false;
}
}
ResetSwipeStates( false );
break;
}
}
return; // End of touch controls
}
// ********* MOUSE INPUTS ********* //
if( _mouseControls )
{
Vector2 mPos = new Vector2( Input.mousePosition.x, Input.mousePosition.y );
Vector2 mAxis = new Vector2( Input.GetAxis( "MouseX" ), Input.GetAxis( "MouseY" ));
if( Input.GetMouseButtonDown( 0 ))
{
ResetSwipeStates( true );
_touchStart = mPos;
_lastPos = mPos;
}
if( Input.GetMouseButton( 0 ) )
{
// var delta = mPos - _lastPos;
// Store the swipe distance
_swipeDist = ( mPos - _touchStart ).magnitude;
if( Mathf.Abs( _swipeDist ) > deadZone )
{
_swipeObj = GetSwipedObject( mPos );
_swipeVelocity = mAxis.magnitude * Time.deltaTime * 10;
_couldBeSwipe = true;
_swipeEnded = false;
_touchEnd = mPos;
// Track touch position to see how much we move
_moveAmount = mAxis * swipeSpeed * Time.deltaTime;
// Debug.Log("Move Amount: " + _moveAmount);
// While swiping, are we swipping left or right?
swipeDirection = GetSwipeDirection( sType, mAxis );
print("USING MOUSE FOR SWIPE");
}
_lastPos = mPos;
// Stationary
if( mAxis.magnitude == 0f )
{
_swipeEnded = true;
}
}
else
{
// _couldBeSwipe gets turned off after changing screens, in 'UI_LevelSelection'
if( _couldBeSwipe && !_touchEnded )
{
_moveAmount = Vector2.zero;
// When swipe ends, get the swipe direction again, but this time use
// the start position of the touch to calculate the swipe direction.
// This is required for events that take place AFTER the swipe ended,
// like the Level Select Screen which changes screen depending on the
// swipe direction.
swipeDirection = GetSwipeDirection( sType, mPos, _touchStart );
// Check how long the swipe was, and check the swipe direction
// Debug.Log("_swipeDist: " + Mathf.Abs( _swipeDist ) + " | minsSwipeDist: " + minSwipeDist);
if( Mathf.Abs( _swipeDist ) > minSwipeDist )
{
_swipeSuccess = true;
}
else
{
print("SWIPE NOT LONG ENOUGH");
_swipeSuccess = false;
}
}
ResetSwipeStates( false );
}
return; // End of mouse controls
}
}
// =============================================== RESET SWIPE STATES FUNCTION =============================================== //
/// <summary>
/// Resets the swipe states, at the begining or end of swipe.
/// </summary>
/// <param name='touchBegan'>
/// Boolean: is this being called on TouchPhase.Began/Input.GetMouseButtonDown (different values get reset at begining of new touch/input)?
/// </param>
public void ResetSwipeStates( bool touchBegan )
{
// Make sure to reset boolean flags
_moveAmount = Vector2.zero;
if( touchBegan )
{
_touchEnded = false;
_couldBeSwipe = false;
_swipeSuccess = false;
}
else
{
_touchEnded = true;
}
}
// =============================================== SWIPE DIRECTION FUNCTIONS =============================================== //
/// <summary>
/// Gets the direction of the current swipe.
/// </summary>
/// <returns>
/// Enum Value: The swipe direction (LEFT/RIGHT/UP/DOWN).
/// </returns>
/// <param name='sType'>
/// SwipeType: The type of swipe (HORIZONTAL/VERTICAL/BOTH).
/// </param>
/// <param name='tDeltaPos'>
/// Vector2: The delta position of the current touch (same as touch.position - lastPos).
/// </param>
private SwipeDirection GetSwipeDirection( SwipeType sType, Vector2 tDeltaPos )
{
// Here we're using the deltaPosition of the current touch/mous position.
// The delta position is equivalent to touch.position - lastPos.
switch( sType )
{
case SwipeType.HORIZONTAL:
if( tDeltaPos.x < 0 )
{
// Debug.Log("SWIPING LEFT!");
return SwipeDirection.SWIPE_LEFT;
}
else if( tDeltaPos.x > 0 )
{
// Debug.Log("SWIPING RIGHT!");
return SwipeDirection.SWIPE_RIGHT;
}
break;
case SwipeType.VERTICAL:
if( tDeltaPos.y < 0 )
{
// Debug.Log("SWIPING DOWN!");
return SwipeDirection.SWIPE_DOWN;
}
else if( tDeltaPos.y > 0 )
{
// Debug.Log("SWIPING UP!");
return SwipeDirection.SWIPE_UP;
}
break;
}
// Return NONE if none of the above are true
// Debug.Log("SWIPING NONE!");
return SwipeDirection.NONE;
}
/// <summary>
/// Get the gameObject being swiped on.
/// </summary>
/// <returns>
/// GameObject: The swiped gameObject.
/// </returns>
/// <param name='touchPosition'>
/// Vector2: Current position of touch/input.
/// </param>
private GameObject GetSwipedObject( Vector2 touchPosition )
{
Camera cam = UICamera.mainCamera ? UICamera.mainCamera : customUICam;
if( !cam ) return gameObject;
else
{
Ray ray = cam.ScreenPointToRay( touchPosition );
RaycastHit hit;
if( Physics.Raycast( ray, out hit ))
{
// Debug.LogWarning("Swipping ON: " + hit.transform.gameObject.name );
// Debug.Log("Raycasting Camera: " + cam.name);
return hit.transform.gameObject;
}
// If the ray doesn't hit any object, then return the game object this script is attached to
return gameObject;
}
}
public void OnApplicationQuit()
{
_instance = null;
}
}
And from my GUI_Controls class, I access values stored in Swipe() to decide which actions to take:
using UnityEngine;
using System.Collections;
public class GUI_Controls : MonoBehaviour {
public Swipe swipe;
public bool forceControlsOn = false; // Used to bypass game state check
public float preloadMinDist = 200f;
public bool iphoneControls = true;
public bool mouseControls = false;
public GameObject preloadBtn;
public bool preloadOn = false;
// =============================== AWAKE FUNCTION =============================== //
void Awake ()
{
if( !this.enabled ) return;
}
// =============================== STAR FUNCTION =============================== //
void Start ()
{
if( !forceControlsOn )
{
if( !GameStates.initDone )
{
Debug.LogWarning("Disabling gui controls. ~ " + this);
this.enabled = false;
return;
}
}
if( Application.platform != RuntimePlatform.IPhonePlayer )
iphoneControls = false;
else
iphoneControls = true;
// Get the Swipe class
swipe = Swipe.Instance;
}
// =============================== UPDATE FUNCTION =============================== //
void Update() {
if( !forceControlsOn )
{
// ................
}
else
{
// Check for preload conditions
if( swipe.SwipeObj == preloadBtn && swipe.SwipingUp )
{
CheckForPreload( swipe.SwipeDist );
}
}
}
// ================================================= SWIPE CONTROLS (preload/scrub) ================================================= //
// Keeping simple functions like 'CheckForPreload', which itself calls a more advanced function,
// lets us add simple event listeners with only 1-2 parameters, if needed
public void CheckForPreload( float swipeDistance )
{
CheckForSwipeControlState( swipeDistance, preloadMinDist, "PRELOAD", ref preloadOn );
}
public void CheckForSwipeControlState( float swipeDistance, float minSwipeDist, string controlName, ref bool controlOn )
{
if( this.enabled )
{
if( !forceControlsOn )
{
// ..............
}
else
{
if( !swipe.TouchEnded )
{
if( swipeDistance > minSwipeDist )
{
controlOn = true;
}
}
if( swipe.TouchEnded || swipe.SwipeEnded ) controlOn = false;
}
}
Debug.LogWarning("swipeDistance: " + swipeDistance, this);
}
}
There it is…hopefully someone can see something I’m not seeing and help me figure out why swiping 1 finger on the screen slows my frame-rate down. Also, if I’m doing anything BAD in my classes above, please don’t be afraid to let me know I take criticism very well
Thanks!
===================================================================================
OLD: I realize that they are not free, but I have seen my FPS drop by 10fps when swiping on the screen! That was never an issue before so I wonder if the latest Unity update has anything to do with it.
Also, is it faster to use:
int count = Input.touchCount;
for( t = 0; t < count; t++ )
{
Touch touch = Input.GetTouch(t);
// Process touch phases/events
}
// Or use:
foreach( Touch touch in Input.touches )
{
// process touch phases/events
}
Should I really be expecting my FPS to drop by 10 when swiping on the screen? Just touching the screen is fine, it’s only when I start swiping that it takes a hit.
Thanks…