Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411423 Posts in 69363 Topics- by 58416 Members - Latest Member: JamesAGreen

April 18, 2024, 04:12:56 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsCommunityTownhallForum IssuesArchived subforums (read only)TutorialsTutorial: Implementing basic 2D touch controls in unity.
Pages: [1]
Print
Author Topic: Tutorial: Implementing basic 2D touch controls in unity.  (Read 9674 times)
Duckbridge
Level 0
**



View Profile WWW
« on: November 30, 2014, 07:35:01 AM »

Hey all, I’m marciano Viereck, the programmer @ Duckbridge and the other day I got a question about how to implement some basic 2D touch controls in Unity (for example that you can move something up, down, left and right by dragging it. In our framework we have code that allows us to use touch controls, so in this post I’ll go over how we implemented it in Unity3D and it might help you!:)

0: Setting up
Because I’m not sure how much Unity experience you have, we will start at the beginning. So create a new Unity project which you can call whatever you want. Make new scene and add a new c# script, call it TouchListener and add it to a new empty gameObject in the scene.

1: Touching an object
In order to touch an object, we need to add the following variable to the TouchListener class:

public Camera usedCamera;
public float minimumDragDistance = 1f;

private bool isTouching;
private Vector3 touchPoint;

private static GameObject selectedObject;


We will use the usedCamera to detemine which camera we want to use for the raycast. Now that we have this, go into the FixedUpdate function and add the following:

        if(!isTouching) {
            if (Input.GetMouseButtonDown(0)) {
                isTouching = true;
                selectedObject = null;

                RaycastHit hitSummary;
                Physics.Raycast(usedCamera.ScreenPointToRay(Input.mousePosition), out hitSummary, 200);

                this.touchPoint = usedCamera.ScreentoWorldPoint(Input.mousePosition);
                
                if (hitSummary.collider != null) {
                    selectedObject = hitSummary.collider.gameObject;
                    selectedObject.SendMessage("OnTouched", hitSummary, SendMessageOptions.DontRequireReceiver);
                }
            }
        }


What this will do is, check if you’re not touching an object already and then use Raycasting to raycast from the position of your finger inside the camera into the depth. When the raycast hits, it checks if the hit object has a collider.

If it has a collider, it uses the collider to get the gameobject that was hit. And it sends an OnTouched event message to that object! We also register the touchPoint which will be used for the dragging.

2 Test the touch:
If you want to test out if this works, just create a new Cube in the scene and give it a (new) TouchableObject c# script and modify your camera to be ‘orthographic’. Make sure that the cube is inside the camera’s z axis (so you should be able to see it in the ’game’ window). Drag the camera into the ‘usedCamera’ variable inside the Touch Listener in the Unity editor.

Then inside the TouchableObject script, add a new function : OnTouched:

public void OnTouched(RaycastHit hitSummary) {
  Debug.Log(‘hello!’);
}


Then run the scene and try to click the object,  congrats you now have basic touch behaviour! Smiley

3: Dragging an object
So now we got the basic touch behaviour working, we can move on to dragging, which is a bit more tricky, but uses the same idea!

So we go back inside the TouchableObject and inside the FixedUpdate function again. Add the following code:

       if(Input.GetMouseButtonUp(0)) {
            this.isTouching = false;
            
            if(selectedObject != null) {
                selectedObject.SendMessage("OnDraggingStopped", null, SendMessageOptions.DontRequireReceiver);
            }
            
            selectedObject = null;
        }
        
        if(isTouching && selectedObject != null) {
            OnTouchHeld();
        }

I know that the code won’t compile yet, but we’ll fix that soon. Anwyays, what this piece of code is about is; you basically check if the user is still touching, if not, then the touched object is unset and a OnDraggingStopped event is sent to that object. So you can add custom behaviour to the object that was dragged/touched.

Small note: when you implement the OnDraggingStopped function on a TouchableObject, make sure that the OnDraggingStopped function has no parameters!

In order to fix the compile error, we need to add the most crucial part! The OnTouchHeld behaviour. Before we get into that, we need to create a new struct, which we will call DragSummary. So let’s create a new c# script, call it DragSummary and add the following code:


using UnityEngine;

public struct DragSummary {

    public Vector3 position;
    public Vector3 direction;
    public Vector3 amount;

}


That’s all we need! If you’re wondering why we use a struct and not a class, it is beacuse Unity doesn’t like it when we create a new class, so we use a struct.

We’re almost done! We only need to fill the OnTouchHeld function with the right code. Add the following to the TouchListener class:

private void OnTouchHeld() {
        Vector3 currentMousePosition = usedCamera.ScreenToWorldPoint(Input.mousePosition);
        Vector3 dragAmount = (currentMousePosition - touchPoint);
        Vector3 directionToCurrentMousePosition = currentMousePosition - selectedObject.transform.position;

        DragSummary dragSummary = new DragSummary();
        dragSummary.position = currentMousePosition;
        dragSummary.amount = dragAmount;
        dragSummary.direction = directionToCurrentMousePosition;

        if(dragAmount.magnitude > minimumDragDistance) {
            selectedObject.SendMessage("OnDrag", dragSummary, SendMessageOptions.DontRequireReceiver);
        }

        if(Mathf.Abs(dragAmount.x) > minimumDragDistance) {
            selectedObject.SendMessage("OnHorizontalDrag", dragSummary, SendMessageOptions.DontRequireReceiver);
        }
        
        if(Mathf.Abs(dragAmount.y) > minimumDragDistance) {
            selectedObject.SendMessage("OnVerticalDrag", dragSummary, SendMessageOptions.DontRequireReceiver);
        }
    }


This might seem like a lot of code, but it’s not really. So at first we take the current mouse position, and save that. Then we decide how much is dragged by subtracting our original touch position with the new position of the finger.

Then when we have that, we also calculcate the direction that the object needs to use in order to reach our finger’s new position. This might seem useless, because we could just set the object’s position to the position of our finger, right?

The thing is that that solution works fine, but we want to be able to control how fast the object will move towards the finger position.

The rest of this function is bascially checking the distance between the original touch position and the current touch position. Beacuse you might want to drag certain objects only horizontal/vertically or after a certain distance.

So okay, the final thing that we need to do is, go into the TouchableObject and add the following variable:

   public float onTouchMoveSpeed = .5f;

And add the following function, which will allow for dragging:

    public void OnDrag(DragSummary dragSummary) {
        this.transform.position += onTouchMoveSpeed * new Vector3(dragSummary.direction.x, dragSummary.direction.y, 0f);
    }


That should do the trick! Now when you test the scene again you should be able to drag the TouchableObject and also control how fast it can be dragged!

That’s it!, if you weren’t able to figure out some stuff, feel free to download the example project, which contains all the stuff you need.
« Last Edit: December 03, 2014, 02:29:31 PM by Duckbridge » Logged

Dutch indie game developer that is currently working on Luckslinger, you can follow us on Twitter and Facebook
Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic