How to move and rotate where the mouse clicks?

3

I created a script in which my character moves around the mouse but has a problem: it is not spinning > Y , this is the condition I had to create for it to spin on the X axis:

else if (target.x >= target.z)

But I wish that when he was up he would rotate and keep his head up.

I created this script so that it would turn up and down, but when I click it, it will go to the left script and it will look like this:

varangle=Mathf.Atan2(target.y-transform.position.y,target.x-transform.position.x)*Mathf.Rad2Deg;transform.rotation=Quaternion.Euler(0,0,angle);

publicfloatspeed=5.0f;privateVector3target;privateVector3target_rot;privateAnimatordash;privateAnimatorjumpe;//UsethisforinitializationvoidStart(){target=transform.position;dash=GetComponent<Animator>();jumpe=GetComponent<Animator>();}//UpdateiscalledonceperframevoidUpdate(){if(Input.GetMouseButtonDown(0)){target=Camera.main.ScreenToViewportPoint(Input.mousePosition);target.z=transform.position.x;dash.SetInteger("condicao", 1);
        target_rot = Camera.main.ScreenToViewportPoint(Input.mousePosition);
    } else if (transform.position == target) 
    {    
        dash.SetInteger ("condicao", 2); 
    }

    if (target.x <= target.z) {
        transform.localScale = new Vector3 (-1, 1, 1); 
    } else if (target.x >= target.z) {
        transform.localScale = new Vector3 (1, 1, 1); 
    } 

    transform.position = Vector3.MoveTowards (transform.position, target,   speed *Time.deltaTime);
  }

}
    
asked by anonymous 19.10.2017 / 06:14

1 answer

4

You are using scale changes (size) of the object with a negative value on the X axis to simulate the rotation in the left-right direction. That is, by doing transform.localScale = new Vector3 (-1, 1, 1); , you simply "flip" (mirror 180 degrees) the image on that axis. Not the best solution in the world, but it works. The problem is that afterwards you want to rotate the object in the "correct" way (that is, using angular rotation to make it point in the direction of the target). But his "flip" on the X axis continues, so that the object spinning and flipping ends up upside down.

The solution is you do not flip the object on the X axis, and only use the angular rotation. To prevent it from tumbling upside down, you flick on the Y axis only when the spin causes it to flip. This occurs when the object moves up and to the left, or down and to the left. That is, only when the angle is greater than 90º (when it moves up and to the left) or is smaller than 90º (when it moves down and to the left).

  

This is because the rotation in Unity is counted from 0º to 360º from the "front" direction of the object, with a positive value when rotating counterclockwise and negative when rotating clockwise.

The code below, then, illustrates a possible solution. I removed the animation part because it does not exist in my example. And I added a deceleration beam, so the sprite moves more elegantly as you approach the target (and do not jump like crazy when on the target).

using UnityEngine;

public class Teste: MonoBehaviour
{
    public float speed = 5.0f;
    public float reductionRadius = 1.0f;

    // Update is called once per frame
    void Update()
    {
        // Use GetMouseButton para um efeito continuo. Caso contrário, vc precisará ficar
        // clicando para que o personagem se mova (porque GetMouseButtonDown só é True no
        // frame em que o mouse foi pressionado! Já GetMouseButton é True enquanto o mouse
        // estiver pressionado!).
        if(Input.GetMouseButton(0))
        {
            // Use posições do mundo, funciona melhor
            Vector3 target = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            // Como o jogo é 2D, vc não precisa de informação no eixo Z
            target.z = 0f;

            // Rotaciona o personagem em direção ao alvo
            var angle = Mathf.Atan2(target.y - transform.position.y, target.x - transform.position.x) * Mathf.Rad2Deg;
            transform.rotation = Quaternion.Euler(0, 0, angle);

            // Garante que ele não fique "de cabeça pra baixo", flipando o sprite no eixo Y
            // se o ângulo de movimento absoluto for maior do que 90 graus (isto é, sem importar
            // se ele está indo pra cima ou pra baixo)
            if(Mathf.Abs(angle) > 90f)
                transform.localScale = new Vector3(1f, -1f, 1f);
            else
                transform.localScale = new Vector3(1f, 1f, 1f);

            // Move o personagem em direção ao alvo (reduzindo a velocidade conforme
            // ele se aproxima do alvo, a partir de um raio de redução configurado)
            float dist = (target - transform.position).magnitude;
            float movement = speed * Time.deltaTime;
            if(dist < reductionRadius)
                movement *= dist / reductionRadius;

            transform.position += (target - transform.position).normalized * movement;
        }
    }
}

Illustration of working code:

Notethatthecharacter"blinks" when the sprite is reversed (that is, it immediately changes sideways when "flipping" happens). That's why I said: This approach works, but it does not look really good. To do something more professional, use a transition animation between left and right.

    
22.10.2017 / 03:19