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 Position issue?

Discussion in 'Scripting' started by AerionXI, Jul 13, 2022.

  1. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    I downloaded this Infinite plane script to help with prototyping my game. For some reason, however, I cannot get the plane to be as many "tiles" as i need because I think the math is a little wrong. How can I fix this? When I set X groundSize and Z groundSize, the tiles aren't always correctly positioned.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using System.Collections.Generic;
    4. using UnityEngine;
    5.  
    6. public class InfiniteGround : MonoBehaviour {
    7.  
    8.     ///Deactiavate ground yg tidak terlihat > pindahkan posisi-nya > activate lagi
    9.  
    10.     [Tooltip("Pivot for the ground to follow")]
    11.     public Transform target;
    12.  
    13.     [SerializeField] Transform groundPrefab;
    14.  
    15.     [SerializeField, Tooltip("Ground size in world scale")]
    16.     Vector3 groundSize = new Vector3(1f, 0f, 1f);
    17.  
    18.  
    19.     readonly List<Transform> spawnedGround = new List<Transform>();
    20.  
    21.     Vector3 groundOffset;
    22.     Vector3 groundSizeHalf;
    23.     Vector3 newGroundTrigger;
    24.  
    25.     private void Awake()
    26.     {
    27.         groundOffset = groundSize * 3f;
    28.         groundSizeHalf = groundSize * 0.5f;
    29.         newGroundTrigger = groundSize + groundSizeHalf;
    30.  
    31.         for (int i = -1; i <= 1; i++) {
    32.             for (int j = -1; j <= 1; j++) {
    33.                 SpawnGround(new Vector3(i * groundSize.x, 0, j * groundSize.z));
    34.             }
    35.         }
    36.  
    37.         void SpawnGround(Vector3 pos) {
    38.             Transform obj = Instantiate(groundPrefab, transform);
    39.             obj.transform.position = pos;
    40.             spawnedGround.Add(obj);
    41.         }
    42.     }
    43.  
    44.     private void Update() {
    45.         FixOutsideRange();
    46.     }
    47.  
    48.     void FixOutsideRange() {
    49.         for (int i = 0; i < spawnedGround.Count; i++) {
    50.             Vector3 groundPos = spawnedGround[i].position;
    51.             Vector3 mag = target.position - groundPos;
    52.             if (mag.x < -newGroundTrigger.x)
    53.             {
    54.                 groundPos.x -= groundOffset.x;
    55.             }
    56.             else if (mag.x > newGroundTrigger.x)
    57.             {
    58.                 groundPos.x += groundOffset.x;
    59.             }
    60.  
    61.             if (mag.z < -newGroundTrigger.z)
    62.             {
    63.                 groundPos.z -= groundOffset.z;
    64.             }
    65.             else if (mag.z > newGroundTrigger.z)
    66.             {
    67.                 groundPos.z += groundOffset.z;
    68.             }
    69.  
    70.             spawnedGround[i].transform.position = groundPos;
    71.         }
    72.     }
    73. }
    74.  
    Any help is most-greatly appreciated!

    Thank you!
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    All programs and all parts of all programs solely exist to transform data. You are reporting a data problem. Therefore staring at code won't be useful. Here's how to debug the above code.

    What is often happening in these cases is one of the following:

    - the code you think is executing is not actually executing at all
    - the code is executing far EARLIER or LATER than you think
    - the code is executing far LESS OFTEN than you think
    - the code is executing far MORE OFTEN than you think
    - the code is executing on another GameObject than you think it is
    - you're getting an error or warning and you haven't noticed it in the console window

    To help gain more insight into your problem, I recommend liberally sprinkling Debug.Log() statements through your code to display information in realtime.

    Doing this should help you answer these types of questions:

    - is this code even running? which parts are running? how often does it run? what order does it run in?
    - what are the values of the variables involved? Are they initialized? Are the values reasonable?
    - are you meeting ALL the requirements to receive callbacks such as triggers / colliders (review the documentation)

    Knowing this information will help you reason about the behavior you are seeing.

    You can also supply a second argument to Debug.Log() and when you click the message, it will highlight the object in scene, such as
    Debug.Log("Problem!",this);


    If your problem would benefit from in-scene or in-game visualization, Debug.DrawRay() or Debug.DrawLine() can help you visualize things like rays (used in raycasting) or distances.

    You can also call Debug.Break() to pause the Editor when certain interesting pieces of code run, and then study the scene manually, looking for all the parts, where they are, what scripts are on them, etc.

    You can also call GameObject.CreatePrimitive() to emplace debug-marker-ish objects in the scene at runtime.

    You could also just display various important quantities in UI Text elements to watch them change as you play the game.

    If you are running a mobile device you can also view the console output. Google for how on your particular mobile target, such as this answer or iOS: https://forum.unity.com/threads/how-to-capturing-device-logs-on-ios.529920/ or this answer for Android: https://forum.unity.com/threads/how-to-capturing-device-logs-on-android.528680/

    Another useful approach is to temporarily strip out everything besides what is necessary to prove your issue. This can simplify and isolate compounding effects of other items in your scene or prefab.

    Here's an example of putting in a laser-focused Debug.Log() and how that can save you a TON of time wallowing around speculating what might be going wrong:

    https://forum.unity.com/threads/coroutine-missing-hint-and-error.1103197/#post-7100494

    You must find a way to get the information you need in order to reason about what the problem is.
     
    TheDevloper likes this.
  3. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    I already know what's going on. As far as I am aware, the i & j numbers are somehow too big....
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Then somehow a calculation is wrong. Again, staring at code won't fix this, because it won't show where the calculation goes astray.
     
  5. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    Here's what it SHOULD look like :



    Here's what it is doing :

     
  6. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    I don't understand what I'm doing wrong here... The problem is the number, but what am I NOT putting in the code to stop it from doing what it SHOULDN'T be doing like above?
     
  7. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Are you simply not setting the positions and all the ground chunks are located at (0,0,0) rather than laid out in a grid?
     
  8. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    I believe I am setting the positions because the tiles follow me. But.....
     
  9. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    What do I need to multiply by to get "x" amount of tiles to show up in the right places?
     
  10. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    I think the issue is more the fact that you don't really understand what this piece of code actually does. So lets clear up some confusion:

    • This script creates exactly 9 ground tiles in a 3x3 pattern. The values i and j go from -1 to 1. This is hardcoded into the script.
    • In the screenshot you've shown it seems your tiles are way too far spread out. This indicates you haven't set the groundsize to the correct size. How large this should be depends on how large one of your ground tiles is. You have set the groundsize to 50 in "x" and "z" but it seems one tile is much smaller than that.
    • As mentioned in the last point, the groundsize does not change how many tiles there are or how large a tile appears. It's actually a configuration setting that has to be adapted to the size of your ground tile.
    According to your initial post you want to have "more tiles" around you. Note that having a lot of objects is bad for performance. Relatively small amounts should be no problem. However if you create, say 100x100 tiles that would be 10k tiles in total.

    In order to get more tiles you have to modify the script to create more tiles than just the hardcoded 9. You could introduce a "radius" setting and adjust your for loops like this:

    Code (CSharp):
    1.     for (int i = -r; i <= r; i++) {
    2.         for (int j = -r; j <= r; j++) {
    3.             // [ ... ]
    Here the variable "r" should be a positive integer.
    Code (CSharp):
    1. public int r = 1;
    Increasing r would create more tiles. Though keep in mind that the number of tiles increase with the square of that number. So you get
    Code (CSharp):
    1. // r  | number of tiles | size
    2. //-----------------------------
    3. // 0  |   1             | 1x1
    4. // 1  |   9             | 3x3
    5. // 2  |  25             | 5x5
    6. // 3  |  49             | 7x7
    7. // 4  |  81             | 9x9
    8. // 5  | 121             | 11x11
    9. // 6  | 169             | 13x13
    Of course the first thing you should do is fix your groundsize variable so it represents the correct size again.
     
  11. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Note I haven't really looked that deep into the script yet. However there are other things that need to be changed as well. As I said the script was designed with a hardcoded grid size of 3x3. So the "groundOffset" as well as the newGroundTrigger are both wrong as well. It needs to be

    Code (CSharp):
    1. groundOffset = groundSize * (1 + r*2);
    2. newGroundTrigger = groundSize * (0.5f+r);
    3.  
    Otherwise the whole wrapping logic wont work.
     
    Last edited: Jul 14, 2022
  12. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Bunny83 what am i doing wrong here?

    Specifically, line{s} 55 - 59

    Code (CSharp):
    1. public class InfiniteGround : MonoBehaviour {
    2.  
    3.     ///Deactiavate ground yg tidak terlihat > pindahkan posisi-nya > activate lagi
    4.  
    5.     [Tooltip("Pivot for the ground to follow")]
    6.     public Transform target;
    7.  
    8.     [SerializeField] Transform groundPrefab;
    9.  
    10.     [SerializeField, Tooltip("Ground size in world scale")]
    11.     Vector3 groundSize = new Vector3(1f, 0f, 1f);
    12.  
    13.     [ Header ( "Tile Settings" ) ]
    14.     public int tileRadius = 3;
    15.     public int tileCount = 1;
    16.  
    17.     readonly List<Transform> spawnedGround = new List<Transform>();
    18.  
    19.     Vector3 groundOffset;
    20.     Vector3 groundSizeHalf;
    21.     Vector3 newGroundTrigger;
    22.  
    23.     private void Awake ( ) {
    24.  
    25.         // groundOffset = groundSize * 3f;
    26.         // groundSizeHalf = groundSize * 0.5f;
    27.         // newGroundTrigger = groundSize + groundSizeHalf;
    28.  
    29.         groundOffset = groundSize * (1 + tileRadius*2);
    30.         groundSizeHalf = groundSize * 0.5f;
    31.         newGroundTrigger = groundSize * (0.5f+tileRadius);
    32.  
    33.         float gSizeX = groundSize.x;
    34.         float gSizeZ = groundSize.z;
    35.  
    36.         Debug.Log ( $"groundOffset :: { groundOffset }" );
    37.         Debug.Log ( $"groundSizeHalf :: { groundSizeHalf }" );
    38.         Debug.Log ( $"newGroundTrigger :: { newGroundTrigger }" );
    39.  
    40.         for ( int i = -tileRadius; i <= tileRadius; i++ ) {
    41.  
    42.             for ( int j = -tileRadius; j <= tileRadius; j++ ) {
    43.  
    44.                 Debug.Log ( $"i :: { i }" );
    45.                 Debug.Log ( $"j :: { j }" );
    46.                 Debug.Log ( $"gSizeX :: { gSizeX }" );
    47.                 Debug.Log ( $"gSizeZ :: { gSizeZ }" );
    48.  
    49.                 int tileCountX = ( i * ( int ) gSizeX ) / 2;
    50.                 int tileCountZ = ( j * ( int ) gSizeZ ) / 2;
    51.  
    52.                 Debug.Log ( $"tileCountX :: { tileCountX }" );
    53.                 Debug.Log ( $"tileCountZ :: { tileCountZ }" );
    54.  
    55.                 SpawnGround ( new Vector3 (
    56.                     ( tileCountX ),
    57.                     0.0f,
    58.                     ( tileCountZ )
    59.                 ) );
    60.  
    61.                 tileCount = (
    62.                     ( ( tileCountX ) + ( tileCountZ ) ) +
    63.                     ( ( tileRadius ) + 1 )
    64.                 );
    65.  
    66.             }
    67.  
    68.         }
    69.  
    70.         void SpawnGround(Vector3 pos) {
    71.             Transform obj = Instantiate(groundPrefab, transform);
    72.             obj.transform.position = pos;
    73.             spawnedGround.Add(obj);
    74.         }
    75.     }
    76.  
    77.     private void Update() {
    78.         FixOutsideRange();
    79.     }
    80.  
    81.     void FixOutsideRange() {
    82.         for (int i = 0; i < spawnedGround.Count; i++) {
    83.             Vector3 groundPos = spawnedGround[i].position;
    84.             Vector3 mag = target.position - groundPos;
    85.             if (mag.x < -newGroundTrigger.x)
    86.             {
    87.                 groundPos.x -= groundOffset.x;
    88.             }
    89.             else if (mag.x > newGroundTrigger.x)
    90.             {
    91.                 groundPos.x += groundOffset.x;
    92.             }
    93.  
    94.             if (mag.z < -newGroundTrigger.z)
    95.             {
    96.                 groundPos.z -= groundOffset.z;
    97.             }
    98.             else if (mag.z > newGroundTrigger.z)
    99.             {
    100.                 groundPos.z += groundOffset.z;
    101.             }
    102.  
    103.             spawnedGround[i].transform.position = groundPos;
    104.         }
    105.     }
    106.  
    107. }
     
  13. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    i did exactly as you said... but the math is still wrong?
     
  14. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    You have your "SpawnGround" method in the Awake() method. That doesn´t work. Move the bracket from line 75 to line 69.

    And a hint: you don´t need 2 for loops, since you never change the value for i or j. So you can use i for tileCountX and tileCountY.

    Getting rid of loops is always a good thing.
     
  15. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Sphinks I did as you said, the math is still wrong.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InfiniteGround : MonoBehaviour {
    6.  
    7.     ///Deactiavate ground yg tidak terlihat > pindahkan posisi-nya > activate lagi
    8.  
    9.     [Tooltip("Pivot for the ground to follow")]
    10.     public Transform target;
    11.  
    12.     [SerializeField] Transform groundPrefab;
    13.  
    14.     [SerializeField, Tooltip("Ground size in world scale")]
    15.     Vector3 groundSize = new Vector3(1f, 0f, 1f);
    16.  
    17.     [ Header ( "Tile Settings" ) ]
    18.     public int tileRadius = 3;
    19.     public int tileCount = 1;
    20.  
    21.     readonly List<Transform> spawnedGround = new List<Transform>();
    22.  
    23.     Vector3 groundOffset;
    24.     Vector3 groundSizeHalf;
    25.     Vector3 newGroundTrigger;
    26.  
    27.     void SpawnGround(Vector3 pos) {
    28.         Transform obj = Instantiate(groundPrefab, transform);
    29.         obj.transform.position = pos;
    30.         spawnedGround.Add(obj);
    31.     }
    32.  
    33.     private void Awake ( ) {
    34.  
    35.         // groundOffset = groundSize * 3f;
    36.         // groundSizeHalf = groundSize * 0.5f;
    37.         // newGroundTrigger = groundSize + groundSizeHalf;
    38.  
    39.         groundOffset = groundSize * (1 + tileRadius*2);
    40.         groundSizeHalf = groundSize * 0.5f;
    41.         newGroundTrigger = groundSize * (0.5f+tileRadius);
    42.  
    43.         float gSizeX = groundSize.x;
    44.         float gSizeZ = groundSize.z;
    45.  
    46.         Debug.Log ( $"groundOffset :: { groundOffset }" );
    47.         Debug.Log ( $"groundSizeHalf :: { groundSizeHalf }" );
    48.         Debug.Log ( $"newGroundTrigger :: { newGroundTrigger }" );
    49.  
    50.         for ( int i = -tileRadius; i <= tileRadius; i++ ) {
    51.  
    52.             Debug.Log ( $"i :: { i }" );
    53.             Debug.Log ( $"gSizeX :: { gSizeX }" );
    54.             Debug.Log ( $"gSizeZ :: { gSizeZ }" );
    55.  
    56.             int tileCountX = ( i * ( int ) gSizeX ) / 2;
    57.             int tileCountZ = ( i * ( int ) gSizeZ ) / 2;
    58.  
    59.             Debug.Log ( $"tileCountX :: { tileCountX }" );
    60.             Debug.Log ( $"tileCountZ :: { tileCountZ }" );
    61.  
    62.             SpawnGround ( new Vector3 (
    63.                 ( tileCountX ),
    64.                 0.0f,
    65.                 ( tileCountZ )
    66.             ) );
    67.  
    68.             tileCount = (
    69.                 ( ( tileCountX ) + ( tileCountZ ) ) +
    70.                 ( ( tileRadius ) + 1 )
    71.             );
    72.  
    73.         }
    74.  
    75.     }
    76.  
    77.     private void Update() {
    78.         FixOutsideRange();
    79.     }
    80.  
    81.     void FixOutsideRange() {
    82.         for (int i = 0; i < spawnedGround.Count; i++) {
    83.             Vector3 groundPos = spawnedGround[i].position;
    84.             Vector3 mag = target.position - groundPos;
    85.             if (mag.x < -newGroundTrigger.x)
    86.             {
    87.                 groundPos.x -= groundOffset.x;
    88.             }
    89.             else if (mag.x > newGroundTrigger.x)
    90.             {
    91.                 groundPos.x += groundOffset.x;
    92.             }
    93.  
    94.             if (mag.z < -newGroundTrigger.z)
    95.             {
    96.                 groundPos.z -= groundOffset.z;
    97.             }
    98.             else if (mag.z > newGroundTrigger.z)
    99.             {
    100.                 groundPos.z += groundOffset.z;
    101.             }
    102.  
    103.             spawnedGround[i].transform.position = groundPos;
    104.         }
    105.     }
    106.  
    107. }
     
  16. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    You keep posting this and yet we know math is always correct.

    The problem is you are either:

    - feeding it wrong inputs
    - changing something else about the output
    - or your basic equation is wrong.

    Every single one of the above can be instantly identified by appropriate use of
    Debug.Log()
    but it seems you have somehow made nearly a dozen posts in here without any indication that you are even making the SLIGHTEST attempt to debug your code.

    Refer to my post above, or else continue to spin. Nobody here can see your data, so it is up to you.
     
  17. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    What are you talking about? You can see my data just fine. I posted it above. P.S. I already have Debug Logs in the right places. So yes, I DID make an attempt to Debug my code.
     
  18. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    The equation doesn't look to be wrong.
     
  19. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Pretty much all of your suggestions are wrong ^^. First of all the latest C# versions do support local / nested methods. I don't really like them but it's possible to have methods defined inside methods now.

    Though your suggestions about the two for loops make no sense. The script tries to create a grid of tiles. So you need the two nested loops, one for the x coordinate and one for the z coordinate. Using a single loop would not create a grid but just a diagonal line of tiles. Not sure why you said the values of "i" and "j" never changes, they do
     
  20. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Bunny83 Ok, I will put the for loops back although I'm not fond of nested methods either.
     
  21. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    Ok, that´s nice to know.

    I said this, because in his code they have all the time the same value and if he wants to have squares, one loop is enough therefor or did i miss some coed, where he changes i and j to different values ? I think in this case it´s even better to have only one loop because he can´t change one value by accident.
     
  22. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    Well, you did not ^^ You changed quite a bit compared to your original code and I'm not sure why.

    Code (CSharp):
    1. int tileCountX = ( i * ( int ) gSizeX ) / 2;
    Why do you suddenly cast the ground size to an integer and why do you divide it by 2? Why is that variable called tileCountX? It's not a count, it's the X position where the tile should be spawned.

    I'm also not sure what this should represent:
    Code (CSharp):
    1. tileCount = (
    2.                     ( ( tileCountX ) + ( tileCountZ ) ) +
    3.                     ( ( tileRadius ) + 1 )
    4.                 );
    The value of "tileCount" has no meaning and isn't even used anywhere.

    I just grabbed your original script and made just the changes I mentioned:

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InfiniteGround : MonoBehaviour
    6. {
    7.  
    8.     [Tooltip("Pivot for the ground to follow")]
    9.     public Transform target;
    10.  
    11.     [SerializeField] Transform groundPrefab;
    12.  
    13.     [SerializeField, Tooltip("Ground size in world scale")]
    14.     Vector3 groundSize = new Vector3(1f, 0f, 1f);
    15.  
    16.     [Header("Tile Settings")]
    17.     public int tileRadius = 3;
    18.  
    19.     readonly List<Transform> spawnedGround = new List<Transform>();
    20.  
    21.     Vector3 groundOffset;
    22.     Vector3 newGroundTrigger;
    23.  
    24.     private void Awake()
    25.     {
    26.         groundOffset = groundSize * (1 + tileRadius * 2);
    27.         newGroundTrigger = groundSize * (0.5f + tileRadius);
    28.  
    29.         for (int i = -tileRadius; i <= tileRadius; i++)
    30.         {
    31.             for (int j = -tileRadius; j <= tileRadius; j++)
    32.             {
    33.                 SpawnGround(new Vector3(i * groundSize.x, 0, j * groundSize.z));
    34.             }
    35.         }
    36.  
    37.         void SpawnGround(Vector3 pos)
    38.         {
    39.             Transform obj = Instantiate(groundPrefab, transform);
    40.             obj.transform.position = pos;
    41.             spawnedGround.Add(obj);
    42.  
    43.             // for visualization purposes only
    44.             obj.GetComponent<Renderer>().material.color = Random.ColorHSV(0, 1);
    45.         }
    46.     }
    47.  
    48.     private void Update()
    49.     {
    50.         FixOutsideRange();
    51.     }
    52.  
    53.     void FixOutsideRange()
    54.     {
    55.         for (int i = 0; i < spawnedGround.Count; i++)
    56.         {
    57.             Vector3 groundPos = spawnedGround[i].position;
    58.             Vector3 mag = target.position - groundPos;
    59.             if (mag.x < -newGroundTrigger.x)
    60.             {
    61.                 groundPos.x -= groundOffset.x;
    62.             }
    63.             else if (mag.x > newGroundTrigger.x)
    64.             {
    65.                 groundPos.x += groundOffset.x;
    66.             }
    67.  
    68.             if (mag.z < -newGroundTrigger.z)
    69.             {
    70.                 groundPos.z -= groundOffset.z;
    71.             }
    72.             else if (mag.z > newGroundTrigger.z)
    73.             {
    74.                 groundPos.z += groundOffset.z;
    75.             }
    76.  
    77.             spawnedGround[i].transform.position = groundPos;
    78.         }
    79.     }
    80. }
    81.  
    Though in order to see the different tiles better I colored them temporarily with a random color. I simply used a default cube as tile, set the "groundSize" to (1,0,1) since that's the size of one of the cubes and put script on an empty gameobject in the scene. I created a "player" object which I assigned to the "target" and this is the result:

    InfinitePlane.gif

    This does exactly what it should do. This is an example with a tileRadius of 5. So it's an 11x11 grid. You always said something doesn't work on your side. What exactly does not work? Do you get any error? Doesn't it do what you had in mind? What is it?
     
    Kurt-Dekker likes this.
  23. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    3,528
    I don't quite follow what you're saying here. Look, there are two nested loops:

    Code (CSharp):
    1.  for ( int i = -tileRadius; i <= tileRadius; i++ )
    2. {
    3.     for ( int j = -tileRadius; j <= tileRadius; j++ )
    4.     {
    5.         // [ ... ]
    6.     }
    7. }
    The outer loop uses the variable i which is incremented each loop iteration. The inner loop uses the variable j which is also incremented each of its iterations. So if tileRadius is 1 we loop from -1 to 1 for both variables and we get those 9 pairs:
    Code (CSharp):
    1. //  i |  j
    2. // ---|-----
    3. // -1 | -1
    4. // -1 |  0
    5. // -1 |  1
    6. //  0 | -1
    7. //  0 |  0
    8. //  0 |  1
    9. //  1 | -1
    10. //  1 |  0
    11. //  1 | -1
    12.  
    How exactly do you want to create those grid coordinates with a single loop? Yes you could get fancy with modulo and integer division and calculate the x and y values from a single index, but why would you? If you have a two dimensional problem, using a nested loop it the most natural solution to it.
     
  24. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,756
    Now I just want to give your colored cubes some vertical offsets and make "Q-Bert 2022 The Hoppening."
     
  25. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Bunny83 That is what I had in mind, yes. but I am trying to get it to allow the player to move to close to the edge before it starts re creating the tiles and allowing the movement of tiles. That way it looks like in any direction, I am walking on an `infinite plane` in any direction, EXACTLY how Blitz3D's CreatePlane ( ) works.

    https://kippykip.com/b3ddocs/commands/3d_commands/CreatePlane.htm
     
  26. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    yes yes, you are totally right. I´m just dumb... For sure iterates the inner loop much more often till the outer loops again...
    @AerionXI just ignore my posts, they are totally bulls**t
     
    Bunny83 likes this.
  27. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    @Sphinks It's all good brother. I absolutely appreciate the help and you all in here all deserve a thank you. <3
     
    Sphinks likes this.
  28. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    This is a bit better but I can't get the movement of the infinite plane to move smoothly.

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InfiniteGround : MonoBehaviour
    6. {
    7.  
    8.     [Tooltip("Pivot for the ground to follow")]
    9.     public Transform target;
    10.  
    11.     [SerializeField] Transform groundPrefab;
    12.  
    13.     [SerializeField, Tooltip("Ground size in world scale")]
    14.     Vector3 groundSize = new Vector3(1f, 0f, 1f);
    15.  
    16.     [Header("Tile Settings")]
    17.     public int tileRadius = 3;
    18.     public int oldTileRadius = 0;
    19.  
    20.     readonly List<Transform> spawnedGround = new List<Transform>();
    21.  
    22.     Vector3 groundOffset;
    23.     Vector3 newGroundTrigger;
    24.  
    25.     public Vector3 targetPosition;
    26.     public float smoothFactor = 2.0f;
    27.  
    28.     void SpawnGround(Vector3 pos)
    29.     {
    30.         Transform obj = Instantiate(groundPrefab, transform);
    31.         obj.transform.position = pos;
    32.         spawnedGround.Add(obj);
    33.  
    34.         // for visualization purposes only
    35.         obj.GetComponent<Renderer>().material.color = Random.ColorHSV(0, 1);
    36.     }
    37.  
    38.     private void CreateGroundSpawn ( ) {
    39.  
    40.         groundOffset = groundSize * (1 + tileRadius * 2);
    41.         newGroundTrigger = groundSize * (0.5f + ( 3*tileRadius ));
    42.  
    43.         for (int i = -tileRadius; i <= tileRadius; i++ ) {
    44.             for (int j = -tileRadius; j <= tileRadius; j++) {
    45.                 SpawnGround ( new Vector3 (
    46.                     i * groundSize.x,
    47.                     0.0f,
    48.                     j * groundSize.z
    49.                 ) );
    50.             }
    51.         }
    52.  
    53.     }
    54.  
    55.     private void Awake()
    56.     {
    57.         oldTileRadius = tileRadius;
    58.         CreateGroundSpawn();
    59.     }
    60.  
    61.     private void Update()
    62.     {
    63.         transform.position = Vector3.Lerp (
    64.             transform.position,
    65.             targetPosition,
    66.             Time.deltaTime * smoothFactor
    67.         );
    68.         FixOutsideRange();
    69.     }
    70.  
    71.     void FixOutsideRange ( ) {
    72.  
    73.         for ( int i = 0; i < spawnedGround.Count; i++ ) {
    74.  
    75.             Vector3 groundPos = spawnedGround [ i ].position;
    76.             Vector3 mag = target.position - groundPos;
    77.  
    78.             Debug.Log ( $"mag.x : { mag.x }" );
    79.             Debug.Log ( $"mag.z : { mag.z }" );
    80.  
    81.             if ( mag.x < -newGroundTrigger.x ) { groundPos.x -= groundOffset.x; }
    82.             if ( mag.x >  newGroundTrigger.x ) { groundPos.x += groundOffset.x; }
    83.             if ( mag.z < -newGroundTrigger.z ) { groundPos.z -= groundOffset.z; }
    84.             if ( mag.z >  newGroundTrigger.z ) { groundPos.z += groundOffset.z; }
    85.  
    86.             spawnedGround [ i ].transform.position = groundPos;
    87.  
    88.         }
    89.     }
    90. }
     
  29. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    So I am trying to detach the created children objects from the parent and immediately destroy the parent so there's not an extra tile showing up at runtime, but for some reason the children are no longer following the player target...

    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class InfiniteGround: MonoBehaviour {
    6.  
    7.     [Tooltip("Pivotfor the ground tofollow")]
    8.     public Transform target;
    9.  
    10.     [SerializeField] Transform groundPrefab;
    11.  
    12.     [SerializeField, Tooltip("Ground size in world scale")]
    13.     Vector3 tileSpacing = new Vector3(0.0f, 0.0f, 0.0f);
    14.  
    15.     [Header("Tile Settings")]
    16.     public int tileRadius = 3;
    17.     public int oldTileRadius = 0;
    18.  
    19.     public readonly List <Transform> spawnedGround = new List<Transform>();
    20.  
    21.     Vector3 groundOffset;
    22.     Vector3 newGroundTrigger;
    23.  
    24.     public Vector3 targetPosition;
    25.  
    26.     public void SpawnGround(Vector3 pos) {
    27.  
    28.         Transform obj = Instantiate(groundPrefab, transform);
    29.         obj.transform.position = pos;
    30.         spawnedGround.Add(obj);
    31.  
    32.         // for visualization purposes only
    33.  
    34.         obj.GetComponent <Renderer>().material.color = Random.ColorHSV(
    35.             0, 1
    36.         );
    37.  
    38.     }
    39.  
    40.     public void CreateGroundSpawn() {
    41.  
    42.         groundOffset = tileSpacing * (1.0f + tileRadius * 2.0f);
    43.         newGroundTrigger = tileSpacing * (0.5f + tileRadius);
    44.  
    45.        for (int i = -tileRadius; i <= tileRadius; i++) {
    46.            for (int j = -tileRadius; j <= tileRadius; j++) {
    47.                 SpawnGround(new Vector3(
    48.                     i * tileSpacing.x,
    49.                     0.0f,
    50.                     j * tileSpacing.z
    51.                 ));
    52.             }
    53.         }
    54.  
    55.     }
    56.  
    57.     public void RemoveParent(GameObject[] objectList) {
    58.  
    59.         if (objectList.Length > 0) {
    60.             Object.Destroy(
    61.                 objectList[0].transform.parent.gameObject
    62.             );
    63.         }
    64.  
    65.     }
    66.  
    67.     public void RemoveParentObj() {
    68.  
    69.         transform.DetachChildren();
    70.         Object.Destroy(this.gameObject);
    71.  
    72.     }
    73.  
    74.     public voidfixOutsideRange() {
    75.  
    76.        for (int i = 0; i < spawnedGround.Count; i++) {
    77.             Vector3 groundPos = spawnedGround[i].position;
    78.             Vector3 mag = target.position - groundPos;
    79.             if (mag.x < -newGroundTrigger.x){groundPos.x -= groundOffset.x;}
    80.             if (mag.x >  newGroundTrigger.x){groundPos.x += groundOffset.x;}
    81.             if (mag.z < -newGroundTrigger.z){groundPos.z -= groundOffset.z;}
    82.             if (mag.z >  newGroundTrigger.z){groundPos.z += groundOffset.z;}
    83.             spawnedGround[i].transform.position = groundPos;
    84.         }
    85.  
    86.     }
    87.  
    88.     private void Awake() {
    89.  
    90.         oldTileRadius = tileRadius;
    91.         CreateGroundSpawn();
    92.         RemoveParentObj();
    93.  
    94.     }
    95.  
    96.     private void Update() {
    97.  
    98.        fixOutsideRange();
    99.  
    100.     }
    101.  
    102. }
     
    Last edited: Jul 21, 2022
  30. AerionXI

    AerionXI

    Joined:
    Jul 20, 2020
    Posts:
    482
    With the code above, how do I remove the parent plane, and keep the child planes in order to create a big plane out of those pieces big enough to "hide" the "big plane" all the way up to the horizon no matter which direction the player is moving?
     
    Last edited: Jul 21, 2022