Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Resolved Look at the player (2D)

Discussion in '2D' started by Gabo19x, Apr 22, 2021.

  1. Gabo19x

    Gabo19x

    Joined:
    Oct 23, 2020
    Posts:
    96
    Hello
    I am making a game with a view from above, the problem is that the enemies do not look at the player correctly: they rotate in strange ways and it affects me a lot because the targeting of the enemies is fatal.

    A part of the script
    Code (CSharp):
    1. Vector3 objetivo = jugador.transform.position;
    2.             objetivo.Normalize();
    3.             float angulo = Mathf.Atan2(objetivo.y, objetivo.x) * Mathf.Rad2Deg;
    4.             transform.localRotation = Quaternion.Euler(0f, 0f, angulo);
     
  2. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    you are normalizing a position there, not a direction, which makes no sense unless whatever is calling this script is on position (0, 0, 0)...

    generally unless I m really missing something, your entire script is dependent on the transform to be in the scene origin...
    otherwise your angel calculation also makes no sense...
    and you mixing local rotation with global transform positions is also wierd

    i think what you are trying to do is the following:

    Code (CSharp):
    1. Vector3 directionToJugador = jugador.transform.position - transform.position;
    2. directionToJugador.z = 0; //lets ignore the z value since we are in 2D
    3. Vector3 currentLookDirection = transform.up; //I assume that you set your enemy up to look upwards by default, (as in green axis is look direction), if you instead set it up to take the x (red) axis as look direction, replace this with transform.right
    4. currentLookDirection.z = 0; //shouldnt be neccessary tho...
    5. float angleToNewLookDirection =  Vector3.Angle(currentLookDirection, directionToJugador);
    6. transform.Rotate(Vector3.forward, angleToNewLookDirection); //we use Vector3.forward here as the rotation axis because this is the z axis and we are in 2D (so Vector3.forward is actually not forward but rather outward for us)
    7.  
     
  3. Gabo19x

    Gabo19x

    Joined:
    Oct 23, 2020
    Posts:
    96
    I had previously asked for help on the forum and they had advised me to do the above ...
    Thanks to your help, the enemies now look at the player correctly, but, they have some sharp turns.
     
  4. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    thats because this here:

    Code (CSharp):
    1. float angleToNewLookDirection =  Vector3.Angle(currentLookDirection, directionToJugador);
    2. transform.Rotate(Vector3.forward, angleToNewLookDirection);
    rotates them instantly to look at the player since the rotation angle is non restricted and thus can be the full rotation that is needed

    to slowly rotate towards the player you could clamp the ange (clamp means that you dont allow the value to go above or below a min/ max value)

    like:
    define a varibale
    float rotationSpeed = 5f; //to define the max rotation angle your enemy is allowed to rotate by in a single frame, this here would be 5° per frame (for a real "speed" definition in angle per second you would additionally take a look at the passed time of the frame, tho angle per frame suffices for now)

    Code (CSharp):
    1.  
    2. float angleToNewLookDirection =  Vector3.Angle(currentLookDirection, directionToJugador);
    3. angleToNewLookDirection= Mathf.Clamp(angleToNewLookDirection, -rotationSpeed, rotationSpeed);
    4. transform.Rotate(Vector3.forward, angleToNewLookDirection);
    5.  
    what this means on an example:
    if the enemy wants to rotate by 15° to look towards the player, it will instead rotate by 5° in the first frame since we clamped the rotate to 5°
    in the next frame it will calculate the target angle again which would then be about 10° (it was 15 befor but then we rotated by 5)
    this 10 degree rotation is clamped at 5 again so we just rotate by 5°
    similar for next frame after which the enemy will be looking at the player

    so essentially the idea here is to split of the rotation into several smaller rotations

    (if it still rotates to sharply with this, simply lower the rotationSpeed)
     
  5. Gabo19x

    Gabo19x

    Joined:
    Oct 23, 2020
    Posts:
    96
    Now he does not turn sharply, but he does a round to look at the player, that is, he gives 360 ° each time the player enters his attack area.
     
  6. TheNightglow

    TheNightglow

    Joined:
    Oct 1, 2018
    Posts:
    201
    ooooh sry my bad, instead of Vector3.Angle you want to use Vector3.SignedAngle

    Vector3.Angle will always output a positiv angle so no matter if the player is right or left of the enemy, the enemy will always turn right (thus turning ~360° instead of turning by a negative small angle)
     
  7. Gabo19x

    Gabo19x

    Joined:
    Oct 23, 2020
    Posts:
    96
    Thank you, I do some documentation and it seems that it is ready: the enemy does not turn unnecessarily and always aims at the player if he is in the zone.

    Final code:
    Code (CSharp):
    1. Vector3 objetivo = jugador.transform.position - transform.position;
    2.             objetivo.z = 0;
    3.             Vector3 direccion = transform.up;
    4.             direccion.z = 0;
    5.             float angulo = Vector3.SignedAngle(direccion, objetivo, Vector3.forward); //PRINCIPAL CHANGES
    6.             angulo = Mathf.Clamp(angulo, -velocidadRotacion, velocidadRotacion);
    7.             transform.Rotate(Vector3.forward, angulo);