Reputation: 295
I'm trying to rotate my camera(50 degree in X) and also place an object following the touch posiiton, here is my script, can rotate the camera and move the object but since it's perspective the object isn't moving correctly following the finger, any tips on how I can achieve that?
The goal is achieve something like in this video https://www.youtube.com/watch?v=Ljnpp5ibfGQ
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class CameraRotator : MonoBehaviour
{
private float initialX;
public float offset = 10f;
public float speed = 10f;
public GameObject cube;
public bool movingPlayer = false;
void Update()
{
if (Input.touchCount > 0 && !movingPlayer)
{
Touch touch = Input.GetTouch(0);
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
switch (touch.phase)
{
case TouchPhase.Began:
initialX = touch.position.x;
break;
case TouchPhase.Moved:
if (touch.position.x + offset < initialX)
transform.rotation = Quaternion.Euler(0f, transform.rotation.eulerAngles.y - speed, 0f);
else if (touch.position.x - offset > initialX)
transform.rotation = Quaternion.Euler(0f, transform.rotation.eulerAngles.y + speed, 0f);
initialX = touch.position.x;
break;
}
}
if (Input.touchCount > 0 && movingPlayer)
{
Touch touch = Input.GetTouch(0);
Vector3 touchPosition = Camera.main.ScreenToWorldPoint(touch.position);
Ray raycast = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
if (Input.GetTouch(0).phase == TouchPhase.Moved)
{
Ray ray = Camera.main.ScreenPointToRay(Input.GetTouch(0).position);
Vector3 xx = ray.GetPoint(10f);
xx.y = 1f;
xx.x = (int)xx.x;
xx.z = (int)xx.z;
cube.transform.position = xx;
}
}
}
}
Upvotes: 1
Views: 2356
Reputation: 702
I created something like that some time ago.
You need to be careful with ScreenToWorldPoint()
. A Click position is basically never a 3D point in the world, but a Ray. There is a whole line of locations in space that would all appear on the same spot on the screen.
The Unity function ScreenToWorldPoint()
uses the Z coordinate from the input vector as a distance. Since you just pick it up from Input.GetTouch()
, it is surely not the distance you want.
Doc on it: https://docs.unity3d.com/2020.1/Documentation/ScriptReference/Camera.ScreenToWorldPoint.html
Preferably use Camera.ScreenPointToRay()
. Then use that ray to decide which point on that it is that you want to consider clicked.
In my grabbing-implementation, I used that to call Physics.Raycast()
or Physics.RaycastAll()
, look at the hits found, and decide for a hitpoint.
When the player drags, you need to decide how to change the distance. If clicking around on a map like in your sample video link, you might keep the Y coordinate of the click target and then for each mouse-move intersect the new Ray with this Y-plane.
In my sample, I just kept the distance and that let the player move an item, keeping at the same distance it was when picked up.
From my sample, on clicking I do this:
// try to grab something.
Ray beam = new Ray(){origin=head.transform.position,direction=head.transform.forward};
RaycastHit hit;
if( ! Physics.Raycast(beam,out hit,15.0f) )
return;
grab_item = hit.rigidbody;
if( grab_item==null || grab_item.isKinematic )
return;
grab_pos_on_item = grab_item.transform.InverseTransformPoint(hit.point);
grab_distance = (hit.point-beam.origin).magnitude;
then, in each update, check where the new point is and then move item there.
if(grab_item!=null)
{
// p1: hand, p2: item
Vector3 p1 = head.transform.position + head.transform.forward * grab_distance;
Vector3 p2 = grab_item.transform.TransformPoint(grab_pos_on_item);
Vector3 dist = p1-p2;
// code to make the item move by 'dist'
If I understand right, you might be rather be interested to keep the Y coordinate constant?
Upvotes: 2