A* Pathfinding (E02: node grid)

Поділитися
Вставка
  • Опубліковано 25 жов 2024

КОМЕНТАРІ • 554

  • @synvian8212
    @synvian8212 8 років тому +308

    I could listen to this guys voice all day, strangely relaxing . . .

    • @eleos5
      @eleos5 5 років тому +2

      Not me, for sure!

    • @louissherwood5221
      @louissherwood5221 5 років тому +1

      he pays hugh grant to do his voice overs xD

    • @peterbengtson7406
      @peterbengtson7406 4 роки тому

      @@louissherwood5221 He has a far posher voice than Hugh Grant, though: he pronounces "off" as "orf" and "gone" as "gorne", for instance, and I suspect he would pronounce "hour" as "ahr" and "flower power" as "flahr pahr" (so-called triphthong smoothing). A very pleasant voice speaking Conservative RP. Not that usual nowadays.

    • @joshual3486
      @joshual3486 4 роки тому

      @@peterbengtson7406 To me it's really not RP, it's more from mainland Europe (pretty sure he's Danish)

    • @gobblestheturkey1413
      @gobblestheturkey1413 3 роки тому +1

      A* asmr

  • @Garbaz
    @Garbaz 9 років тому +288

    17:00
    (a + b/2) / b = (a/b) + (b/(2*b)) = a/b + 1/2 [ = a/b + 0.5 ]
    And calculating "a/b + 0.5" is easier for the PC than "(a + b/2) / b".

    • @SebastianLague
      @SebastianLague  9 років тому +140

      Good optimization, thanks for pointing that out.

    • @MrMineHeads.
      @MrMineHeads. 7 років тому +1

      why the fuck would you do that? this is a float.

    • @scholes8734615
      @scholes8734615 6 років тому +2

      Not the same fact

    • @brainlow
      @brainlow 6 років тому +40

      I'd like to add one more thing about this for anyone else who scours the comments for tweaks - three years late, i know, but these tutorials are phenomenal and i've been going through them. I've learned more about A* than I ever thought possible.
      Mathf.RoundToInt((gridSizeX-1) * percentX) is almost right, but not quite.
      By subtracting 1 before multiplying by the percent, you won't go over the number of squares that exist, but you'll be getting a percent of an incorrect number. If you have a grid with 100 or more squares, you may eventually encounter situations where you are off by a square.
      Also, you need to you FloorToInt, because assuming 0 is the left-edge of the grid, it's also the left edge of the first square. 0.5, then, would be the middle of the first square, and so would 0.9, 0.99, and so on. If you ever round up, you can be inaccurate by as much as half a square.
      So instead what i've done is Mathf.FloorToInt(Mathf.Min(gridSizeX * percentX), gridSizeX - 1)

    • @QuestionMark43
      @QuestionMark43 6 років тому +19

      Did you mean:
      Mathf.FloorToInt(Mathf.Min(gridSizeX * percentX, gridSizeX - 1))

  • @bejoscha
    @bejoscha 5 років тому +8

    Lovely pace for learning stuff - including mistakes, which are a natural part of the coding experience. I’m glad you are not editing them out.

  • @FranciscoAmorim
    @FranciscoAmorim 7 років тому +66

    19:30
    if you round down a percentage multiplied by a grid-1 you can end with a target one node away from your actual current node.
    Take x = 14.4 for example:
    (14.4 + 30 / 2) / 30 = 0.98
    x = round(29 * 0.98) = round(28.42) = 28, so you end up at node 28.
    But if your x = 14.4 you are between x=14 and x=15, so you actually are at the far right node (29)
    You should not round and subtract one, you should floor without subtracting:
    x = floor(30*0.98) = floor(29.4) = 29
    edit: you also need to clamp before floor:
    int x = Mathf.FloorToInt(Mathf.Clamp((gridSizeX) * percentX, 0, gridSizeX - 1));
    o/

    • @zoetechandme
      @zoetechandme 3 роки тому +5

      You should also remove these lines>
      percentX = Mathf.Clamp01(percentX);
      percentY = Mathf.Clamp01(percentY);
      Becouse otherwise the bottom Y node is always one above from the current node.
      This is my whole function:
      public Node NodeFromWorldPoint(Vector3 worldPosition)
      {
      float percentX = (worldPosition.x + gridWorldSize.x / 2) / gridWorldSize.x;
      float percentY = (worldPosition.y + gridWorldSize.y / 2) / gridWorldSize.y;
      int x = Mathf.FloorToInt(Mathf.Clamp((gridSizeX) * percentX, 0, gridSizeX - 1));
      int y = Mathf.RoundToInt((gridSizeY) * percentY) +1;
      return grid[x, y];
      }

    • @DancingManson
      @DancingManson 3 роки тому +4

      @@zoetechandme Can you please elaborate this little bit more. Why do you need to add +1 to int y?

    • @umarfaroukabdulmutallab4451
      @umarfaroukabdulmutallab4451 2 роки тому

      o/

    • @dumbcow-j97
      @dumbcow-j97 Рік тому +1

      This!

    • @camo_man
      @camo_man Рік тому +1

      THANK U

  • @mr_donutz
    @mr_donutz 4 роки тому +37

    just finished watching this tutorial, now gotta do it 99 more times for me to get it

  • @damien5266
    @damien5266 8 років тому +46

    You're an amazing programmer. Thanks for the videos.

  • @burhanuddin9047
    @burhanuddin9047 4 роки тому

    Thanks a lot. You are the best 😊 teacher. Explained everything in details and your voice have magic, can hear all the day without feel bored. thanks a lot again. 😇😊

  • @MACHINEBUILDER
    @MACHINEBUILDER 3 роки тому +3

    I saw this video in my recommended, and I've already watched it twice, but I clicked on it again just to listen to your voice lol

  • @web_tutorials_for_beginners
    @web_tutorials_for_beginners 9 років тому +2

    Sebastian Lague More, and more videos please, you are a great tutor!!!
    More videos about anything! In every video I learn something new.

  • @bwegrzyn
    @bwegrzyn 3 роки тому +1

    I'm trying to implement this in Java and it works fine. I only had problem with percentX and percentY, wich were returning 5X bigger value than they should, but I fixed it. Thanks for great tutorial!

  • @pixeldustinteractive
    @pixeldustinteractive 5 років тому +3

    I came here from this guy named Daniel... he kind of just reuploaded your tutorial with his following your tutorial... he did NOT fix the "that's y it's meant to be z" for the percent value. I've been stuck for a week. Lol.

  • @PatrickWilliamsphd
    @PatrickWilliamsphd 6 років тому +2

    I have watched this and Part 1 and am super excited to try this stuff out. I'll be able to quickly create some fun games for my kids with this AI. Keep up the good work friend.

  • @jessejones6756
    @jessejones6756 5 років тому +16

    No idea what you're talking about but I'm still interested.

  • @moduntilitbreaks
    @moduntilitbreaks 4 роки тому +3

    This guy is the reason i requested .1x playing speed from UA-cam.

  • @MrNintendeion
    @MrNintendeion 3 роки тому

    Omg I know I'm a bit late so you may well not see this comment but this tutorial dude wow. I'm trying to implement A* into an Xcom style strategy game and after hours of trying to follow another UA-camr (I won't name names but god it was infuriating), this tutorial is just what I needed :) I've followed this all the way through and feel so much better about A* now, you're a great programmer mate thanks so much.

  • @lamdasoftworks1165
    @lamdasoftworks1165 6 років тому +11

    I'd love to see an update on this, using unity's new Tilemap Grid system.

  • @Ensiferum888
    @Ensiferum888 9 років тому

    Amazing tutorial, I'm using Aron Granberg's pathfinding since I couldn't implement it myself. Your explainations are extremely easy to understand. Great work!

  • @10chaos1
    @10chaos1 9 років тому +1

    thank you very much for this Sebastian i now understand what i need to do to make a placement grid for my citybuilder game project

  • @Undead2k
    @Undead2k 7 років тому +2

    Thanks for making this tutorial and for also adding the source files for the 2D project somewhere in the comments (as the video is for 3D). I am still learning c# and unity and now trying to learn A* pathfinding. I am finding this really useful and educational.

    • @dead2gamer
      @dead2gamer Рік тому

      Hey can you link me up with the code for 2D. I'm working with this and trying to figure out how to check for collisions on 2D

  • @tshichan
    @tshichan 4 роки тому +2

    I wish the youtube has another LIKE button !! thank you Sebastian for this piece of magic code :)

  • @tumankito7776
    @tumankito7776 3 роки тому

    I am a big fan of you! Great way to explain the logic of your code, thanx for the amazing tutorial.

  • @naipeadicto
    @naipeadicto 9 років тому

    Thanks!!!!!!! Incredible explanation! I was struggling setting the grid for my project, but I followed along and it turned out really simple and easy. now to part 3...

  • @JakeDownsWuzHere
    @JakeDownsWuzHere 9 років тому +1

    worked perfectly for me. really enjoying this series. :D thanks for sharing it

  • @MrSquishedsquashed
    @MrSquishedsquashed 9 років тому

    Really great tutorial!
    Quick, to the point and clear.
    Thanks!

  • @klevialushi571
    @klevialushi571 3 роки тому +1

    its an old video but gotta love the fact that you got stockfish there

  • @MangaPianet
    @MangaPianet 3 роки тому

    Talk about A(*) programmers! Great video and great code, I love all your videos!

  • @davidpike5959
    @davidpike5959 7 років тому +86

    wow, copying this guy makes me feel clever :O

  • @gadgetboyplaysmc
    @gadgetboyplaysmc 4 роки тому +3

    There's another way to do 17:17 on the NodeFromWorldPoint function.
    Which is to just Vector3.InverseLerp(-gridPosition*.5,gridPosition*.5,worldPosition.x)
    It's automatically clamped to 0 and 1 so no need to do Mathf.Clamp or whatever:
    Mathf.InverseLerp(-gridWorldSize.x*.5f,gridWorldSize.x*.5f, worldPosition.x);
    Mathf.InverseLerp(-gridWorldSize.z*.5f,gridWorldSize.y*.5f, worldPosition.z);
    Remember, gridWorldSize and worldPosition are 1:1 proportion.
    Little definition of Inverse Lerp:
    InverseLerp(min,max,t)
    What InverseLerp does is that it returns a float value that converts value t into a value between 0,1.
    Kinda like Lerp except t is a value you pass in that is between 0 and 1 and returns a float value that is between min and max.

  • @AA-vf4fv
    @AA-vf4fv 7 років тому

    Thanks for the great Tutorial. It helped me very much.
    Also good explanation and easy to follow.

  • @sits
    @sits 8 років тому +49

    We should also take node radius and our A* object position into account when getting node from world point or the results will be pretty inaccurate.
    Here's what I ended up with:
    float percentX = (worldPosition.x - transform.position.x) / gridWorldSize.x + 0.5f - (nodeRadius / gridWorldSize.x);
    float percentY = (worldPosition.z - transform.position.z) / gridWorldSize.y + 0.5f - (nodeRadius / gridWorldSize.y);

    • @ukaszw7924
      @ukaszw7924 8 років тому +1

      +Alexander Sorokin Thanks!

    • @ashleytwo
      @ashleytwo 8 років тому

      +Alexander Sorokin I think I'm having this problem. When I was following along and testing and put it at 0,0,0 it was all fine. Now that I actually want to implement it in my game as soon as it pathfinds it's trying to go somewhere weird.
      I think its the NodeFromWorldPoint method that's doing it but can't figure out how to fix it.
      Your reply seems to suggest there should be some code. Mind posting it again as I can't see anything and I'm hoping you have the answer!
      Thanks :)

    • @sits
      @sits 8 років тому

      Ashley Jones dunno why you don't see it, I am still seeing it in my reply.
      Anyway, here you go:
      gist.github.com/alsorokin/2550976f89b5649314a4

    • @FeuerfallFan
      @FeuerfallFan 8 років тому +1

      Helped me, thank you very much! :)

    • @TheTwyker
      @TheTwyker 8 років тому +1

      this is the most important comment on youtube I've ever read! UP YOU GO, SIR!
      WITHOUT THIS, YOU CAN'T USE IT IN YOUR GAME, meaning: you can't move the grid.

  • @zhaoxuefei3829
    @zhaoxuefei3829 2 роки тому

    omg, what a amazing video for a star, thank you very much

  • @dennischan2263
    @dennischan2263 6 років тому

    excellent tutorial, thank you very much dude, you save my FYP and my life

  • @MrDavidCollins
    @MrDavidCollins 3 роки тому

    Just implemented this for my infinite world map! I love GMS2's new class/object programming

    • @kevinmolinari8953
      @kevinmolinari8953 Рік тому

      what?... how? seriously, im lost how do u do it for an infinite map

  • @catanator123654
    @catanator123654 8 років тому +48

    So I got all the code right but it just wouldn't work and after a half hour of checking over the code turns out I misspelled "position" 😑

    • @Villfuk02
      @Villfuk02 7 років тому +18

      that's 40% of being programmer - fixing simple mistakes ¯\_(ツ)_/¯

    • @elektro36
      @elektro36 5 років тому +7

      A CLASSIC

    • @chappie3642
      @chappie3642 4 роки тому +7

      How did you not see that on the error log lmao

    • @alexanderrupp1209
      @alexanderrupp1209 4 роки тому +1

      That’s a mood

    • @daksheshgupta7045
      @daksheshgupta7045 4 роки тому

      get a linter

  • @RoutineJustice
    @RoutineJustice 9 років тому +4

    I was JUST wondering how I was going to do the AI for the top down shooter. I've had some exposure to A* before but never in the context of actually doing it.
    Sebastian: I love you.

    • @windowsxseven
      @windowsxseven 3 роки тому +1

      lmao gay

    • @Phagocytosis
      @Phagocytosis 3 роки тому

      ​@@windowsxseven I love you

    • @windowsxseven
      @windowsxseven 3 роки тому +1

      @@Phagocytosis 💝💝💘💋💋💌💓💕💞❤️‍🔥💟💚💙💜😘😘😙🥰💕💗💖

  • @BlockerofDoom
    @BlockerofDoom 7 років тому +2

    Awesome video, one problem that I encountered while testing this code is that when you pass the player position parameter to NodeFromWorldPoint you have to convert coordinates to local relative to grid object with Transform.InverseTransformPoint otherwise if your grid is not centered on 0,0,0 then it will not work :)

    • @Tevan1n
      @Tevan1n 4 роки тому +1

      Hey there, I know it's 3 years late, but how would you go about doing this? Could you clarify? Thanks.

    • @alexrico5764
      @alexrico5764 4 дні тому

      To anyone ready to spend an hour or so looking through the comments for the solution. Try this method from @itsybitsypixel. His comment is buried, so hopefully this finds and helps you before you start digging:
      ANYONE WHO IS HAVING INACCURATE POSITIONS FROM THE NodeFromWorldPoint READ THIS
      I found that the "NodeFromWorldPoint" method returned an inaccurate position while on the sides of the grid, so I tried remaking it too show a more accurate position. It's basically the same but it skips the percent and uses the nodeRadius and nodeDiameter variables and that somehow works.
      int x = Mathf.RoundToInt((worldPosition.x + gridWorldSize.x / 2 - nodeRadius)/nodeDiameter);
      int y = Mathf.RoundToInt((worldPosition.y + gridWorldSize.y / 2 - nodeRadius)/nodeDiameter);
      x = Mathf.Clamp(x, 0, gridSizeX - 1);
      y = Mathf.Clamp(y, 0, gridSizeY - 1);
      return grid[x, y];
      ^This code is inside the method^
      I tested this and it worked and gave me a more accurate position, but I have not tested this with the rest of the tutorial so be warned.
      Also I am using this for a 2D game so I used the Y position instead of the Z position in "worldPosition". If you are making a 3D game use Z instead.

  • @videomasters2468
    @videomasters2468 9 років тому +7

    if possible i would really like to see a tutorial/tutorial series on procedural level generation :)

    • @SebastianLague
      @SebastianLague  9 років тому +10

      Yeah that'd be fun :) Do you have something particular in mind? I could easily do some sort of cool cave generation using using cellular automata..

    • @videomasters2468
      @videomasters2468 9 років тому +1

      Sebastian Lague
      Yeah, either your suggested cave generation or some kind of race track, which would be of greater interest to you ?

    • @JoshD22
      @JoshD22 9 років тому

      Another great tutorial Sebastian! Procedural generation sounds like a great idea! I would also like to suggest procedural voxel terrain in Unity, maybe block type worlds like Minecraft or smooth voxel terrains by using something like marching cubes or even better Dual Contouring, which allows you to have sharp features for buiulding but the smoothness that you want for the ground.

    • @trevor7066
      @trevor7066 9 років тому +1

      Sebastian Lague
      I think something along the lines of Terraria style map generation would be extremely useful.

    • @BrainRobo
      @BrainRobo 9 років тому

      Sebastian Lague
      Also, if possible random planet generation, using spheres as the planet for space exploration, would be very intriguing.

  • @riteshrobotics9713
    @riteshrobotics9713 3 роки тому

    A* Life Saver
    Was a really good video!

  • @jasperh6618
    @jasperh6618 9 років тому +1

    I absolutely love this ^^ such a clear explanation :)

  • @3personal5me8
    @3personal5me8 3 роки тому

    Me, about to go to bed because I work tomorrow: "Well, guess I'm watching this whole series first".

  • @levonravel3698
    @levonravel3698 3 роки тому +11

    Be aware if you are following this tutorial there is a pitfall, the map is suppose to be at 0,0,0 it cant move if you do the path to the character is off. To fix this do this instead of what was provided.
    private Node GetNodeFromWorldPoint(Vector3 worldPosition)
    {
    var percentX = (worldPosition.x - transform.position.x + GridSize.x / 2) / GridSize.x;
    var percentY = (worldPosition.y - transform.position.y + GridSize.y / 2) / GridSize.y;
    Thank me later but this portion really threw me off and solved it in about 5 minutes.

    • @impact3373
      @impact3373 2 роки тому +1

      you literally saved my life thanks

    • @juicedup14
      @juicedup14 2 роки тому +1

      This needs to get pinned

    • @diggerpy
      @diggerpy Рік тому +1

      thanks

    • @dumitrascumihai-cosmin1615
      @dumitrascumihai-cosmin1615 Рік тому +1

      It is like this actually:
      float percentX = (worldPosition.x - transform.position.x + gridWorldSize.x/2) / gridWorldSize.x;
      float percentY = (worldPosition.z - transform.position.z + gridWorldSize.y/2) / gridWorldSize.y;
      But, thank you for saving my day!

    • @sanmaro91
      @sanmaro91 Рік тому +1

      thank you you are great dad

  • @yuuryu2394
    @yuuryu2394 7 років тому +1

    exactly what i was looking for, thanks a lot! :D

  • @FeuerfallFan
    @FeuerfallFan 8 років тому +2

    if you have an inaccurate position from the NodeToWorldPoint, make sure your GameObjects position with the Grid Script is set to Vector3(0,0,0)

  • @alexandergilbert7572
    @alexandergilbert7572 9 років тому

    It might be a fun little project to get A* path finding to work on your spherical world.

    • @arandomlizard3411
      @arandomlizard3411 5 років тому

      "fun" might not be the best word to describe it.

  • @worempie
    @worempie 8 років тому

    A little late and don't know if this has been posted already or not, but currently you don't use the unwalkableMask. If you have for example other gameobjects with a collider, they will also be added to the non-walkable grid. To fix this you have to add the layer mask to line 28:
    bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask));
    Also to update the grid just run the CreatGrid(), for example by pressing the N button:
    if (Input.GetKeyDown(KeyCode.N))
    {
    CreateGrid();
    }
    or from a different script (don't forget to make CreateGrid() public:
    if (Input.GetKeyDown(KeyCode.N))
    {
    GameObject.Find("A*").GetComponent().CreateGrid();
    }

  • @mohamedsalbi2759
    @mohamedsalbi2759 3 роки тому

    Best channel ever

  • @MrCheliab
    @MrCheliab 9 років тому +5

    Hello Sebastian.
    I have problem with your code in function NodeFromWorldPoint(). They get incorrect coodinates of node.
    This is my solution, if sobody have same problem:
    public Node NodeFromWorldPoint(Vector3 worldPosition)
    {
    // Move coordinates in right position
    float linearPosX = worldPosition.x - worldBottomLeft.x;
    float linearPosY = worldPosition.y - worldBottomLeft.y;
    // Get float value of positions in new coordinates
    float floatPosX = (linearPosX / nodeDiameter) - nodeRadius;
    float floatPosY = (linearPosY / nodeDiameter) - nodeRadius;
    int x = Mathf.RoundToInt(floatPosX);
    int y = Mathf.RoundToInt(floatPosY);
    x = Mathf.Clamp(x, 0, gridSizeX - 1);
    y = Mathf.Clamp(y, 0, gridSizeY - 1);
    return grid[x, y];
    }

  • @aidansoles5113
    @aidansoles5113 9 років тому

    You are a boss at debugging....

  • @romainchow5706
    @romainchow5706 6 років тому +2

    what does the Node[,] variable do in Grid? It's not working for me, do I have to attach the node script?

  • @DriitzzCabal
    @DriitzzCabal 7 років тому

    I would like to see how you would go about having an Enemy AI that jumps up and down platform to chase the player , in a 2D SideScroller platformer, Which route would you pick ? A* pathfinder , Raycast , Grid base ,MeshBase. Possibly also giving your opinion on difference between them with Pros and Cons.

  • @sallycleverdoggo700
    @sallycleverdoggo700 3 роки тому

    This is so good! Thank you!

  • @batomow
    @batomow 7 років тому +1

    I know this might be a little bit off topic, but have you considered doing a GOAP AI tutorial? Since this sort of pathfinding is popularly implemented with GOAPs, i figured it could be an interesting follow up.
    Also, keep up the good work :)

  • @RetroEcoChicken
    @RetroEcoChicken 4 роки тому

    you can use this with his cavesystem if you diable the node script then enable it after runtime when the mesh and collision has been generated.

  • @jdelaay025
    @jdelaay025 8 років тому +1

    fantastic tutorial Sebastian!! I have one issue. The playerNode will not update or show as a different color. I even continued on I even continued on to the next tutorial for pathfinding to see if the old code would correct itself and it did not. I changed the zed and y coordinates and everything but it would work on either the x or y plane. So that means no path finding. It does work for the layer mask but none of the update type of functionality. Just the stuff that's on the startup section
    what do you suggest

  • @skelhain
    @skelhain 6 років тому +1

    Wow, nice tutorial as always!
    One question though.
    What would the math look like inside the NodeFromWorldPoint function if the grid origin was in the corner at 0, 0 and not at the center?
    These are the variables I use:
    public int gridRows = 5;
    public int gridColumns = 5;
    public float nodeScale = 1;
    In CreateGrid() this is what I do:
    Vector3 nodePos = transform.position + new Vector3(r, 0, c) * nodeScale;
    bool walkable = Physics.CheckBox(nodePos, Vector3.one * nodeScale, Quaternion.identity, obstacleLayerMask) == false;
    grid[r, c] = new Node(nodePos, walkable);
    As you see, I left out the extra math and simply build the grid from "transform.position".
    The problem is, I can't figure out how I get a node from a world position.
    This is the closest "formula" I could figure out thanks to the people in the comments.
    int x = Mathf.FloorToInt((worldPosition.x - transform.position.x) + (gridRows * 0.5f) / nodeScale);
    x = Mathf.Clamp(x, 0, (gridRows - 1));
    int z = Mathf.FloorToInt((worldPosition.z - transform.position.z) + (gridColumns * 0.5f) / nodeScale);
    z = Mathf.Clamp(z, 0, (gridColumns - 1));
    return grid[x, z];
    But the bigger the offset from World 0,0,0 the bigger the offset between worldPosition and nodePosition in the grid. Any help?

    • @ArtrexSt
      @ArtrexSt 4 роки тому

      in NodeFromWorldPoint function Add: worldPosition.x - transform.position
      Like:
      float percentX = ((worldPosition.x - transform.position.x) / gridWorldSize.x) + .5f;

      OR
      float percentX = ((worldPosition.x - transform.position.x) + (gridWorldSize.x / 2)) / gridWorldSize.x;

  • @badrballish9328
    @badrballish9328 3 роки тому

    Great tutorial thank you very much.

  • @Phagocytosis
    @Phagocytosis 3 роки тому +1

    I love these videos, they are great!
    Just one small thing that's bugging me slightly, at 16:39 and in earlier videos, you're calling these things percents but that would be something between 0 and 100 rather than between 0 and 1, right? Would be better (in terms of intuitive variable names etc.) to call them fractions, as that is what they are.

    • @marcindathefierce
      @marcindathefierce 2 роки тому +1

      Saying "42" versus "42%" would be quite different in meaning. Mathematically rather than colloquially, a percent is a number between 0 and 1, as Sebastian has presented here. The reason for this is that "percent" means literally "divided by 100." So percents are indeed fractions: they are always fractions out of 100 🙂

    • @Phagocytosis
      @Phagocytosis 2 роки тому +2

      @@marcindathefierce Exactly, I know that. But he said "a percentage of point five" (for the middle of the screen), when it would be either a fraction of point five, or a percentage of 50, right? That's what I meant.

  • @MoloSolo
    @MoloSolo 8 років тому

    Congratulations, I'm really enjoying your tutorials!
    Just one question. Don't you think it could be better to define variables "worldPoint" and "walkable" (lines 27 and 28) outside of the "for" instructions and assign the new value inside?
    I think it's faster to define these variables just one time instead of creating and destructing them in each loop.
    What do you think?

  • @michaelveloso
    @michaelveloso 9 років тому +1

    good clear instructions. thanks

  • @ThePistolWhippets
    @ThePistolWhippets 8 років тому

    Great tutorial - many thanks

  • @pablokalemba2924
    @pablokalemba2924 5 років тому

    Thanks !! you saved my proyect

  • @trinketos
    @trinketos 9 років тому +3

    OverflowException: Number overflow.
    Grid.CreateGrid () (at Assets/Pathfinding/Pathfinding_test/Grid.cs:22)
    Grid.Start () (at Assets/Pathfinding/Pathfinding_test/Grid.cs:18)
    I use Unity 5

    • @shezfroze7137
      @shezfroze7137 9 років тому

      trinketos I've got same error (grid = new Node[gridSizeX, gridSizeY];) of Number overflow. have you got the solution? I am also using unity 5.0.0.

    • @trinketos
      @trinketos 9 років тому

      no, that's bad for me xD, maybe I have to ask to some "experts" in unity xD

    • @shezfroze7137
      @shezfroze7137 9 років тому

      trinketos Ooo :|

    • @trinketos
      @trinketos 9 років тому

      :D

    • @Mrpngu
      @Mrpngu 9 років тому

      +trinketos You managed to get this part working?

  • @Robsfund
    @Robsfund 8 років тому +1

    Hey, great video! Quick question, if I want a grid node for a 3d terrain, should I just raycast down and create each node at the hit point, is it that simple?

  • @mahmoueco1200
    @mahmoueco1200 4 роки тому +2

    wow,just wow dude u r amazing where r u from !!! from land of genuis

  • @Bluzora.
    @Bluzora. 9 років тому

    Useful! Love it! Keep it going man! :D

  • @Krebzonide
    @Krebzonide 6 років тому +2

    How would you change this to make it work with 2d sprites instead of cubes? So far my best idea is to hide cubes behind the sprites which has worked but seems like it might cause lag with lots of obstacles.
    Edit: Looking over it it seems that it is the boxes collision that causes the detection so I just need some way to add collision to sprites.

  • @AnujRam-f4e
    @AnujRam-f4e Місяць тому

    is there any way in which we could avoid the diagonal grid tiles and figure out the path to the target only by moving horizontal or vertical directions if you have any suggestion please let me
    know

  • @S3fR0
    @S3fR0 8 років тому +19

    You need to explain more in detail what exactly the variables do. I feel like im just copying, without learning anything,. Thanks for the videos though!

    • @Chubzdoomer
      @Chubzdoomer 7 років тому +3

      Agreed. He doesn't explain each step thoroughly enough.

    • @HaroWorld1
      @HaroWorld1 7 років тому +1

      I understood fine... :/

    • @nimrat9999
      @nimrat9999 6 років тому +10

      Probably it's a good idea to go through a basic programming training first.

    • @viniciuslambardozzi4358
      @viniciuslambardozzi4358 6 років тому +2

      His tutorials are not about programming, so you should learn a bit before and it will become more clear.

    • @maximiliantschuchnig154
      @maximiliantschuchnig154 6 років тому +6

      This tutorial is beautifully done, the pace might be high for starters but as an experienced programmer i really appreciate the speed. Also, programming wise there is nothing special or difficult in the used variables/functions.

  • @devlog98
    @devlog98 6 років тому

    Hello there! I know this video is quite old, but I'd like to ask something... for some unknown reason, the nodes that are at the corners of my objects don't turn red, unless I change the value of the node size... it's weird because I can clearly see the object tresspassing the node's limits... well, thanks in advance, and keep up with the great work!

  • @azrailnone
    @azrailnone 3 роки тому +1

    Any suggestions for me to find the best way to learn C# like that??? have been struggling for a while now, quite a complex lang.

  • @chrisgengr
    @chrisgengr 9 років тому +1

    Hey Sebastian,
    I was wondering what the equivalent of creating a plane and, using gizmos to visually display the walkable and unwalkable regions of the world would be for a 2d project?
    Furthermore, What is the equivalent of the Physics.CheckSphere method in a 2d environment? At the moment I am currently using colliders, and I was hoping that there is a better solution in existence.
    Thanks!

    • @PvPNetwork
      @PvPNetwork 5 років тому +3

      Phyiscs2D.OverlapCircle works. 3 years late answer, but maybe someone else in the future will find it useful.

    • @gustavoguaresi8698
      @gustavoguaresi8698 3 роки тому +1

      @@PvPNetwork yeah, thanks. 2 years late, but still... haha

  • @alexter-sarkisov8321
    @alexter-sarkisov8321 7 років тому +2

    I changed the code a bit to account for a fact that a large object (e.g. player ship) can occupy several nodes. To create gizmos with the same color for all such nodes, I added a boolean to Node object (playerhere) and a condition in the CreateGrid() method ("player_shield_weak" is simply a collider object of the player ship):
    if (walkable == false) {
    Collider[] col = Physics.OverlapSphere (worldPoint, nodeRadius);
    if (col [0].gameObject.tag == "player_shield_weak") {
    grid [x, y] = new Node (walkable, worldPoint, true);
    } else {
    grid [x, y] = new Node (walkable, worldPoint, false);
    }
    } else {
    grid [x, y] = new Node(walkable, worldPoint, false);
    }
    This creates a Node object with playerhere =true, and then, in DrawGizmos() method I just changed the condition to check this boolean:
    if (node.playerhere == true)
    {
    Gizmos.color = Color.cyan;
    }
    and it worked!

  • @leddy_
    @leddy_ 9 років тому

    I've been using "Sublime Text 2" in Unity for a little while now, mostly because I love its Ctrl+D function. When you mentioned the replace x with y using Cmd+R at 8:32, is that a plugin? I do notice you are using iOS, while I am on Windows, but I tried using Ctrl, the Windows button, Alt, Shift, and then went on Google to try and look it up. I can't find anything on it. This might be a stupid question with an obvious answer, but I'm just very confused right now and would love to know how you did that. :P

  • @kureysalp
    @kureysalp Рік тому +1

    GetNodeFromWorldPos has a problem. When the world pos is near edges it gets inaccurate. For example when it's at the most edge the position percentage is below zero. When you round that value to nearest Integer if that below zero value is less than 0.5f it will round to 0 and you get the most edge node yes But if it's more than 0.5 it will round to 1 and you will get next the Node.
    You should floor it without subtracting one than clamp to max index so it will not get out of index.

  • @dexyuzs
    @dexyuzs 9 років тому +1

    Hi Sebastian, nice tut!
    The 'NodeFromWorldPoint' function works fine for me when the player is near the (0, 0) point (the center of the map, we can say). But it gives me unaccurate values if I put the player far from that point. Any ideas about what's happening?
    Thank you!

    • @moeayyad8228
      @moeayyad8228 5 років тому +1

      Is it weird that I reply to a 3-year-old comment?
      Were you able to solve this? I kinda know where the problem is; if you're in a position that is larger than the grid world size (say your world size is set to 20 and you're at position 70), you're technically out of bounds, even though you're inside the grid, and that's because the division result will be larger than 1 which would then be clamped to 1 which is at the border of the grid. So we need some kinda offset from the origin, but so far all my attempts have failed :(

    • @moeayyad8228
      @moeayyad8228 5 років тому +2

      I've actually just solved the problem. As I mentioned above, the problem was with the offset. I was trying to offset everything from the origin, but the solution was to actually pretend we've never left the origin. To do that, I subtracted the player's position with the object's position (so if the player is at 75,0 and the enemy is at 70,0 --> We can treat it as if the enemy is at the origin and the player is at 5,0), this way the function makes sense and resulting value would always be

  • @Ben274722
    @Ben274722 8 років тому

    Hey Sebastian, great Video !!! But I have a question about the Node-Constructor in the Node class. I am a starter-programmer so forgive me any stupidity. Here is my Question : Why didn't you create the Node-Constructor in the grid-script and would this be possible too ? BR, Ben.

  • @RetroEcoChicken
    @RetroEcoChicken 4 роки тому

    add if (grid != null) if you are tired of the constant errormessages it just checks if it has a grid before trying to calculate
    {
    Node playernode = nodefromworldpoint(player.position);
    }

    • @RetroEcoChicken
      @RetroEcoChicken 4 роки тому

      then he deleates it in the end of the video. wow like getting my painting ripped from the refrigirator :(

  • @danny3man
    @danny3man 5 років тому +50

    Can you enable the subtitles ? some of us are deaf.Thanks.

    • @grandpas-stuff
      @grandpas-stuff Рік тому

      You’re deaf?

    • @scoreandspore.5606
      @scoreandspore.5606 8 місяців тому +1

      No

    • @braedenL29221
      @braedenL29221 3 місяці тому +1

      I'm sorry, I shouldn't be laughing, but this comment is so hilarious in the best way possible. "Some of us are deaf" so matter of fact lmao

    • @pureatheistic
      @pureatheistic Місяць тому +1

      If you're deaf, I recommend not relying on specific platforms to supply Accessibility features for this exact reason.
      Most OSs both on phone and Computers have features for generating captions. They aren't always right, but they all get pretty close.

  • @alisontaylor4589
    @alisontaylor4589 8 років тому +1

    is it possible to use this in a game in unity where your scene is so smalll that your node points to world points need to get small floats/doubles? I'm trying to use this in a game but sometimes my enemies go to spots they shouldn't be able to and get stuck, i think its something with the conversion but not sure.

  • @yagohenriquepereira3367
    @yagohenriquepereira3367 8 років тому

    amazing tutorial! Thanks

  • @javiermurarios3960
    @javiermurarios3960 9 років тому

    very wonderfull tutorials man, im enjoying so much your tutorials. And i want to add something very little, i dont like that NodeFromWorldPoint get the node to the right or bottom of the capsule so i modified the percent so they are calculated from the center of the capsule, but i dont know if the modification i did its really working on any case, here is my modification:
    percentX = (worldPosition.x + gridWorldSize.x/2 + nodeRadius) / gridWorldSize.x;
    percentY = (worldPosition.z + gridWorldSize.x/2 + nodeRadius)/ gridWorldSize.y;
    pd: forget it, it doesnt work, i was testing it just for the top right, the other sides doesnt work.
    pd2: well i think now works, just to make more precise the transition between nodes:
    public Node NodeFromWorldPoint(Vector3 worldPosition) {
    float percentX = (worldPosition.x + gridWorldSize.x/2) / gridWorldSize.x;
    float percentY = (worldPosition.z + gridWorldSize.y/2) / gridWorldSize.y;
    percentX = Mathf.Clamp01(percentX);
    percentY = Mathf.Clamp01(percentY);
    int x = Mathf.RoundToInt((gridSizeX-1) * percentX);
    int y = Mathf.RoundToInt((gridSizeY-1) * percentY);
    //here start my added modification
    if (grid [x, y].worldPosition.x + nodeRadius < worldPosition.x && x < gridSizeX - 1 && x > 0)
    x++;
    else
    if (grid [x, y].worldPosition.x - nodeRadius > worldPosition.x && x < gridSizeX - 1 && x > 0)
    x--;
    if (grid [x, y].worldPosition.z + nodeRadius < worldPosition.z && y < gridSizeY - 1 && y > 0)
    y++;
    else
    if(grid [x, y].worldPosition.z - nodeRadius > worldPosition.z && y < gridSizeY - 1 && y > 0)
    y--;
    return grid[x,y];
    }
    this should be easy for you but since i'm new with unity i wanted to see if im doing it right.

  • @mexico9500
    @mexico9500 7 років тому

    Love the video, please do audio books - your voice is great!

  • @Yukaraoke
    @Yukaraoke 3 роки тому +2

    Thank u for this tutorial. How can I implement this in 2d top down?

    • @ZZaGGrrUzz
      @ZZaGGrrUzz 3 роки тому +3

      just change vector.forward to vector.up and instead of spherecast use
      bool walkable = !(Physics2D.OverlapBox(worldPoint, new Vector2(nodeDiameter, nodeDiameter), unwalkableMask));
      or at least it seems to work for me at this lesson's stage of implementing
      and
      Gizmos.DrawWireCube(transform.position, new Vector3(gridWorldSize.x, gridWorldSize.y));
      for grid

    • @Yukaraoke
      @Yukaraoke 3 роки тому

      Thank you so much 💕💕

    • @gustavoguaresi8698
      @gustavoguaresi8698 3 роки тому

      ​@@ZZaGGrrUzz Thanks buddy, i am currently banging my head over this haha.

  • @L0932
    @L0932 9 років тому

    Sebastian Lague
    If I wanted to make the cyan colored detection cube for the player to work properly, does the plane have to be centered at 0,0,0? I've tested this out and that seems to be the case. What's a good solution to have the player detection working properly for planes positioned at any world position? Thanks in advance.

  • @annaleonid6095
    @annaleonid6095 8 років тому +2

    Hey - you are amazing! I love your teaching style! Thank you for these videos. I just wanted to ask - does the grid know how to detect sprites? I have no trouble getting the grid set up the way you have it, and it works fine with cubes as long as they're under the layer "unwalkable", or with newly imported quads etc. But not sprites, it seems.
    Do you have any advice? Is there something about the sprite renderer that acts differently than a mesh renderer?
    Thanks again!

    • @annaleonid6095
      @annaleonid6095 8 років тому +1

      Perhaps it's something to do with the "bool walkable = !(Physics.CheckSphere (worldPoint,nodeRadius,unwalkablemask)); ?
      Because sprites are 2d, does it have to be a different physics check?
      that's my guess anyway.

    • @_graiderz2462
      @_graiderz2462 8 років тому +4

      +Anna Leonid
      Yup yup.
      For 2D,
      Change,
      bool walkable = !(Physics.CheckSphere (worldPoint,nodeRadius,unwalkablemask));
      to
      bool walkable = !(Physics2D.OverlapCircle(worldPoint, nodeRadius, unwalkableMask));
      After this, it will still not work because, the sprite have no collider to detect collision (Physics2D.OverlapCircle)
      Therefore, add a 2D collider to the sprite.
      Worked on mine.

    • @annaleonid6095
      @annaleonid6095 8 років тому

      +Muhd Amirul Thanks!! That totally works!! One more question.
      How would I set walkable so that it can detect both sprites and 3d objects?
      bool walkable = !(Physics2D.OverlapCircle(worldPoint, nodeRadius, unwalkableMask)) || !(Physics.CheckSphere (worldPoint, nodeRadius, unwalkableMask));
      Am I missing some parentheses? I'm unable to get the grid to detect both.

    • @_graiderz2462
      @_graiderz2462 8 років тому

      +Anna Leonid
      Yo yo,
      Sorry for late reply. I was addicted to a specific game and yeah...
      I apologize, as this time, I am unable to explain why the following code work.
      Change,
      bool walkable = !(Physics2D.OverlapCircle(worldPoint, nodeRadius, unwalkableMask)) || !(Physics.CheckSphere (worldPoint, nodeRadius, unwalkableMask));
      to
      bool walkable = !( (Physics2D.OverlapCircle(worldPoint, nodeRadius, unwalkableMask)) || (Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask)) );
      It would seems that it has something to do with the ''!''.
      If it still doesnt detect the 3D object, make sure that the 3D object is touching the Grid.
      If it still doesnt work, then all the best.
      Im not sure if the new code would affect the pathfinding, because I already ditch my plan of using this tutorial because it doesnt provide me with smooth pathfinding, and dynamic pathfinding.

    • @IFrozenFireI
      @IFrozenFireI 8 років тому

      "dynamic pathfinding"? Dude, for it to be "dynamic", you should just call the appropriate code in an update function.

  • @jessenance8889
    @jessenance8889 4 роки тому

    I know it's been years since this video came out but can we generate nodes onto something more abstract than a plane? Say something like a sphere or something with hills. This is a good starting point for me in learning more about A* Pathfinding.

    • @bronze2181
      @bronze2181 4 роки тому

      Sure you can, the only difference is going to be how to assign the location of the node, the algorithm itself doesn't change at all.

  • @amanmahendroo1784
    @amanmahendroo1784 4 роки тому

    Awesome videos! But could you please increase the font size of your code? That would be great

  • @canfly8385
    @canfly8385 6 років тому

    thanks man, youre great.

  • @PauloHenrique-em2ly
    @PauloHenrique-em2ly 3 роки тому

    Just a question, if i make the gridWorldSize with diferent values, like (x=40, 15) the variable WorldBottomLeft still get the correct value?

  • @MrRemorc
    @MrRemorc 7 років тому +4

    I'm encountering a problem with the code. I have written everything down like it was done in the video, but when i run the program in Unity, no grid is drawn at all. Console doesn't return any errors either.

    • @GrashalmTuts
      @GrashalmTuts 7 років тому

      MrRemorc same problem here

    • @thejaker1O
      @thejaker1O 7 років тому +1

      I had the same problem and it was being caused by a missing decimal point so triple check your code!

    • @Ryanks12
      @Ryanks12 7 років тому

      I'm also having this problem - can't see any of my grid!

    • @RealTheMarco
      @RealTheMarco 7 років тому +1

      If somebody has the same problem : you certainly don't have active Gizmos in your Scene view. Check on Google.

    • @Ratstail91
      @Ratstail91 6 років тому

      Thank you!

  • @pedicagames3729
    @pedicagames3729 7 років тому

    I usually use this for "index from positions":
    int x = (int)((worldPosition.x - worldBottomLeft.x) / (nodeRadius * 2));
    int y = (int)((worldPosition.z - worldBottomLeft.z) / (nodeRadius * 2));
    x = Mathf.Clamp(x, 0, gridSizeX - 1);
    y = Mathf.Clamp(y, 0, gridSizeY - 1);
    return grid[x, y];
    ps: worldBottomLeft must be global and calculate at Start()

  • @CubeFlow_46
    @CubeFlow_46 Рік тому

    is anyone else having issues with player node and n both being null when checking if the playernode and n are equal inside of the OnDrawGizmos method? I can't figure out my issue, i have the same code as sebastian and nothing was going wrong before this. inside the NodeFromWorldPoint method, x and y are being updated correctly, but playernode is always null. help?

  • @marielauredebeaune1780
    @marielauredebeaune1780 2 роки тому

    thanks for this video how can I do for only make a line renderer betwen a few cubes in taking the shortest path?

  • @DerXavia
    @DerXavia 7 років тому

    I wonder why you use the sphere check instead of a boxcheck, isn't that more efficient?

  • @aryamangupta3919
    @aryamangupta3919 8 років тому +3

    Can you explain the math behind Converting World point to Node.

    • @IFrozenFireI
      @IFrozenFireI 8 років тому +5

      Hello. Since I realize that he is pretty bad at explaining. I will explain it to you. The point of WorldPoint is simple. It changes the point for every new cube(node in this example) by calculating the diameter and moving the new position correspondingly left and up to the diameter, so the cubes calculate the spacing between them and don't spawn in the same place... That's as simple as I can to explain it. First he creates a massive of object from the class Node//Node[,] grid\\ which contains (walkable and worldPosition) from the class //public Node(walkable, worldPosition);\\
      Then he calculates the sizeX and sizeY by determing the diameter of every cube so he can get clear picture of how many cubes are to take the grid and then he creates a for loop to go through every cube on the grid and change the position of every new one by using a virtual function of Node //grid=new Node[gridSizeX, gridSizeY]\\ and the worldpoint(which I already tried to explain). Hope I helped. It can be done easier by the way but he "overcomplicates" the code.

    • @IFrozenFireI
      @IFrozenFireI 8 років тому +2

      What he does is basically make a massive and save every cube's position by making it a virtual function so for exmaple grid[0,1] will have a worldPosition equal to worldPoint as seen in the code where he changes the assigns the parameter worldPoint to worldPosition.

    • @aryamangupta3919
      @aryamangupta3919 8 років тому

      IFrozenFireI Thank you for replying and i understood that.

  • @Random0scar
    @Random0scar 6 років тому

    Does the ondrawgizmos only update once? Because I have a game where you will be able to add and remove blocks and they dont turn red/white if I do.

  • @MrJiraiyah
    @MrJiraiyah 9 років тому +1

    There is something I would like to see, the nodes being generated on 3D coords and not only on 2D, I have an Idea and will try to use ur way but the implementation on 3D aspect needs a bit more thinking before just dropping the nods around the world for example if we are going to put them on the world terrain, how should we handle the slope that is possible for navigation? etc. etc. so can you add another video about node generation for 3D space. Thanks

    • @nyforandring
      @nyforandring 8 років тому

      +Alireza Khodakarami Did you get your idea working? I'm trying to do something similar. Please do help me out

    • @MrJiraiyah
      @MrJiraiyah 8 років тому

      80 Proof Gameplay yah i got some sort of working solution for 3d system but the lookup table would be too big for each scene or at least i think i was doing hasty job in R&D but if you join 3Dbuzz.com, i will soon publish some videos there about my systemm subscription is free, so why not?

  • @itsybitsypixel
    @itsybitsypixel 8 років тому +6

    *ANYONE WHO IS HAVING INACCURATE POSITIONS FROM THE NodeFromWorldPoint READ THIS*
    I found that the "NodeFromWorldPoint" method returned an inaccurate position while on the sides of the grid, so I tried remaking it too show a more accurate position. It's basically the same but it skips the percent and uses the nodeRadius and nodeDiameter variables and that somehow works.
    int x = Mathf.RoundToInt((worldPosition.x + gridWorldSize.x / 2 - nodeRadius)/nodeDiameter);
    int y = Mathf.RoundToInt((worldPosition.y + gridWorldSize.y / 2 - nodeRadius)/nodeDiameter);
    x = Mathf.Clamp(x, 0, gridSizeX - 1);
    y = Mathf.Clamp(y, 0, gridSizeY - 1);
    return grid[x, y];
    ^This code is inside the method^
    I tested this and it worked and gave me a more accurate position, but I have not tested this with the rest of the tutorial so be warned.
    Also I am using this for a 2D game so I used the Y position instead of the Z position in "worldPosition". If you are making a 3D game use Z instead.

    • @Seanld98
      @Seanld98 6 років тому

      I know this is old, but this tutorial is probably the best for pathfinding, and sorry for asking a question 2 years later, but I am also doing a 2D game, and for me when I first test to see the red and white squares, they are all white for me. None of them turn red. I changed the code so it showed in an XY way and removed the Z, but it doesn't work. I think it has something to do with bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask)); The 3D physics I think is the problem, but not sure how to fix it. Ideas?

    • @smilos99
      @smilos99 6 років тому +1

      @@Seanld98 Have you created a layer mask for unwalkable objects on your scene? If you have check if you have added the layer mask to your unwalkable game objects. Also if that is not the case check if you maybe forgot to change the "Unwalkable Mask" parameter on your "Grid" script from "Default" to "Unwalkable". If this is all correct for you maybe you miss-spelled something while writing the gizmos? This "bool walkable = !(Physics.CheckSphere(worldPoint, nodeRadius, unwalkableMask)); " seams fine to me :P.
      Hope this helps.

    • @Seanld98
      @Seanld98 6 років тому

      @@smilos99 I have double checked all that, but what I found changed it was adding the normal Box Colliders (non 2D) to the 2D boxes and that seemed to work so I'm not sure why it wouldn't work in the 2D space, thanks though :)

    • @MaskedImposter
      @MaskedImposter 6 років тому +2

      @@Seanld98 I'm currently going through this tutorial. This worked for me: bool walkable = !(Physics2D.CircleCast(worldPoint, nodeRadius, Vector3.forward, nodeRadius, unwalkableMask)); 2D and 3D colliders don't collide, so you gotta go 2D!

    • @darkopeninger1915
      @darkopeninger1915 5 років тому

      Thanks
      PixelMannen! I had the same issue and your comment solved it.

  • @sachacerf6513
    @sachacerf6513 7 років тому

    Hi sebastian. Ive got a problem with the playerNode : its not at the player position, but it moves correctly when im moving the player around. I think its a problem with the NodeFromPosition method, but i dont see any problems. Any idea?
    Edit : Ok, the Astar GameObject had to be at (0,0,0)

  • @hobojoejr2
    @hobojoejr2 2 місяці тому

    I know this video is old, but the code still works incase anyone was wondering.