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

Question Vector3 always returns (0,0,0) with GETComponent

Discussion in 'Scripting' started by lairdjames81, Aug 17, 2023.

  1. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    So here's what is happening, I really do need help as I am sure its something really stupid I am doing wrong.

    So I have a wave manger with a enemy class:
    Code (CSharp):
    1.  
    2. [System.Serializable]
    3. public class Enemy
    4. {
    5.     public GameObject enemyObject;
    6.     public int startingPos;
    7.     public float speed;
    8.     public int[] waypoints;
    9.  
    10. }
    11.  
    12. public class WaveManager : MonoBehaviour
    13. {
    14.  
    15.     public Enemy[] enemies;
    16.     public IntVariable enemyCount;
    17.     public FloatingBool endWave;
    18.     public IntVariable waveNumber;
    19.     public ParticleSystem entranceEffect;
    20.     public float waitForNextEnemy;
    21.     public Vector3 currentPos;
    22.     public GameObject target;
    23.  
    24.     public LevelManager levelManager;
    25.  
    26.  
    27.  
    28.     private void Awake()
    29.     {
    30.    
    31.         foreach (Enemy enemy in enemies)
    32.         {
    33.             Instantiate(entranceEffect, Grid.Instance.locations[enemy.startingPos], Quaternion.identity);
    34.             Instantiate(enemy.enemyObject, Grid.Instance.locations[enemy.startingPos], Quaternion.identity);
    35.             enemy.enemyObject.GetComponent<Movement>().arr = enemy.waypoints;
    36.             levelManager.enemies.Add(enemy);
    37.  
    38.         }
    39.    
    40.     }
    This holds the enemies for each wave, an adds them to a level manager List

    Code (CSharp):
    1. public enum WaveState { spawning, waiting, counting };
    2.  
    3. [System.Serializable]
    4. public class Wave
    5. {
    6.     public GameObject wave;
    7.     public Transform focalPoint;
    8.     public int count;
    9.     public float rate;
    10.     public int speed;
    11.     public int numberOfEnemiesBeforeNextWave;
    12.     public float zoomAmt;
    13.     public float zoomSpeed;
    14.  
    15. }
    16.  
    17.  
    18. public class LevelManager : MonoBehaviour
    19. {
    20.  
    21.     public Wave[] waves;
    22.     public GameObject player;
    23.     public int nextWave = 0;
    24.  
    25.     public List<Enemy> enemies;
    26.     public float timeBetweenWaves;
    27.     public float waveCountDown;
    28.     public WaveState state = WaveState.counting;
    29.  
    30.     public IntVariable enemyCount;
    31.  
    32.     public Vector3 relativePos;
    33.     public Quaternion rotation;
    34.  
    35.     public Vector3 testVector;
    36.  
    37.     public GameObject levelOverHolder;
    38.  
    39.     public Vector3 levelHolderPos;
    40.  
    41.     public RectTransform levelOverScreen;
    42.  
    43.     public FloatingBool startWave;
    44.     public float zoomAmtVisual;
    45.     public IntVariable levelNumber;
    46.  
    47.     public FloatingBool endLevel;
    48.  
    49.     public FloatingBool gameInProgess;
    50.  
    51.  
    52.     void Start()
    53.     {
    54.         enemyCount.Value = 0;
    55.         waveCountDown = timeBetweenWaves;
    56.         gameInProgess.Value = true;
    57.  
    58.     }
    59.  
    60.     void Update()
    61.     {
    62.         for (int i = 0; i < enemies.Count; i++)
    63.         {
    64.             Debug.Log(enemies[i].enemyObject.name, enemies[i].enemyObject.GetComponent<Movement>());
    65.         }
    66.         relativePos = waves[nextWave].focalPoint.transform.position - player.transform.position;
    67.         rotation = Quaternion.LookRotation(relativePos, Vector3.up );
    68.         player.transform.rotation = Quaternion.Lerp(player.transform.rotation, rotation, waves[nextWave].speed * Time.deltaTime);
    69.         Camera.main.fieldOfView = Mathf.Lerp(Camera.main.fieldOfView, waves[nextWave].zoomAmt, waves[nextWave].zoomSpeed * Time.deltaTime);
    70.         zoomAmtVisual = waves[nextWave].zoomAmt;
    71.  
    72.         if (state == WaveState.waiting)
    73.         {
    74.             if (enemyCount.Value <= waves[nextWave].numberOfEnemiesBeforeNextWave && startWave.Value == false)
    75.             {
    76.  
    77.                 //WaveCompleted();
    78.  
    79.  
    80.             }
    81.         }
    82.  
    83.         if(waveCountDown<= 0)
    84.         {
    85.             if (state != WaveState.spawning)
    86.             {
    87.                 StartCoroutine(SpawnWave(waves[nextWave]));
    88.             }
    89.         }
    90.  
    91.         else
    92.         {
    93.             waveCountDown -= Time.deltaTime;
    94.         }
    95.  
    96.     }
    97.  
    98.     void WaveCompleted()
    99.     {
    100.        
    101.  
    102.         state = WaveState.counting;
    103.         waveCountDown = timeBetweenWaves;
    104.        
    105.  
    106.         if (nextWave + 1 > waves.Length - 1)
    107.         {
    108.             levelOverScreen.DOAnchorPos(Vector2.zero, 0.5f);
    109.             endLevel.Value = true;
    110.  
    111.         }
    112.  
    113.         nextWave++;
    114.         testVector = waves[nextWave].focalPoint.transform.position;
    115.         relativePos = waves[nextWave].focalPoint.transform.position - player.transform.position;
    116.         rotation = Quaternion.LookRotation(relativePos, Vector3.up);
    117.         player.transform.rotation = Quaternion.Lerp(player.transform.rotation, rotation, waves[nextWave].speed * Time.deltaTime);
    118.         Debug.Log("wavecomplete");
    119.     }
    120.  
    121.     IEnumerator SpawnWave(Wave _wave)
    122.     {
    123.         state = WaveState.spawning;
    124.  
    125.         _wave.wave.SetActive(true);
    126.  
    127.         state = WaveState.waiting;
    128.  
    129.         yield break;
    130.     }
    131.  
    132. }
    133.  
    I then have a button which I want to press which will shoot a bullet at each of the enemies:

    Code (CSharp):
    1.  
    2. public class MultiShotSpecial : MonoBehaviour
    3. {
    4.     public LevelManager levelManager;
    5.     public GameObject playerAimBot;
    6.     public GameObject multiShotBullet;
    7.     private Vector3 enemyPos;
    8.     public Button barrelRollButton;
    9.  
    10.     private void Start()
    11.     {
    12.         barrelRollButton.onClick.AddListener(Shot);
    13.     }
    14.  
    15.     public void Shot()
    16.     {
    17.         for (int i = 0; i < levelManager.enemies.Count; i++)
    18.         {
    19.             if (levelManager.enemies[i] != null)
    20.             {
    21.  
    22.                 Enemy enemy = levelManager.enemies[i];
    23.  
    24.                 enemyPos = enemy.enemyObject.transform.position;
    25.  
    26.                 Debug.Log("enemyPos " + enemyPos);
    27.  
    28.                 Vector3 direction = enemyPos - playerAimBot.transform.position;
    29.                 Quaternion  rotation = Quaternion.LookRotation(direction);
    30.                 playerAimBot.transform.rotation = rotation;
    31.  
    32.                 GameObject _bullet = Instantiate(multiShotBullet, playerAimBot.transform.position, rotation);
    33.                
    34.                 IShootable shootable = multiShotBullet.GetComponent<IShootable>();
    35.                 shootable.Shoot();
    36.  
    37.             }
    38.         }
    39.     }
    40. }
    41.  
    but the transform I get is 0,0,0

    please for the love of god can someone help?!
     
    Last edited: Aug 18, 2023
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,718
    Please see https://forum.unity.com/threads/using-code-tags-properly.143875/ for proper code formatting.

    Anyway my guess is your list is probably referring to prefabs rather than the actual enemies in the scene. Also I don't see the point of the
    currentPos
    variable since ti can just be retrieved through transform.position. This is wasteful.
     
    Bunny83 likes this.
  3. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    Welcome. First of all, please use code tags to post code examples. This is pretty much unreadable.

    You write in code:
    Code (CSharp):
    1. enemyPos = levelManager.enemies.GetComponent<Movement>().currentPos;
    Enemies as in plural, yet you try to call GetComponent? You wrote your level manager keeps a list of enemies. And you try to get a component .. of a list? That doesnt really make sense, nor should it even run. Do you have errors in your console?
     
  4. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Nice one for the link, ill use that in future. I have a foreach loop to instantiate the enemies and then add them to the list. I can post that as well if that helps? How would i know if it was a prefab or the actual enemy that is in the scene?

    The currentPos was literally just to make sure the enemy itself was giving out the correct transform.
     
  5. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Nope no errors. The level manager enemies bit seems to have not pasted the index when i copied this, i do define the actual enemy i want
     
  6. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    For one, I'd make a List of the enemies classes, not the game objects. That way you already have the components, and wouldn't need to keep "getting" them.

    I disagree with this a little, caching the transform is a micro performance. However caching "transform.position" does nothing, as the transform would still need it's GetComponent() call for that. But true, that's just a readability thing as it sits.

    As Yoreki mentions, calling for a singular return on a List without an index is like casting a fishing line on your roof, wondering why no fish are biting.

    I am confused by this, do you want one bullet to hit all enemies, or do you want a bullet for each enemy?
     
  7. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    You can add a context object to any Debug.Log call as second argument. This context object has to be a UnityEngine.Object derived type (like GameObject, MonoBehaviour, Mesh, Material, whatever....) When you click on that message in the console, Unity will highlight that object in the editor. So add a
    gameObject
    to each of your two Log statements and see which objects respond
     
  8. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    I had to syntax out your code, you need the
    [i]
    after enemies(in both calls for the list), and your missing a closing bracket
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4. using UnityEngine.UI;
    5.  
    6. public class MultiShotSpecial : MonoBehaviour
    7. {
    8.     public LevelManager levelManager;
    9.     public GameObject playerAimBot;
    10.     public GameObject multiShotBullet;
    11.     private Vector3 enemyPos;
    12.     public Button barrelRollButton;
    13.  
    14.     private void Start()
    15.     {
    16.         barrelRollButton.onClick.AddListener(Shot);
    17.     }
    18.  
    19.     public void Shot()
    20.     {
    21.         for (int i = 0; i < levelManager.enemies.Count; i++)
    22.         {
    23.             if (levelManager.enemies[i] != null)
    24.             {
    25.  
    26.                 enemyPos = levelManager.enemies[i].GetComponent<Movement>().currentPos;
    27.  
    28.                 Debug.Log("enemyPos " + enemyPos); // enemyPos (0.00, 0.00, 0.00)
    29.  
    30.  
    31.                 Vector3 direction = enemyPos - playerAimBot.transform.position;
    32.                 Quaternion rotation = Quaternion.LookRotation(direction);
    33.                 playerAimBot.transform.rotation = rotation;
    34.  
    35.                 GameObject _bullet = Instantiate(multiShotBullet, playerAimBot.transform.position, rotation);
    36.  
    37.                 IShootable shootable = multiShotBullet.GetComponent<IShootable>();
    38.                 shootable.Shoot();
    39.             // missing bracket "}"
    40.         }
    41.     }
    42. }
     
    Last edited: Aug 17, 2023
  9. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,495
    Well, he most likely has those in his code. However since he failed to properly put his code into a code section here, the
    [i]
    was probably be interpreted as a BB code for italic text. So @lairdjames81, please, when you edit your first post to properly format your code, copy your actual code again from your source and don't just edit the text in your post. Saving code as text in a forum can mess up several things. That doesn't really help identifying issues with your code when most of the issues come from misformatting the code here in the forum.

    ps: looking at the source code of the OP, we can even see the italic tag:
    upload_2023-8-18_0-57-27.png
     
    Yoreki and wideeyenow_unity like this.
  10. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Nice one, to be honest its the first time I have done this (as i think everyone has realised). Ill go back and sort it.

    Thanks for doing that though thats much appreciated.
     
  11. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Amazing thanks I will give this a try
     
  12. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Its gonna be one bullet per enemy, so it iterates through the list and shoots each enemy in turn.

    I do have a class of enemy, it just wasnt giving me the correct transform position back, thats why i stuck the currentPos on the the object to make sure it gave the correct result(which it did) so then i figured i would just try and get that data as at least that was right. Ive gone down a proper rabbit hole of ideas here. The only thing that worked was finding the enemy with its tag, but i have read that not really great, and its a bit crass when this way surely should work.
     
  13. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Well, I mean:
    Code (CSharp):
    1. public class LevelManager : MonoBehaviour
    2. {
    3.    public List<Enemy> enemies;
    4. }
    That way you can easily call each enemies "anything" within their script:
    Code (CSharp):
    1. public void Shot()
    2.     {
    3.         for (int i = 0; i < levelManager.enemies.Count; i++)
    4.         {
    5.             if (levelManager.enemies[i] != null)
    6.             {
    7.                 Enemy enemy = levelManager.enemies[i];
    8.                 enemyPos = enemy.transform.position;
    9.                 print($"enemy {enemy.name} is at pos: {enemyPos} with health {enemy.health}");
    10.  
    11.                 Vector3 direction = enemyPos - playerAimBot.transform.position;
    12.                 Quaternion rotation = Quaternion.LookRotation(direction);
    13.                 playerAimBot.transform.rotation = rotation;
    14.  
    15.                 GameObject _bullet = Instantiate(multiShotBullet, playerAimBot.transform.position, rotation);
    16.  
    17.                 IShootable shootable = multiShotBullet.GetComponent<IShootable>();
    18.                 shootable.Shoot();
    19.             }
    20.         }
    21.     }
    It seems a little overkill for just position, so I threw the health variable in the print, just for an example. And your enemy class would just need to reference the levelManager script and say:
    Code (CSharp):
    1. void Awake()
    2. {
    3.    levelManager.enemies.Add(this);
    4. }
    As when you say
    Add.(this)
    it adds the enemies script to that list. Which makes life easier, than to keep calling GetComponent() a bunch of times. And once you get used to that type of Singleton usage, script communication problems is never a thing. :)
     
  14. Yoreki

    Yoreki

    Joined:
    Apr 10, 2019
    Posts:
    2,588
    OP, please, you replied about a gazillion times since we asked you (multiple times) to please edit the initial post and add the code using code tags for proper formatting. Why do i still see this italic, bold, red, huge mess in the first post? :p
     
  15. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Im at work init, and then i'll try these ideas. Then change the post up if its not solved to make it more satisfactory.
     
    Yoreki likes this.
  16. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13

    all done, looks much better. I've tried the stuff wideeyenow_unity has suggested, but its still not working. I'm hoping that now its formatted properly you can see my mistake.
     
  17. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    you don't need to call the gameObject, just
    Code (CSharp):
    1. enemyPos = enemy.transform.position;
     
  18. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    My example was if you had the enemy class(MonoBehaviour) on the enemy object, then just instantiating the enemy would wake up it's script, then enemy Awake() method would add it to the list. So all you need to do after that is just call the Lists index to call the proper enemy(and all of it's variables).

    But I see you use the enemy class as a raw class, I'm not sure how that works. As calling transform is a MonoBehaviour related thing. So I'm assuming if you still want to use a raw class, and reference the gameObject, the prefab would need the gameObject set in the inspector(or get through code). So in that case, true, you would have to call
    enemies[i].enemyObject.transform.position
     
  19. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    Ive changed that and its not 0,0,0 anymore but 0.36,-0.91,0.19 but the gameobject is at -2.2,3.04,1.5
     
  20. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Here hopefully this helps, as it might be confusing still:
    Code (CSharp):
    1. public class Enemy : Monobehaviour
    2. {
    3.     // public GameObject enemyObject;
    4.     // set in inspector if not static list
    5.     public GameObject levelManager;
    6.     public int startingPos;
    7.     public float speed;
    8.     public int[] waypoints;
    9.  
    10.     void Awake()
    11.     {
    12.         // if static list
    13.         LevelManager.enemies.Add(this);
    14.         // if not static list
    15.         levelManager.GetComponent<LevelManager>().enemies.Add(this);
    16.     }
    17. }
    18.  
    19. public class WaveManager : MonoBehaviour
    20. {
    21.     Instantiate(enemyObjectPrefab, Grid.Instance.locations[enemy.startingPos], Quaternion.identity);
    22.     // enemy.enemyObject.GetComponent<Movement>().arr = enemy.waypoints;
    23.     // levelManager.enemies.Add(enemy);
    24. }
    25.  
    26. public class LevelManager : MonoBehaviour
    27. {
    28.     // if static
    29.     public static List<Enemy> enemies = new List<Enemy>();
    30.     // if not static
    31.     public List<Enemy> enemies = new List<Enemy>();
    32.  
    33.     for (int i = 0; i < enemies.Count; i++)
    34.     {
    35.         Debug.Log(enemies[i].name);
    36.     }
    37. }
    If using the example I mentioned :)
     
    Last edited: Aug 18, 2023
  21. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    well at least it's showing something! :)

    But that would have to do with what position you gave it upon Instantiation.
     
  22. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    wait.. that actually makes no sense, is there a child parent relationship with the gameObject? Upon Instantiation, I don't see you setting a parent transform, so there should only be one gameObject with one position.

    To double check, the enemy object is just a singular object? and if it's set as a prefab, and you instantiate that prefab, and the prefab has the Enemy.cs on it, there should be no issues. Because the only way you'd be getting 2 different positions is if there was two different instances, there should only be one.
     
  23. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13

    yeah it literally one here with a couple of aimbots on it. This is why I am so confused, there is nothing at that vector that it gives out.

    I think the best course of action is to set it up differently. I'm gonna lose my mind if I continue with this.
     
  24. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    The only other thing I can think, is you don't have the Enemy.cs as a separate script. The way you show it in the first code snippet makes me think it's within that other class.

    Just make sure enemyPrefab has (single class)Enemy.cs attached to it. And it will work just fine.

    But sure if you don't like my method, then just use a list of gameObjects, and use GetComponents.
     
  25. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    I think I am gonna set up a separate class of the enemy and not intertwine it with the wave manager and level manager as much
     
  26. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13

    Nah it's not your method, that method just threw up other issues, I think its more my coding than your response!

    Thanks so much for your help though!
     
    wideeyenow_unity likes this.
  27. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    That is common practice, if you make an object or prefab, you want it to have it's class on it, that way you can reference it specifically. And then if you so choose to, add other scripts to it, for other things, and just reference those through the objects particular class, so you can get all references through that one script.

    All my method does is cache the script of the object, so you don't need to keep calling GetComponent. That's all that's different.
     
  28. lairdjames81

    lairdjames81

    Joined:
    Dec 26, 2020
    Posts:
    13
    I think that learning off YouTube etc I ended up mixing so many ideas that the whole thing becomes more and more messy. I have cleaned up so many bad ideas up already, but things are slowly coming together.

    Thanks again for your help, was really nice of you to take your time to do it.
     
    wideeyenow_unity and Yoreki like this.
  29. wideeyenow_unity

    wideeyenow_unity

    Joined:
    Oct 7, 2020
    Posts:
    728
    Yup, no problem! I just wish I could explain it better, as I remember first digging into code I never understood what a component was, and took forever to realize they're basically just scripts. Like Transform, GameObject, etc... They all are a class somewhere in the internal code of MonoBehaviour.

    So after dealing with GameObject.GetComponent enough, I eventually learned what caching was, and how much better, and less typing it was. So it's hard for me to go back in time to explain all the things I figured out along the way on each hurdle.

    But yup, keep playing with it, it's the only way you'll figure it all out. And don't stress out, if you do take a break from it. An idea will always pop up later, and attack the problem again with a fresh mind.