0
\$\begingroup\$

I'm making a 2D game where the player character should dash toward the mouse position when the player clicks, but the dash is currently not a consistent distance each time.

Let's say you put the cursor far-right like x = 20, so the character moves 20 units. But if you put it closer, like at x = 5, the character dashes only 5 units.

How can I limit the position input to just a direction, so the player character would travel the same distance, no matter where the mouse is positioned?

void FixedUpdate() {
    //...
    float xor = Input.GetAxis("Horizontal"), yor = Input.GetAxis("Vertical");

    if ((xor != 0 || yor != 0) && !dash)
    {
        rg2d.velocity = new Vector2(xor * speed, yor * speed);
        anim.SetFloat("speed", Mathf.Abs(xor + yor));
    }
    if(Input.GetKeyDown(KeyCode.Mouse0) && !fire)
    {
        //PUNCH
        dash = true;
        fire = true;
        StartCoroutine(Stop_Fire(0.5f));
        anim.SetTrigger("attack");
        fist.GetComponent<Collider2D>().enabled = true;

        Vector2 pos = (transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition)).normalized;

        rg2d.AddForce(-pos * punch_force, ForceMode2D.Impulse);
    }
}

// I call this function at the end of the attack animation, in the Animation window
public void Stop_Dash()
{
    dash = false;
    fire = false;
    fist.GetComponent<Collider2D>().enabled = false;
    rg2d.velocity = Vector2.zero;
}
\$\endgroup\$
8
  • \$\begingroup\$ Where do you set fire to true? \$\endgroup\$
    – DMGregory
    Dec 23, 2019 at 22:58
  • \$\begingroup\$ @DMGregory sorry forgot to include that part. edited it. \$\endgroup\$
    – ZozeR
    Dec 23, 2019 at 23:12
  • \$\begingroup\$ Can you show us how your camera is configured? Orthographic / perspective, and any transformation applied to it? \$\endgroup\$
    – DMGregory
    Dec 23, 2019 at 23:14
  • \$\begingroup\$ I haven't even touched any values in the camera. i added it to post. \$\endgroup\$
    – ZozeR
    Dec 23, 2019 at 23:18
  • \$\begingroup\$ You're taking a 3D vector with a potentially-large z component, normalizing it, then discarding the z to make it a 2D vector. This will result in a vector that can be quite a bit smaller than unit length. Does converting to 2D before normalizing make any difference for your case? \$\endgroup\$
    – DMGregory
    Dec 23, 2019 at 23:21

2 Answers 2

0
\$\begingroup\$

said in the comment section:

You're taking a 3D vector with a potentially-large z component, normalizing it, then discarding the z to make it a 2D vector. This will result in a vector that can be quite a bit smaller than unit length. Does converting to 2D before normalizing make any difference for your case?

        Vector3 mousepos = Camera.main.ScreenToWorldPoint(Input.mousePosition);
        Vector3 moveDirection = (transform.position - mousepos);
        moveDirection.z = 0;
        moveDirection.Normalize();

        rg2d.AddForce(-moveDirection * punch_force, ForceMode2D.Impulse);
\$\endgroup\$
1
  • \$\begingroup\$ The reason for this is that ScreenToWorldPoint gives you a point at a depth in front of the camera specified by the z component of the argument. Since you give it a 2D argument, the z is zero, so it gives you a point in the same plane as the camera. Your game objects are in front of the camera, so transform.position - ScreenToWorldPoint gives you a 3-vector that points diagonally: partly in the xy plane, and partly in the z. If the xy component was short, the z gets most of the length in the normalized vector, leaving a very small xy component after normalizing. Discard the z first to fix. \$\endgroup\$
    – DMGregory
    Dec 24, 2019 at 3:33
0
\$\begingroup\$

Seems like you are already doing the correct thing (getting .normalized which in any way will give you a vector of magnitude of 1) and your problem isn't related to how you get the direction. I guess that Input.GetAxis("Fire1") is a continuous event and this code is being executed multiple times per SECOND during multiple FRAMES. Thus you are getting a different distance each time, depending on how long you hold the Fire1 event.

To fix this you can have some kind of a cooldown, or a bool that would restrict firing an event again until it was released.

Edit 1

The z position of Camera.ScreenToWorldPoint - "position for depth (for example, a camera clipping plane)."

From official example point = cam.ScreenToWorldPoint(new Vector3(mousePos.x, mousePos.y, cam.nearClipPlane));. Which would indicate that cam.ScreenToWorldPoint(new Vector3(Input.mousePosition)); should disregard z as it's a 0. Which in turn would give us new Vector3(x, y, 0f), so normalizing it after conversion to Vector2 shouldn't give a different result. But I may be wrong, indeed this is something I need to research.

Edit 2

Seems like transform.position is the culprit. Vector2 pos = (transform.position - Camera.main.ScreenToWorldPoint(Input.mousePosition)).normalized; If this Component's transform.position was changed on z axis from 0 to any other value, this would create a different Vector3 each time a position of this transform was changed.

\$\endgroup\$
6
  • \$\begingroup\$ i already tried doing that but it seems it didn't have any effect, I edited the code to show changes, what am i missing. \$\endgroup\$
    – ZozeR
    Dec 23, 2019 at 18:04
  • \$\begingroup\$ @ZozeR when/where do you call Stop_Fire(float ct)? \$\endgroup\$ Dec 23, 2019 at 21:21
  • \$\begingroup\$ I was doing changes sorry i missed to include that part. i edited it once again. \$\endgroup\$
    – ZozeR
    Dec 23, 2019 at 23:09
  • \$\begingroup\$ @ZozeR just curious, was the position of object(player) on z axis any different from 0? \$\endgroup\$ Dec 23, 2019 at 23:58
  • \$\begingroup\$ it was 0, i tent to reset each object's transform when I create them. but it seems the problem was caused by the mouse input z-axis, i think. \$\endgroup\$
    – ZozeR
    Dec 24, 2019 at 0:03

You must log in to answer this question.

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