0
\$\begingroup\$

I have a game where you need to cut chains, similar to Cut The Rope. I want to develop it for Android, so I need mobile controls.

For detecting swipes I used OnMouseEnter() and OnMouseDown() for when you just click and it works perfectly! The problem only occurs when you swipe too fast over the chain because, in this case, it doesn't get destroyed.

The code I used is:

using UnityEngine;

public class DestroyOnDrag : MonoBehaviour
{
    private void OnMouseEnter()
    {
        Destroy(gameObject);
    }

    private void OnMouseDown()
    {
        Destroy(gameObject);
    }
}

I think this is because Unity's Input System is not fast enough: on one frame, the finger is on the left side of the chain, and next it is already on the right. That would explain why those methods are not called, but I'm unsure if this is correct and how to fix that.

Update:

I tried Implementing raycast to check between this and last touches position and to cut any chains inbetween, but it didn't work.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class RaycastMouse : MonoBehaviour
{
    private Vector2 lastTouch;
    private void FixedUpdate()
    {
        if (Input.touchCount > 0)
        {
            Touch touch = Input.GetTouch(0);
            Vector2 dir = touch.position - lastTouch;
            CastRay(touch.position, dir);
            lastTouch = touch.position;
        }
    }

    private void CastRay(Vector2 origin, Vector2 dir)
    {
        RaycastHit2D[] hits = Physics2D.RaycastAll(origin, dir.normalized, dir.magnitude);
        foreach (RaycastHit2D hit in hits)
        {
            Destroy(hit.collider.gameObject);
        }
        Debug.DrawRay(origin, dir.normalized * dir.magnitude, Color.magenta);
    }
}

The chain's inspector:

the chain's inspector

and prefab hierachy window:

hi

\$\endgroup\$
4
  • 4
    \$\begingroup\$ Have you considered using a physics raycast or shape cast to sweep between the cursor's previous and next positions to slice anything in between? \$\endgroup\$
    – DMGregory
    Commented Apr 17 at 16:13
  • \$\begingroup\$ Your raycast is taking screen coordinates then using them as though they were world coordinates. You're missing a Camera.ScreenToWorldPoint call in there. \$\endgroup\$
    – DMGregory
    Commented Apr 20 at 13:41
  • \$\begingroup\$ So RaycastHit2D[] hits = Physics2D.RaycastAll(Camera.ScreenToWorldPoint(origin), dir.normalized, dir.magnitude); ? \$\endgroup\$
    – CheckerT
    Commented Apr 20 at 14:17
  • 1
    \$\begingroup\$ Your distance is still in screenspace. You'll likely want to do the conversion to world space once when you read touch.position. Remember to provide a depth value as the z coordinate. \$\endgroup\$
    – DMGregory
    Commented Apr 20 at 14:32

1 Answer 1

2
\$\begingroup\$

You are currently experiencing a form of tunnelling. You are checking if touch coordinates move through the Collider's boundaries inwards (outside-inside) or outwards (inside-outside) during each frame, but are not covering the case of a touch crossing over the whole Collider during the same frame (outside-inside-outside).

A solution may be using the current touch position to define a line trajectory from the previous touch position and perform a raycast check between such line and the chain.

If you're using the new Input System, you can use TouchControl's position and delta to find out the ends of the line trajectory, and then check for collisions.

Otherwise, the built-in Input class provides support for touch events via the Touch data structure, which also exposes properties such as position and deltaPosition that you can leverage to estimate the finger trajectory. Detect the different touch moments in time through the TouchPhase enumeration.

\$\endgroup\$
3
  • \$\begingroup\$ I'm not very good with the new Input System, is there a way to also do this with code or the old Input System? But thanks to your answer anyways, I will try to implement a (temporarily) raycast solution for this. \$\endgroup\$
    – CheckerT
    Commented Apr 18 at 17:59
  • 1
    \$\begingroup\$ I updated my answer to address the old input system as well. The high-level approach is the same, though: get touch input, compute the appropriate coordinates, and then check for collision. Good luck! :) \$\endgroup\$
    – liggiorgio
    Commented Apr 19 at 11:26
  • \$\begingroup\$ I have tried, but I can't get it to work. I updated my answer to include code I used for raycasting. \$\endgroup\$
    – CheckerT
    Commented Apr 20 at 12:53

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .