DAVIDBALAS1
DAVIDBALAS1

Reputation: 484

Dragging and moving 2D gameObject

so as my previous threads show, I am creating a gameObject from sprites images at runtime using this code:

 tex = Resources.Load<Texture2D>("pig") as Texture2D;
 Sprite sprite = new Sprite();
 sprite = Sprite.Create(tex, new Rect(0, 0, 250, 150), new Vector2(0.5f, 0.5f));
 GameObject newSprite = new GameObject();
 newSprite.AddComponent<Rigidbody2D>();
 newSprite.GetComponent<Rigidbody2D>().gravityScale = 0f;
 newSprite.AddComponent<ObjectMovement>();
 newSprite.AddComponent<SpriteRenderer>();
 SR = newSprite.GetComponent<SpriteRenderer>();
 SR.sprite = sprite;

As you see I added a script "ObjectMovement", I want to check in this script if someone is dragging this particular gameObject and if so, make it follow the touch position, just to mention - this game is 2D. I never used RaysorRaycast so I am not sure where I gone wrong. Anyway here is my script code:

public SpriteRenderer selection=null;
    void Update()
    {
        if (Input.touchCount >= 1)
        {
            foreach (Touch touch in Input.touches)
            {
                Ray ray = Camera.main.ScreenPointToRay(touch.position);
                RaycastHit hit;
                switch (touch.phase)
                {
                    case TouchPhase.Began:
                        if (Physics.Raycast(ray, out hit, 100))
                            selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
                        break;
                    case TouchPhase.Moved:
                        selection.transform.position = new Vector2(selection.transform.position.x + touch.position.x / 10, selection.transform.position.y + touch.position.y / 10);
                        break;
                    case TouchPhase.Ended:
                        selection = null;
                        break;
                }
            }
        }
    }

So basically - when touching the screen, fire a ray and check which gameObject is in this position, when moving the finger make it follow it. Drag and drop. Thanks.

EDIT: I noticed the script is attached to every gameObject which is not effective, any ideas?

Upvotes: 0

Views: 3424

Answers (1)

Programmer
Programmer

Reputation: 125305

For 2D, you use RaycastHit2D and Physics2D.Raycast instead of RaycastHit and Physics.Raycast. Those are for 3D. Secondly, Make sure to attach a collider to the Sprite. Since this is a 2D game, the collider must have word "2D" in it. For example, Box Colider 2D from the Editor. You can also use Circle Collider 2D.

I noticed the script is attached to every gameObject which is not effective, any ideas?

Just create an empty GameObject and attach that script to it. That's it.

Here is fixed version of your code:

float tempZAxis;
public SpriteRenderer selection;
void Update()
{
    Touch[] touch = Input.touches;
    for (int i = 0; i < touch.Length; i++)
    {
        Vector2 ray = Camera.main.ScreenToWorldPoint(Input.GetTouch(i).position);
        RaycastHit2D hit = Physics2D.Raycast(ray, Vector2.zero);
        switch (touch[i].phase)
        {
            case TouchPhase.Began:
                if (hit)
                {
                    selection = hit.transform.gameObject.GetComponent<SpriteRenderer>();
                    if (selection != null)
                    {
                        tempZAxis = selection.transform.position.z;
                    }
                }
                break;
            case TouchPhase.Moved:
                Vector3 tempVec = Camera.main.ScreenToWorldPoint(touch[i].position);
                tempVec.z = tempZAxis; //Make sure that the z zxis never change
                if (selection != null)
                {
                    selection.transform.position = tempVec;
                }
                break;
            case TouchPhase.Ended:
                selection = null;
                break;
        }

    }
}

That would only work on mobile but not on the Desktop Build. I suggest you implement IBeginDragHandler, IDragHandler, IEndDragHandler and override the functions that comes with them. Now, it will work with both mobile and desktop platforms.

Note: For the second solution you have to attach the script below to all Sprites you want to drag unlike the first script above.

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.EventSystems;

public class Dragger : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{

    Camera mainCamera;
    float zAxis = 0;
    Vector3 clickOffset = Vector3.zero;

    // Use this for initialization
    void Start()
    {
        //Comment this Section if EventSystem system is already in the Scene
        addEventSystem();


        mainCamera = Camera.main;
        mainCamera.gameObject.AddComponent<Physics2DRaycaster>();

        zAxis = transform.position.z;
    }

    public void OnBeginDrag(PointerEventData eventData)
    {
        clickOffset = transform.position - mainCamera.ScreenToWorldPoint(new Vector3(eventData.position.x, eventData.position.y, zAxis));
    }

    public void OnDrag(PointerEventData eventData)
    {
        //Use Offset To Prevent Sprite from Jumping to where the finger is
        Vector3 tempVec = mainCamera.ScreenToWorldPoint(eventData.position) + clickOffset;
        tempVec.z = zAxis; //Make sure that the z zxis never change

        transform.position = tempVec;
    }

    public void OnEndDrag(PointerEventData eventData)
    {

    }

    //Add Event Syste to the Camera
    void addEventSystem()
    {
        GameObject eventSystem = new GameObject("EventSystem");
        eventSystem.AddComponent<EventSystem>();
        eventSystem.AddComponent<StandaloneInputModule>();
    }
}

Upvotes: 3

Related Questions