I am working on a script to move an object back anf forth based on swipe similarly to a game called Sky Rusher on the iOS App Store. The movement in the original game lets you swipe in any direction and an object moves in the same direction. However, the object also "bounces" for lack of a better term. For example, if you swipe to the left, the object will tilt to the left and then tilt back to its original position. For the best example I can give, please take a look at this video for a demonstartion of the game:
Sky Rusher Gameplay
This is the code I currently have (the object also doesn't move back and forth when swiping, not sure what==y that is but have an idea on how to fix it):
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MovePlayer : MonoBehaviour
{
private Vector3 currentPos;
private Vector3 touchPos;
private float screenWidth;
private float screenHeight;
private float touchX;
private float touchY;
private float objectX;
private float objectY;
// Start is called before the first frame update
void Start()
{
touchX = 0;
touchY = 0;
screenWidth = (float)Screen.width / 2.0f;
screenHeight = (float)Screen.height / 2.0f;
currentPos = new Vector3(0.0f, 1.0f, 0.0f);
}
// Update is called once per frame
void Update()
{
if(Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
if(touch.phase == TouchPhase.Moved)
{
//touchPos = new Vector3((touch.position.x - screenWidth)/screenWidth, (touch.position.y - screenHeight)/screenHeight + 1, 0.0f);
touchPos = new Vector3(touch.position.x, touch.position.y, 0.0f);
touchX = (touchPos.x - screenWidth)/screenHeight - 1f;
touchY = (touchPos.y - screenHeight)/screenHeight + 1f;
//objectX = ((currentPos.x * screenWidth) - screenWidth)/screenWidth;
//objectY = ((currentPos.y * screenHeight) - screenHeight)/screenHeight;
objectX = currentPos.x;
objectY = currentPos.y;
objectX += (touchX - objectX) * 1.5f;
//objectY += (touchY - objectY) * 1.5f;
if(touchX >= 0.9f)
{
objectX+=0.05f;
}
else if(touchX <= -0.9f)
{
objectX-=0.05f;
}
currentPos = new Vector3(objectX, objectY, 0.0f);
transform.position = currentPos;
}
}
}
void OnGUI()
{
/*
// Compute a fontSize based on the size of the screen width.
GUI.skin.label.fontSize = (int)(Screen.width / 40.0f);
GUI.Label(new Rect(20, 20, screenWidth, screenHeight * 0.25f),
"Pos: x = " + (objectX.ToString("f2")) +
", y = " + objectY.ToString("f2"));
GUI.Label(new Rect(20, 50, screenWidth, screenHeight * 0.25f),
"Touch: x = " + (touchX.ToString("f2")) +
", y = " + (touchY.ToString("f2")));
*/
}
}
I need my object to tilt when moved similarly to how it is done in sky rusher. My game is played in a landscape orientation on an iOS Device using Unity Remote 5 and Unity 2018.3.
Quick way to achieve this effect, if I understood correctly what you mean:
1) Each time touchX >= .9f (you are moving right) apply localRotation along Z axis with some angle.
2) Each time touchX <= -.9f (you are moving left) apply localRotation along Z axis with some negative angle.
To make this look smooth and not jumpy, apply rotation along several frames, first calculating target rotation, then using RotateTowards with some given speed. Here is yourr code slightly modified:
public float tiltEffectAngle = 20;
public float tiltEffectSpeed = 90f;
void Update() {
var targetRotation = Quaternion.identity;
if (Input.touchCount > 0) {
Touch touch = Input.GetTouch(0);
if (touch.phase == TouchPhase.Moved) {
//touchPos = new Vector3((touch.position.x - screenWidth)/screenWidth, (touch.position.y - screenHeight)/screenHeight + 1, 0.0f);
touchPos = new Vector3(touch.position.x, touch.position.y, 0.0f);
touchX = (touchPos.x - screenWidth) / screenHeight - 1f;
touchY = (touchPos.y - screenHeight) / screenHeight + 1f;
//objectX = ((currentPos.x * screenWidth) - screenWidth)/screenWidth;
//objectY = ((currentPos.y * screenHeight) - screenHeight)/screenHeight;
objectX = currentPos.x;
objectY = currentPos.y;
objectX += (touchX - objectX) * 1.5f;
//objectY += (touchY - objectY) * 1.5f;
if (touchX >= 0.9f) {
objectX += 0.05f;
targetRotation = Quaternion.Euler(
transform.localEulerAngles.x,
transform.localEulerAngles.y,
tiltEffectAngle);
} else if (touchX <= -0.9f) {
objectX -= 0.05f;
targetRotation = Quaternion.Euler(
transform.localEulerAngles.x,
transform.localEulerAngles.y,
-tiltEffectAngle);
}
currentPos = new Vector3(objectX, objectY, 0.0f);
transform.position = currentPos;
}
}
transform.localRotation = Quaternion.RotateTowards(transform.localRotation, targetRotation, tiltEffectSpeed * Time.deltaTime);
}
Related
How do I limit the touch space to the right side of the screen so that it only registers the right side touches. Left side touch nothing will happen. How am I able to do it with this script? Been trying out for the past 2 days still cannot figure anything out. Any experts able to help me out?
public class look2 : MonoBehaviour
{
private Vector3 firstpoint; //change type on Vector3
private Vector3 secondpoint;
private float xAngle = 0.0f; //angle for axes x for rotation
private float yAngle = 0.0f;
private float xAngTemp = 0.0f; //temp variable for angle
private float yAngTemp = 0.0f;
public GameObject character;
void Start()
{
//Initialization our angles of camera
xAngle = 0.0f;
yAngle = 0.0f;
this.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
character.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
}
void Update()
{
//Check count touches
if (Input.touchCount > 0)
{
//Touch began, save position
if (Input.GetTouch(0).phase == TouchPhase.Began)
{
firstpoint = Input.GetTouch(0).position;
xAngTemp = xAngle;
yAngTemp = yAngle;
}
//Move finger by screen
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
secondpoint = Input.GetTouch(0).position;
//Mainly, about rotate camera. For example, for Screen.width rotate on 180 degree
xAngle = xAngTemp + (secondpoint.x - firstpoint.x) * 180.0f / Screen.width;
yAngle = yAngTemp - (secondpoint.y - firstpoint.y) * 90.0f / Screen.height;
//Rotate camera
this.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
character.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
}
}
}
}
You can use Screen.width to get exactly that: The width of the device's screen in pixels.
Since the Touch.position is also in screen pixel space the right half of the screen is as simple as any touch having
touch.position.x > Screen.width / 2f
you could also use >= depending whether you want one pixel more or less ;)
And then you could simply filter the touches on that condition before accessing them e.g. using Linq Where
var validTouches = Input.touches.Where(touch => touch.position.x > Screen.width / 2f).ToArray();
This is basically short for doing something like
var touches = new List<Touch>();
foreach(var touch in Input.touches)
{
if(touch.position.x > Screen.width / 2f)
{
touches.Add(touch);
}
}
var validTouches = touches.ToArray();
So your code could look like
using System.Linq;
...
void Update()
{
//Check count touches
if (Input.touchCount > 0)
{
// Now collect only touches being on the left half of the screen
var validTouches = Input.touches.Where(touch => touch.position.x > Screen.width / 2f).ToArray();
if(validTouches.Length > 0)
{
var firstTouch = validTouches[0];
// Better use switch here
switch(firstTouch.phase)
{
case TouchPhase.Began:
firstpoint = firstTouch.position;
xAngTemp = xAngle;
yAngTemp = yAngle;
break;
case TouchPhase.Moved:
secondpoint = firstTouch.position;
//Mainly, about rotate camera. For example, for Screen.width rotate on 180 degree
xAngle = xAngTemp + (secondpoint.x - firstpoint.x) * 180.0f / Screen.width;
yAngle = yAngTemp - (secondpoint.y - firstpoint.y) * 90.0f / Screen.height;
//Rotate camera
this.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
character.transform.rotation = Quaternion.Euler(yAngle, xAngle, 0.0f);
break;
}
}
}
}
I am working on a project in unity and I have a small circle that shows how much power will be applied to a ball and an arrow that shows the direction.
The circle and arrow are meant to scale up to a max distance; the arrow scales but it is too big (takes up half the screen) and doesn't rotate properly; the circle does not scale at all. I have tried to change the local scale of the arrow and messed around with the various values but I am not sure what to really do. The arrow tends to only face the correct direction when the cursor is in the top left and the arrow is in the bottom right.
The two points, point A and B are two empty objects; point B is attached to the ball and pointA follows the mouse. When the ball is clicked on and the cursor is dragged away pointB moves in the opposite direction; I am trying to get the arrow to face pointB at all times or point at pointB from the opposite side of the ball.
Everything except for the arrow and circle rotating and scaling works. I'm fairly new to code and don't understand Mathf.Log. The arrow rotate and scale code is commented out as I am currently trying to get the circle to work.
If you can point me in the right direction or help with just one of these issues I'd greatly appreciate it.
public class PlayerBallHit : MonoBehaviour
{
private GameObject mousePointA;
private GameObject mousePointB;
private GameObject arrow;
private GameObject circle;
// calc distance
private float currDistance;
public float maxDistance = 3f;
private float spaceLimit;
private float shootPower;
public float shootPowervar;
public Vector2 shootDirection;
void Start()
{
}
void Awake()
{
mousePointA = GameObject.FindGameObjectWithTag("PointA");
mousePointB = GameObject.FindGameObjectWithTag("PointB");
arrow = GameObject.FindGameObjectWithTag("Stick");
circle = GameObject.FindGameObjectWithTag("Circle");
}
private void OnMouseDrag()
{
currDistance = Vector2.Distance(mousePointA.transform.position, transform.position);
if (currDistance <= 3f)
{
spaceLimit = currDistance;
}
else
{
spaceLimit = maxDistance;
}
// Direction of Hit and Circle
StrDirMarkers();
// calc Power & Direction
shootPower = Mathf.Abs(spaceLimit) * shootPowervar;
Vector3 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
mousePointB.transform.position = (Vector3)transform.position + ((dimxy / difference) * currDistance * -1);
mousePointB.transform.position = new UnityEngine.Vector3(mousePointB.transform.position.x, mousePointB.transform.position.y);
shootDirection = (Vector2)Vector3.Normalize(mousePointA.transform.position - transform.position);
}
void OnMouseUp()
{
//arrow.GetComponent<SpriteRenderer>().enabled =false;
circle.GetComponent<SpriteRenderer>().enabled = false;
Vector2 push = shootDirection * shootPower *-1;
GetComponent<Rigidbody2D>().AddForce(push, ForceMode2D.Impulse);
}
private void StrDirMarkers()
{
//arrow.GetComponent<SpriteRenderer>().enabled = true;
circle.GetComponent<SpriteRenderer>().enabled = true;
// calc position
/*
if (currDistance <= maxDistance)
{
arrow.transform.position = new Vector2((2f * transform.position.x) - mousePointA.transform.position.x, (2f * transform.position.y) - mousePointA.transform.position.y);
}
else
{
Vector2 dimxy = mousePointA.transform.position - transform.position;
float difference = dimxy.magnitude;
arrow.transform.position = (Vector2)transform.position + ((dimxy / difference) * maxDistance * -1);
arrow.transform.position = new UnityEngine.Vector2(arrow.transform.position.x, arrow.transform.position.y);
}
*/
circle.transform.position = transform.position + new Vector3(0, 0, 0.04f);
Vector3 dir = mousePointA.transform.position - transform.position;
float rot;
if(Vector3.Angle(dir, transform.forward)> 90)
{
rot = Vector3.Angle(dir, transform.right);
}else
{
rot = Vector3.Angle(dir, transform.right) * -1;
}
//arrow.transform.eulerAngles = new Vector3(0, 0, rot);
// scale arrow
float scaleX = Mathf.Log(1 + spaceLimit / 10000f, 2f) * 0.05f;
float scaleY = Mathf.Log(1 + spaceLimit / 10000f, 2f) * 0.05f;
//arrow.transform.localScale = new Vector3(1 + scaleX, 1 + scaleY, 0.001f);
circle.transform.localScale = new Vector3(1 + scaleX, 1 + scaleY, 0.001f);
}
}
try to use this code for scaling and rotate the arrow
Vector3 dir = mousePointA.transform.position - transform.position;
float rot;
if (mousePointA.transform.position.y >= transform.position.y)
{
rot = Vector3.Angle(dir, transform.position) * -1;
}
else
{
rot = Vector3.Angle(dir, transform.position);
}
arrow.transform.eulerAngles = new Vector3(0, 0, rot);
// scale arrow
float scaleValue = Vector3.Distance(mousePointA.transform.position,
transform.position);
arrow.transform.localScale = new Vector3(1 + scaleValue,
arrow.transform.localScale.y, 1);
circle.transform.localScale = new Vector3(1 + scaleValue * 0.05f, 1 + scaleValue *
0.05f, 0.001f);
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
I have a Problem that I just discovered a few days ago and the Problem is that I cant rotate my Object on a Surface with Touch because I only can Rotate it via Mouse and my question is what do I have to add to my Simple Mouse Roatator Script?
Im a beginner with C# and Unity so hopefully somebody could help me here.
Here is the Code:
using System;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;
namespace UnityStandardAssets.Utility
{
public class SimpleMouseRotator_E : MonoBehaviour
{
// A mouselook behaviour with constraints which operate relative to
// this gameobject's initial rotation.
// Only rotates around local X and Y.
// Works in local coordinates, so if this object is parented
// to another moving gameobject, its local constraints will
// operate correctly
// (Think: looking out the side window of a car, or a gun turret
// on a moving spaceship with a limited angular range)
// to have no constraints on an axis, set the rotationRange to 360 or greater.
public Vector2 rotationRange = new Vector3(70, 70);
public float rotationSpeed = 10;
public float dampingTime = 0.2f;
public bool autoZeroVerticalOnMobile = true;
public bool autoZeroHorizontalOnMobile = false;
public bool relative = true;
public GameObject reflectionprobe;
public Vector2 startPos;
public Vector2 direction;
public bool directionChosen;
private Vector3 m_TargetAngles;
private Vector3 m_FollowAngles;
private Vector3 m_FollowVelocity;
private Quaternion m_OriginalRotation;
private bool whileDragging;
private void Start()
{
whileDragging = false;
m_OriginalRotation = transform.localRotation;
}
private void Update()
{
// Track a single touch as a direction control.
if (Input.touchCount > 0)
{
Touch touch = Input.GetTouch(0);
// Handle finger movements based on touch phase.
switch (touch.phase)
{
// Record initial touch position.
case TouchPhase.Began:
startPos = touch.position;
directionChosen = false;
break;
// Determine direction by comparing the current touch position with the initial one.
case TouchPhase.Moved:
direction = touch.position - startPos;
break;
// Report that a direction has been chosen when the finger is lifted.
case TouchPhase.Ended:
directionChosen = true;
break;
}
}
if (directionChosen)
{
// Something that uses the chosen direction...
}
if (whileDragging)
{
// we make initial calculations from the original local rotation
transform.localRotation = m_OriginalRotation;
// read input from mouse or mobile controls
float inputH;
float inputV;
if (relative)
{
inputH = CrossPlatformInputManager.GetAxis("Mouse X");
inputV = CrossPlatformInputManager.GetAxis("Mouse Y");
// wrap values to avoid springing quickly the wrong way from positive to negative
if (m_TargetAngles.y > 180)
{
m_TargetAngles.y -= 360;
m_FollowAngles.y -= 360;
}
if (m_TargetAngles.x > 180)
{
m_TargetAngles.x -= 360;
m_FollowAngles.x -= 360;
}
if (m_TargetAngles.y < -180)
{
m_TargetAngles.y += 360;
m_FollowAngles.y += 360;
}
if (m_TargetAngles.x < -180)
{
m_TargetAngles.x += 360;
m_FollowAngles.x += 360;
}
#if MOBILE_INPUT
// on mobile, sometimes we want input mapped directly to tilt value,
// so it springs back automatically when the look input is released.
if (autoZeroHorizontalOnMobile) {
m_TargetAngles.y = Mathf.Lerp (-rotationRange.y * 0.5f, rotationRange.y * 0.5f, inputH * .5f + .5f);
} else {
m_TargetAngles.y += inputH * rotationSpeed;
}
if (autoZeroVerticalOnMobile) {
m_TargetAngles.x = Mathf.Lerp (-rotationRange.x * 0.5f, rotationRange.x * 0.5f, inputV * .5f + .5f);
} else {
m_TargetAngles.x += inputV * rotationSpeed;
}
#else
// with mouse input, we have direct control with no springback required.
m_TargetAngles.y += inputH * rotationSpeed;
m_TargetAngles.x += inputV * rotationSpeed;
#endif
// clamp values to allowed range
m_TargetAngles.y = Mathf.Clamp(m_TargetAngles.y, -rotationRange.y * 0.5f, rotationRange.y * 0.5f);
m_TargetAngles.x = Mathf.Clamp(m_TargetAngles.x, -rotationRange.x * 1f, rotationRange.x * 0.2f);
}
else
{
inputH = -Input.mousePosition.x;
inputV = -Input.mousePosition.y;
// set values to allowed range
m_TargetAngles.y = Mathf.Lerp(-rotationRange.y * 0.5f, rotationRange.y * 0.5f, inputH / Screen.width);
m_TargetAngles.x = Mathf.Lerp(-rotationRange.x * 1f, rotationRange.x * 1f, inputV / Screen.height);
}
// smoothly interpolate current values to target angles
m_FollowAngles = Vector3.SmoothDamp(m_FollowAngles, m_TargetAngles, ref m_FollowVelocity, dampingTime);
// update the actual gameobject's rotation
transform.localRotation = m_OriginalRotation * Quaternion.Euler(-m_FollowAngles.x, m_FollowAngles.y, 0);
}
}
public void BeginDrag()
{
whileDragging = true;
}
public void EndDrag()
{
whileDragging = false;
}
}
}
Maybe somebody could help me here it would be pretty awesome!
Grettings from Germany
Hmmm, why not try using this?
float rotSpeed = 20;
void OnMouseDrag(){
float rotX = Input.GetAxis("Mouse X") * rotSpeed * Mathf.Deg2Rad;
float rotY = Input.GetAxis("Mouse Y") * rotSpeed * Mathf.Deg2Rad;
transform.RotateAround(Vector3.up, -rotX);
transform.RotateAround(Vector3.right, rotY);
}
A simple way of rotating using touch input :)
I'm trying to get a unity C# script working that will rotate the camera around the X axis in a 3D environment. Currently, it flips the screen making my terrain look like it is hanging upside down. I'm just trying to get the camera to rotate on the X axis instead. Below is what I currently have.
using UnityEngine;
public class TouchCamera : MonoBehaviour {
Vector2?[] oldTouchPositions = {
null,
null
};
Vector2 oldTouchVector;
float oldTouchDistance;
void Update() {
if (Input.touchCount == 0) {
oldTouchPositions[0] = null;
oldTouchPositions[1] = null;
}
else if (Input.touchCount == 1) {
if (oldTouchPositions[0] == null || oldTouchPositions[1] != null) {
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = null;
}
else {
Vector2 newTouchPosition = Input.GetTouch(0).position;
transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] - newTouchPosition) * camera.orthographicSize / camera.pixelHeight * 2f));
oldTouchPositions[0] = newTouchPosition;
}
}
else {
if (oldTouchPositions[1] == null) {
oldTouchPositions[0] = Input.GetTouch(0).position;
oldTouchPositions[1] = Input.GetTouch(1).position;
oldTouchVector = (Vector2)(oldTouchPositions[0] - oldTouchPositions[1]);
oldTouchDistance = oldTouchVector.magnitude;
}
else {
Vector2 screen = new Vector2(camera.pixelWidth, camera.pixelHeight);
Vector2[] newTouchPositions = {
Input.GetTouch(0).position,
Input.GetTouch(1).position
};
Vector2 newTouchVector = newTouchPositions[0] - newTouchPositions[1];
float newTouchDistance = newTouchVector.magnitude;
transform.position += transform.TransformDirection((Vector3)((oldTouchPositions[0] + oldTouchPositions[1] - screen) * camera.orthographicSize / screen.y));
transform.localRotation *= Quaternion.Euler(new Vector3(0, 0, Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y) / oldTouchDistance / newTouchDistance, -1f, 1f)) / 0.0174532924f));
camera.orthographicSize *= oldTouchDistance / newTouchDistance;
transform.position -= transform.TransformDirection((newTouchPositions[0] + newTouchPositions[1] - screen) * camera.orthographicSize / screen.y);
oldTouchPositions[0] = newTouchPositions[0];
oldTouchPositions[1] = newTouchPositions[1];
oldTouchVector = newTouchVector;
oldTouchDistance = newTouchDistance;
}
}
}
}
If you wanted to rotate it around (like a character turning its head), in the x-z plain, then you wanted to rotate it around the y axis, not the x.
In the end, I had to make a raycast shoot out the center of the camera and when it collided with something, set that as the pivot point. Then I rotated the camera around said pivot point. Example below...
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit, 300)){}
float distanceToGround = hit.distance;
var pivotPoint = hit.point;
// -------- Rotation ---------
transform.RotateAround(pivotPoint, Vector3.up,Mathf.Asin(Mathf.Clamp((oldTouchVector.y * newTouchVector.x - oldTouchVector.x * newTouchVector.y) / oldTouchDistance / newTouchDistance, -1f, 1f)) / 0.0174532924f);
//---------------------------------------------------------