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

alt text

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);
    }
}

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.