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

Unity2D LookAt?!

Discussion in '2D' started by GoldenretriverYT, Jul 31, 2019.

  1. GoldenretriverYT

    GoldenretriverYT

    Joined:
    May 8, 2019
    Posts:
    13
    Hello,

    I have this method:
    Code (CSharp):
    1. public static Quaternion FaceObject(Vector2 myPos, Vector2 targetPos)
    2.     {
    3.         Vector2 direction = targetPos - myPos;
    4.         float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    5.         return Quaternion.AngleAxis(angle, Vector3.forward);
    6.     }
    This method gets called every second with the nearest enemy position as targetPos, and the position of the object for myPos.

    Now the problem is, I first used transform.LookAt (didn't work), then I searched for LookAt in 2D and tried different solutions, no of them worked. Does anyone know the solution?

    Whole script:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using System.Linq;
    5.  
    6. public class BotScript : MonoBehaviour {
    7.  
    8.     public float health = 100f;
    9.     public float framesUntilNextShoot = 90f;
    10.     public GameObject shootPrefab = null;
    11.  
    12.  
    13.     public static Quaternion FaceObject(Vector2 myPos, Vector2 targetPos)
    14.     {
    15.         Vector2 direction = targetPos - myPos;
    16.         float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    17.         return Quaternion.AngleAxis(angle, Vector3.forward);
    18.     }
    19.  
    20.     // Initalize player
    21.     void Start()
    22.     {
    23.         float x = Random.Range(-4.1f, 4.1f);
    24.         float y = Random.Range(-4, 3.8f);
    25.         health = 100f;
    26.  
    27.         gameObject.transform.position = new Vector2(x, y);
    28.  
    29.     }
    30.  
    31.     void FixedUpdate()
    32.     {
    33.         framesUntilNextShoot -= 1;
    34.  
    35.         //if (DistanceToClosestEnemy() < 300f)
    36.         //{
    37.             GameObject go = FindClosestEnemy();
    38.  
    39.             this.transform.rotation = FaceObject((Vector2)transform.position, (Vector2)go.transform.position);
    40.  
    41.             if(framesUntilNextShoot == 0f)
    42.             {
    43.                 framesUntilNextShoot = 90f;
    44.                 GameObject inst = Instantiate(shootPrefab, gameObject.transform.position, gameObject.transform.rotation);
    45.                 inst.transform.parent = this.transform;
    46.                 //print("Shoot pos: " + inst.transform.position.x + " " + inst.transform.position.y + " Script pos: " + this.transform.position.x + " " + this.transform.position.y + " GameObject pos: " + this.gameObject.transform.position.x + " " + this.gameObject.transform.position.y);
    47.                 inst.GetComponent<ProjectileScript>().StartShoot(go);
    48.             }
    49.  
    50.             Vector2 movement = (1f * (this.transform.rotation * Vector2.up))*Time.deltaTime;
    51.             this.transform.position = new Vector2(this.transform.position.x, this.transform.position.y) + movement;
    52.  
    53.         //}
    54.     }
    55.  
    56.     // Update is called once per frame
    57.     void Update () {
    58.         if(health < 1)
    59.         {
    60.             Destroy(this.gameObject);
    61.         }
    62.     }
    63.  
    64.     private void LookAt(Transform go)
    65.     {
    66.         Vector2 direction = new Vector2(go.position.x - this.transform.position.x, go.transform.position.y - this.transform.position.y);
    67.         float rotation = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
    68.         this.transform.eulerAngles = new Vector3(0, 0, rotation);
    69.     }
    70.  
    71.     public GameObject FindClosestEnemy()
    72.     {
    73.         GameObject[] gos;
    74.         gos = GameObject.FindGameObjectsWithTag("Enemy").Concat(GameObject.FindGameObjectsWithTag("Player")).ToArray();
    75.         GameObject closest = null;
    76.         float distance = Mathf.Infinity;
    77.         Vector3 position = transform.position;
    78.         foreach (GameObject go in gos)
    79.         {
    80.             Vector3 diff = go.transform.position - position;
    81.             float curDistance = diff.sqrMagnitude;
    82.             if (curDistance < distance)
    83.             {
    84.                 closest = go;
    85.                 distance = curDistance;
    86.             }
    87.         }
    88.         return closest;
    89.     }
    90.  
    91.     public float DistanceToClosestEnemy()
    92.     {
    93.         GameObject[] gos;
    94.         gos = GameObject.FindGameObjectsWithTag("Enemy");
    95.         GameObject closest = null;
    96.         float distance = Mathf.Infinity;
    97.         Vector3 position = transform.position;
    98.         foreach (GameObject go in gos)
    99.         {
    100.             Vector3 diff = go.transform.position - position;
    101.             float curDistance = diff.sqrMagnitude;
    102.             if (curDistance < distance)
    103.             {
    104.                 closest = go;
    105.                 distance = curDistance;
    106.             }
    107.         }
    108.         return distance;
    109.     }
    110. }
    111.  
     
  2. LiterallyJeff

    LiterallyJeff

    Joined:
    Jan 21, 2015
    Posts:
    2,802
    You can use LookAt but you have to understand what it does, and what parameters it expects in order to get the result you want.

    All the "Look" functions will be assuming that your object's "forward" is the Z axis, as is the standard for 3D objects in Unity. Given a position, they will orient your object with the Z axis facing it.

    For 2D objects, the "forward" axis is usually the X axis. The Z axis is pointing forward along the World Space Z axis so it appears flat to the camera as the sprite moves around on the XY plane. We don't want that to change.

    So instead we can use Quaternion.LookRotation, which accepts the Z and Y axis. We can tell it exactly which direction the Z and Y axis should face, which will result in the X axis pointing where we want.

    Code (CSharp):
    1. public void LookAt2D(Vector3 lookTarget)
    2. {
    3.     // the direction we want the X axis to face (from this object, towards the target)
    4.     Vector3 xDirection = (lookTarget - transform.position).normalized;
    5.  
    6.     // Y axis is 90 degrees away from the X axis
    7.     Vector3 yDirection = Quaternion.Euler(0, 0, 90) * xDirection;
    8.  
    9.     // Z should stay facing forward for 2D objects
    10.     Vector3 zDirection = Vector3.forward;
    11.  
    12.     // apply the rotation to this object
    13.     transform.rotation = Quaternion.LookRotation(zDirection, yDirection);
    14. }
     
    CunningLobster and vakabaka like this.
  3. vakabaka

    vakabaka

    Joined:
    Jul 21, 2014
    Posts:
    1,153
    I am using transform.up (right, -up, -right) as the lookAt in the 2d
    Code (CSharp):
    1. Vector2 direction = targetPos - myPos;
    2. transform.right = direction;
     
    Last edited: Aug 1, 2019
    LiterallyJeff likes this.
  4. GoldenretriverYT

    GoldenretriverYT

    Joined:
    May 8, 2019
    Posts:
    13
    Still not working (arrows show, where the top of their sprite should face)
    upload_2019-8-1_1-11-59.png
     
  5. GoldenretriverYT

    GoldenretriverYT

    Joined:
    May 8, 2019
    Posts:
    13
    Not working... Is it may be just the prefab?
    upload_2019-8-1_2-35-31.png
     
  6. GoldenretriverYT

    GoldenretriverYT

    Joined:
    May 8, 2019
    Posts:
    13
    Okay, fixed it.
    The problem was the nearest entity was itself, so it tried to rotate to itself.