- Home /
Converting 2D Swipe Input into 3D Game
Hi all,
I am making an iPhone game where a user swipes an object to try and land that object in the designated target area.
I'm having difficulty in converting the 2d swipe information into the 3D World through scripting. I'm currently storing information about the "path" of the swipe over time, in order to work out swipe direction and power. The swipe speed/power will be assigned to the 3rd axis... however...
My game features a variety of levels where the camera angle changes from level to level - some levels have a birds-eye-view while others will be human-eye-view for example. My problem is that I can't assign swipe direction and power to specific axis, because it would depend on the camera's location in the scene as to where the user will expect the ball to travel after a swipe. Human-eye-view for example, would fire the object down the z-axis toward the target, but for a birds-eye view this would not suffice as it would launch the object straight toward the ground, where instead that same value should be applied to the cameras Y position.
Also worth noting, is that the user does not control the camera so the camera positions are fixed into place, hence my problem (though thinking about it, a user-controller camera which always fires down it's z-axis mightn't be a bad thing)...
Finally, my target is fired through a physics AddForce.
Thanks for any help, you guys always do a great job.
Cheers
Mat
EDIT : See below for image examples. This is a prototype so please excuse the crude visuals. You can see from the screenshots how the ball might need to be swiped in order to fire it in the correct direction. Note the camera's differing angles for the same level. Given these two different angles, I don't believe I can just map any of the camera's axis to the ball because it would need to be different depending on the camera's angle. It's not like I can say that the camera is the person's eyes into the world, therefore project the ball along the camera's Z axis. Maybe i'm over thinking it
Answer by pyro 1 · Mar 12, 2011 at 04:25 PM
To convert from Camera-space to World-space, you would use the function
Camera.ScreenToWorldPoint()
So in your example, I would take the X,Y position of your swipes BEGIN and END points, convert them into World points, subtract the end point from the begin point, and you now have a simple vector that you can use as the force.
I've created a small demo to show how I would approach it using that method above (tried it out on ipad too): http://www.hazemobile.com/dev/swipetest.html
To re-create it is simple, it uses: 1) your background (with a meshcollider) 2) a light 3) default main camera 4) a sphere (gameobject->create other->sphere) with a rigidbody attached 5) a game object with the script below attached, and the (sphere rigidbody connected to it in the inspector)
using UnityEngine; using System.Collections;
public class TouchMonitor : MonoBehaviour {
public Rigidbody ball;
private Vector3 touchStart;
private Vector3 touchEnd;
private GameObject lineRenderer;
void Update () {
if (Input.touchCount > 0)
{
Touch t = Input.touches[0];
if (t.phase == TouchPhase.Began)
{
touchStart = t.position;
}
if (t.phase == TouchPhase.Ended || t.phase == TouchPhase.Canceled)
{
touchEnd = t.position;
DoInput();
}
}
if (Input.GetButtonDown("Fire1"))
{
touchStart = Input.mousePosition;
}
if (Input.GetButtonUp("Fire1"))
{
touchEnd = Input.mousePosition;
DoInput();
}
}
void DoInput()
{
Vector3 p1 = new Vector3();
Vector3 p2 = new Vector3();
touchStart.z = Camera.main.nearClipPlane+.1f; //push it a little passed the clip plane for camera, just to make sure its visible on screen
touchEnd.z = Camera.main.nearClipPlane+.1f;
p1 = Camera.main.ScreenToWorldPoint(touchStart);
p2 = Camera.main.ScreenToWorldPoint(touchEnd);
CreateLine(p1,p2);
Vector3 v = p2-p1;
ball.AddForce(v*100, ForceMode.Impulse);
}
//creates an ugly purple line from pos1 to pos2 in worldspace
void CreateLine(Vector3 p1, Vector3 p2)
{
Destroy(lineRenderer);
lineRenderer = new GameObject();
lineRenderer.name = "LineRenderer";
LineRenderer lr = (LineRenderer)lineRenderer.AddComponent(typeof(LineRenderer));
lr.SetVertexCount(2);
lr.SetWidth(0.001f, 0.001f);
lr.SetPosition(0, p1);
lr.SetPosition(1, p2);
}
}
Thanks so much for making this working example! I've added it to my game and it's working a treat! However, I would love to know something, and that is, why does setting the touch Z to Camera.main.nearClipPlane+.1f; make this whole example work? Without setting it the whole thing just doesn't work, but i'm unsure of why it makes such a difference, given that we're setting the same value for both the start and end touches here. I would love to know exactly what's happening here (if you don't $$anonymous$$d explaining it). Thanks once again for the very thorough answer!
Does the script work if I want to to check whether the swipe direction is perpendicular to one of the game object's axis whether it is X, Y, or Z
Because I need to check any swipe direction will rotate the game object on one specific axis that perpendicular to the swipe direction since my camera will always rotating around the game object.
Thanks
Answer by Ashkan_gc · Mar 11, 2011 at 02:09 PM
so you can always use the camera's local y or write different components for different camera modes and attach them to your objects based on the camera in your level. to converting positions/directions from local space of a gameObject to world space and vice versa you can use Transform.TransformDirection and other methods in Transform class.
thanks for answer, but i'm still a bit unsure on this one - i'd like to be able to script it so that it can work out the final vector3 for AddForce without me having to specify which type of camera it is. I have seen Transform.TransformDirection but I don't think this is enough to do what I want. Do you have any more suggestions or examples please? thanks again
just say you have a reference to the camera object and you always nned to move the object in camera's transform.up and transform.right. get those from your camera and convert them to wrold space and use them for your force.
Hi Ashkan. Thanks once again for helping me on this one. I have adjusted my original question to include an image. with a little note above it. $$anonymous$$aybe i'm over-thinking it but i'm still not entirely sure of what you're telling me. If you wouldn't $$anonymous$$d, please refer to the image i've posted and perhaps give a code example? At the moment all of the swipe information is being stored in an ArrayList called SwipeInputs which contains vector3s (touch position x, touch position y, time). I have my reference to the camera, and to the ball. Thanks and sorry if i'm being a bit dumb here.
the code by pyro is ok. you can use it. thank you pyro for providing the code! just you can change the z value from nearclip + .1 to ball's distance from camera.
Thank you Ashkan for your help on this also. I love the Unity community - everyone is always happy to help eachother!