How to move and rotate where the mouse click is?

Asked

Viewed 1,337 times

3

I created a script in which my character moves through click of mouse but there’s a problem: it’s not spinning in position Y, this is the condition I had to create for it to Rotacione on the axis X:

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

But I wish that when he went up he would rotate and turn his head up.

I created this script so that it would rotate up and down, but when I click it to go left script ends up like this:

inserir a descrição da imagem aqui

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

inserir a descrição da imagem aqui

public float speed = 5.0f;

private Vector3 target;
private Vector3 target_rot;

private Animator dash;
private Animator jumpe;

// Use this for initialization
void Start () {
    target = transform.position;
    dash = GetComponent<Animator> ();
    jumpe = GetComponent<Animator> ();
}

// Update is called once per frame
void Update () {
    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);
  }

}

1 answer

4

You are using scale changes (size) of the object with negative value on the X-axis to simulate left-right rotation. I mean, in doing transform.localScale = new Vector3 (-1, 1, 1);, you simply "flip" (mirror at 180 degrees) the image on that axis. It’s not the best solution in the world, but it works. The problem is that you then want to rotate the object "correctly" (that is, using angular rotation to make it point in the direction of the target). Only that its "flip" on the X axis continues, so that the object spinning and flipping ends up being upside down.

The solution is you don’t flip the object on the X-axis, and just use the angular rotation. To prevent it from turning upside down, you flip on the y-axis only when the rotation makes it turn upside down. This occurs when the object moves up and left, or down and left. That is, only when the angle is greater than 90º (when it moves up and left) or is smaller than 90º (when it moves down and left).

This is because the rotation in Unity is counted from 0º to 360º from the "front" direction of the object, with positive value when rotating counterclockwise and with negative value 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’ve added a deceleration radius, so the Chief moves more elegantly when approaching the target (and don’t jump like a madman when on 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:

inserir a descrição da imagem aqui

Note that the character "blinks" when the Sprite is reversed (i.e., it changes immediately when the "flip" occurs). That’s why I said, this approach works, but it doesn’t really work. To do something more professional, use a transition animation between left and right.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.