I am trying to convert pinch to zoom from old input to new Input system using EnhancedTouch.Touch. Unfortunately I am clueless as to how to move forward from here? I am getting error as Operator '==' cannot be applied to operands of type 'TouchPhase' and 'TouchPhase'. How do I fix this?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.EnhancedTouch;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
public class ZoomTouch : MonoBehaviour {
public Camera camera;
float touchDist = 0;
float lastDist = 0;
public void Update () {
if (Input.touchCount == 2) {
Touch touch1 = Touch.activeFingers[0].currentTouch;
Touch touch2 = Touch.activeFingers[0].currentTouch;
if (touch1.phase == TouchPhase.Began && touch2.phase == TouchPhase.Began) {
lastDist = Vector2.Distance (touch1.position, touch2.position);
}
if (touch1.phase == TouchPhase.Moved && touch2.phase == TouchPhase.Moved) {
float newDist = Vector2.Distance (touch1.position, touch2.position);
touchDist = lastDist - newDist;
lastDist = newDist;
camera.fieldOfView += touchDist * 0.1f;
}
}
}
}
I hope this code works. However, I did not have a touch device to test it. This simple code works, takes the distance between the present and the past, and zooms in on their delta.
public float lastDistance;
public float distance;
void Update()
{
if (Input.touchCount < 2) return;
var touch1 = Input.GetTouch(0);
var touch2 = Input.GetTouch(1);
distance = Vector2.Distance(touch1.position, touch1.position);
if (Mathf.Abs(lastDistance-distance) >= 10) lastDistance = distance; // for avoiding sharp zooms on first touch
Camera.main.fieldOfView += distance-lastDistance * 0.1f;
lastDistance = distance;
}
Related
Player movement is working (at least somewhat) now, however one issue remains, and that's the insane numbers the y velocity of the Rigidbody2D on the player. Since the isGrounded check I plan to add will use velocity for the sake of stability, this needs to be fixed.
It confuses me, considering the velocity is 0 normally, but whenever moving left or right it changes to said high numbers.
Movement code:
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
public class PlayerM : MonoBehaviour
{
private PControls control;
Rigidbody2D rb;
SpriteRenderer sp;
Transform tr;
public float speed = 0f;
public float speedC;
public float heightSpeed = 5f;
public float heightC;
public bool grounded;
void Start()
{
control = new PControls();
control.Enable();
rb = GetComponent<Rigidbody2D>();
sp = GetComponent<SpriteRenderer>();
tr = GetComponent<Transform>();
}
// Update is called once per frame
void FixedUpdate()
{
RaycastHit2D hit = Physics2D.Raycast(rb.position, -Vector2.up);
Color color = new Color(0, 0, 1.0f);
Debug.DrawRay(transform.position, Vector2.down);
speedC = rb.velocity.magnitude;
var pos = control.Movement.Move.ReadValue<float>();
float GetVerticalSpeed() => rb.velocity.y;
if(pos == -1)
{
sp.flipX = true;
}
else if(pos == 1)
{
sp.flipX = false;
}
if((pos == 0) && (speed > 0.1f))
{
speed -= 3f * Time.deltaTime;
}
else if(speed < 1.4f)
{
speed += Mathf.Abs(pos) * 8 * Time.deltaTime;
}
if(speedC < 7f)
{
rb.AddForce(new Vector3((pos * 5), 0f) * speed * Time.deltaTime, ForceMode2D.Impulse);
}
var jump = control.Movement.Jump.ReadValue<float>();
Debug.Log(GetVerticalSpeed());
Vector3 v = rb.velocity;
v.y = 10;
if(jump == 1)
{
rb.velocity = v;
}
}
}
Seems the main issue was fixed by converting the height velocity to an integer using System.Math.Round():
float vel = rb.velocity.y;
heightC = (int)System.Math.Round(vel);
Not sure it's the best solution, but it's something..
I am trying to use zoom with two fingers but unfortunately whenever I place two fingers together, the starting value of camera.fieldOfView changes drastically. As in it is not able to read the current value. I feel it goes to some other value. It should start from the current value. What am I doing wrong here?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.InputSystem.EnhancedTouch;
using Touch = UnityEngine.InputSystem.EnhancedTouch.Touch;
public Camera camera;
float touchDist = 0;
float lastDist = 0;
public float maxAngle = 60;
public float minAngle = 30;
private void Start()
{
EnhancedTouchSupport.Enable();
}
public void Update()
{
if (Touch.activeFingers.Count == 2)
{
Touch activeTouch = Touch.activeFingers[0].currentTouch;
Touch touch1 = Touch.activeFingers[0].currentTouch;
Touch touch2 = Touch.activeFingers[1].currentTouch;
if (touch1.phase == UnityEngine.InputSystem.TouchPhase.Began && touch2.phase == UnityEngine.InputSystem.TouchPhase.Began)
{
lastDist = Vector2.Distance(touch1.screenPosition, touch2.screenPosition);
}
if (touch1.phase == UnityEngine.InputSystem.TouchPhase.Moved && touch2.phase == UnityEngine.InputSystem.TouchPhase.Moved)
{
float newDist = Vector2.Distance(touch1.screenPosition, touch2.screenPosition);
touchDist = lastDist - newDist;
lastDist = newDist;
// Your Code Here
camera.fieldOfView += touchDist * 0.05f;
if (camera.fieldOfView > maxAngle)
{
camera.fieldOfView = maxAngle;
}
if (camera.fieldOfView < minAngle)
{
camera.fieldOfView = minAngle;
}
}
}
}
}
I am looking for following implementation in unity based touch game:
I need object to rotate with the touch so it can be viewed from all sides(As long as touch is moving)
The object should keep on rotating in direction of previous touch
movement (when touch ends)
I tried implementing below code. But rotation is quiet quirky. It sometime rotates too fast sometimes in opposite direction of the swipe etc.
Here is what i have tried:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Functionalities : MonoBehaviour
{
public GameObject m_objecttorotate;
Vector3 localAngle;
[SerializeField]
float rotateSpeed = 0.09f;
Touch touchZero;
Vector3 rotateAxis;
float newMouseYpos = 0;
float prevMouseYpos = 0;
bool isIncreasing;
bool isDecreasing;
bool rotateManually;
void Update()
{
if (Input.touchCount > 0)
{
touchZero = Input.GetTouch(0);
//Rotate the model based on offset
localAngle = m_objecttorotate.transform.localEulerAngles;
localAngle.y -= rotateSpeed * touchZero.deltaPosition.x;
m_objecttorotate.transform.localEulerAngles = localAngle;
if (touchZero.deltaPosition != Vector2.zero)
{
rotateAxis = touchZero.deltaPosition;
}
}
else
{
localAngle.y += rotateSpeed * rotateAxis.y;
m_objecttorotate.transform.localEulerAngles = localAngle;
}
CheckIfTouchIsMovingUpOrDown();
if (isIncreasing)
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, -0.25f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
else if (isDecreasing)
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, 0.25f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
else
{
Vector3 newPos = new Vector3(m_objecttorotate.transform.position.x, 0f, m_objecttorotate.transform.position.z);
m_objecttorotate.transform.position = Vector3.Lerp(m_objecttorotate.transform.position, newPos, 1 * Time.deltaTime);
}
}
void CheckIfTouchIsMovingUpOrDown()
{
if (Input.GetMouseButton(0))
{
if (prevMouseYpos != newMouseYpos)
{
if (prevMouseYpos < newMouseYpos + 1f)
{
isIncreasing = true;
isDecreasing = false;
Debug.Log("Increasing");
prevMouseYpos = newMouseYpos;
}
else if (prevMouseYpos > newMouseYpos - 1f)
{
isDecreasing = true;
isIncreasing = false;
Debug.Log("Decreasing");
prevMouseYpos = newMouseYpos;
}
}
newMouseYpos = Input.mousePosition.y;
}
else
{
//isDecreasing = false;
// isIncreasing = false;
prevMouseYpos = newMouseYpos;
}
}
}
Trying to build an AR app where I can have a number of input touch like drag, rotate, scale, double tap to event, hold on object to event etc.
Everything works fine in a test scene I have built [not AR].
Once included the code in my AR placedOnPlane prefab [template scene - place on plane], once I touch the object, it disappears, and I cannot figure out what I am doing wrong!
Finally, I took advantage of LeanTouch and everything works fine (why? because it's a badass asset), but I usually hate using assets when I have my code that is working equally good and I spent days on it! Some help please.
I tried commenting out the built in drag function in the PlacedOnPlane code that comes with the scene of ARfoundation but it didn't work.
using UnityEngine;
using System.Collections;
using UnityEngine.iOS;
public class InputTouchUnity : MonoBehaviour
{
private Vector3 position;
private float width;
private float height;
public float speedDrag= 0.1f;
float initialFingersDistance;
float speedTwist = -4000f;
private float baseAngle = 0.0f;
Vector3 initialScale;
// scale clamp
//public float scalingSpeed = 0.03f;
public Vector3 min = new Vector3(292f, 292f, 292f);
public Vector3 max = new Vector3(800f, 800f, 800f);
// int tapCount;
// float doubleTapTimer;
void Awake()
{
width = (float)Screen.width / 2.0f;
height = (float)Screen.height / 2.0f;
//Position used for the cube.
position = this.transform.position;
}
void OnGUI() // TO OBSERVE MOTION
{
// Compute a fontSize based on the size of the screen width.
GUI.skin.label.fontSize = (int)(Screen.width / 25.0f);
GUI.Label(new Rect(20, 20, width, height * 0.25f),
"x = " + position.x.ToString("f2") +
", y = " + position.z.ToString("f2"));
}
void Update()
{
// Handle screen touches.
if (Input.touchCount > 0)
{
RaycastHit hit;
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
if (Physics.Raycast(ray, out hit))
initialScale = transform.localScale;
{
{
{
//DRAG - got rid of it because conflicting the AR drag
Touch touch = Input.GetTouch(0);
Move the cube if the screen has the finger moving.
if (Input.touchCount == 2)
{
if (touch.phase == TouchPhase.Moved)
{
Vector2 pos = touch.position;
pos.x = (pos.x - width) / width;
pos.y = (pos.y - height) / height;
position = new Vector3(transform.position.x + pos.x * speedDrag, 0, transform.position.y + pos.y * speedDrag);
// Position the cube.
transform.position = position;
}
}
//SCALE
if (Input.touchCount == 2)
{
Touch touch1 = Input.GetTouch(0);
if (touch1.phase == TouchPhase.Began)
{
initialFingersDistance = Vector2.Distance(Input.touches[0].position , Input.touches[1].position);
initialScale = transform.localScale;
}
else
{
var currentFingersDistance = Vector2.Distance(Input.touches[0].position, Input.touches[1].position);
var scaleFactor = (currentFingersDistance / initialFingersDistance );
transform.localScale = initialScale * scaleFactor;
Debug.Log(transform.localScale);
GameObject[] models = GameObject.FindGameObjectsWithTag ("ARobject");
newScale.x = Mathf.Clamp(model.localScale.x - scaleFactor, min.x, max.x);
newScale.y = Mathf.Clamp(model.localScale.y - scaleFactor, min.y, max.y);
newScale.z = Mathf.Clamp(model.localScale.z - scaleFactor, min.z, max.z);
model.localScale = newScale;
}
}
//TWIST
if (Input.touchCount == 2)
{
Touch touch2 = Input.GetTouch(0);
if (touch2.phase == TouchPhase.Began)
{
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
pos = Input.mousePosition - pos;
baseAngle = Mathf.Atan2(pos.y, pos.x) * Mathf.Deg2Rad;
baseAngle -= Mathf.Atan2(transform.right.y, transform.right.x) * Mathf.Rad2Deg;
}
if (touch2.phase == TouchPhase.Moved)
{
Vector3 pos = Camera.main.WorldToScreenPoint(transform.position);
pos = Input.mousePosition - pos;
float ang = Mathf.Atan2(pos.y, pos.x) * Mathf.Deg2Rad - baseAngle;
transform.rotation = Quaternion.AngleAxis(ang * speedTwist, Vector3.up);
}
}
}
}
}
}
}
}
//}
This is because you are using Physics.Raycast which does't work on AR trackables(Planes) because they don't have any specific geometry associated with them.
So to interact with trackable data unity has provided separate Raycast method that is available in ARRaycastManager in ARFoundation.
In previous version of ARFoundation it was available in ARSessionOrigin. So check which version you are using of Ar Foundation.
You can use it like this
enter code here
`
[SerializeField] ARRaycast​Manager raycastManager;
void Update()
{
if (Input.touchCount == 0)
return;
Touch touch = Input.GetTouch(0);
if (raycastManager.Raycast(touch.position,s_Hits,TrackableType.PlaneWithinPolygon))
{
// Raycast hits are sorted by distance, so the first one
// will be the closest hit.
var hitPose = s_Hits[0].pose;
if (spawnedObject == null)
{
spawnedObject = Instantiate(cube, hitPose.position, hitPose.rotation);
}
else
{
spawnedObject.transform.position = hitPose.position;
}
}
}
`
You can also refer to SimpleAR scene from Ar Foundation sample scenes available here: https://github.com/Unity-Technologies/arfoundation-samples
Edit : I need an answer for a 2D implementation, not 3D. So the 'Asked Before' question doesn't work for my project.
Edit : Using the accepted answer below, this is my working script. It's slightly off because the 0.1F part of the Vector3 is hard to get right, but it works. Time.deltaTime didn't work though.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour
{
private float zoom = 10;
Vector3 newPosition;
void Update()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
Camera.main.orthographicSize = zoom;
newPosition = Camera.main.ScreenToWorldPoint(Input.mousePosition);
transform.position = Vector3.Lerp(transform.position, newPosition, 0.1F);
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
Camera.main.orthographicSize = zoom;
}
}
}
Original Question : I have a basic script for zooming in and out, but when I zoom back in with the mouse-wheel, I want to zoom in to the point of the mouse cursor. I think you can see something similar in the Paradox Games (EU4 etc), where you zoom out, hold your mouse over a country off to the left of the screen, then zoom in and the country zooms in and becomes centered.
Here's my basic script so far, attached to my camera, which just zooms in and out in a straight line.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour {
public float zoom = 10F;
void Update () {
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
}
GetComponent<Camera>().orthographicSize = zoom;
}
}
I haven't tried this myself but I hope this will work.
Vector3 newPosition;
bool canZoom;
bool isMoving;
void Update ()
{
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
canZoom = true;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
canZoom = true;
}
if (canZoom)
{
isMoving = true;
Camera.main.orthographicSize = zoom;
newPosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
}
if (isMoving)
{
transform.position = Vector3.Lerp (transform.position, newPosition, Time.deltaTime);
}
if(transform.position == newPosition)
{
isMoving = false;
}
}
Note: If you want the camera to maintain certain camera height, adjust newPosision's y value before moving.
Hope this helps.
Calculate the difference in world space and move towards it while zooming.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraZoom : MonoBehaviour {
public float zoom = 10F;
void Update () {
if (Input.GetAxis("Mouse ScrollWheel") > 0 && zoom > 9)
{
zoom -= 1;
}
if (Input.GetAxis("Mouse ScrollWheel") < 0 && zoom < 101)
{
zoom += 1;
}
Camera cam = GetComponent<Camera>();
RaycastHit hit;
Ray ray = cam.ScreenPointToRay(Input.mousePosition);
Vector3 targetPos;
if (Physics.Raycast(ray , out hit))
{
targetPos = hit.point;
}
Camera cam = GetComponent();
cam.orthographicSize = zoom;
cam.transform.position += (targetPos - transform.position) / 5f;
}
}