intersect_shape() defaults to 32 "max results" if you want to select more make sure to increase this"intersect_shape(query, )" . Was really confused when I created a lot of units. Hope it helps someone. Thx for the videos, very helpful!
I got this working except that when I select multiple units the units RayCast2D's that detect obstacles in the vehicles path stop working , when a unit gets stuck this way and I click on it the RayCast2D's starts working again and it navigates out of the obstacle with out being given the second click to set its destination. when I select units one at a time the navigation RayCasts don't stop working it only happens when I select multiple units.
Happy new year to KCC! I hope 2020 brings us a ton more videos from this channel. 🧡💛💚 After I have finished your tank tutorial, I started working on my own little game that uses some of the tips and tricks from that tutorial. Here is what I have so far: ua-cam.com/video/RApt-3fIHB8/v-deo.html All the art (except bullets and explosion) I drew myself. I plan on making few different biomes some time later, once I have everything in the game working. It's not the most original game, but I need something I can handle in order to learn the engine. 😁 This tutorial will be awesome when I start making a little selectable hero unit. Thank you for your tutorials, they really make a difference. Your teaching style just works for me, and I prefer it to any other tutorial series!
for item in selected: item.collider.selected = true it doesn't highlight the units else: for item in selected: item.collider.target = event.position item.collider.selected = false selected = [] when I try to run it, crashes
By the way, which video shows us how to make click to move? I tried searching for it on the channel but can't find it. Also, on the website, in the article for this tutorial, "starting project" link is missing. I am guessing it will be added later.
I'm sure I've used it in some demo before. Regardless, see here for an example of click-to-move: docs.godotengine.org/en/latest/tutorials/2d/2d_movement.html#click-and-move I'll check the written article - thanks for letting me know.
I tried something like this for CharacterBody2D node: extends CharacterBody2D @export var speed = 400 var selected = false var target: Vector2 func _ready(): target = position func _physics_process(delta): velocity = position.direction_to(target) * speed if position.distance_to(target) > 10: move_and_slide()
When I was doing this with a moving camera, my rectangles drew wrong. event.position was giving different values than get_global_mouse_position so i just set both to get_global_mouse_position and it started drawing correctly. I think it was because event.position's 0, 0 coordinates were based on camera position while global was not. I was confused because with a fixed camera it worked as intended. However, now Im not getting it to return the kinematic2d bodies I have within the rectangle. I just wanted to give folks a heads up that might be doing something similar, however I didnt want to say the solution worked perfectly till I could get thing to show up in my array.
did you get it to detect the kinematic2d bodies? I have no idea how to get it to work Edit: Just figured it out. I was using PhysicsShapeQueryParameters instead of Physics2DShapeQueryParameters took far too long to figure that out
Yep. event.position was returning local positions not global ones with my set up too, so I use get_global_mouse_position() instead. It's fine so long as you use the same for drag_end, drag_start and in the _draw function.
you could give each unit a team name eg. ""red"" and then check if the players team is the same as the units eg if TEAM_COLOR == item.color: ## put the action here
@@camuor3645 thanks, I asked this some time ago and never really got this to work quite this way using Direct space state. I learned how to do box select with an area and defining a collision rectangle. I just used groups [ if body.is_in_group("player"): body.selected = true ] I learned a lot from this video , I also make some Godot content you may want see see a variation on this method ua-cam.com/video/9Q8zgXQBinU/v-deo.html
Yeah, unit selection can be quite complicated to implement in the first time, specially in Godot. Another thing that I find very hard is to automate some unit according to its function: like a lumberjack that receives the command to chop some wood and keep doing its task (find a tree, chop it, collect the wood, carry the wood to the lumberyard, drop the wood, restart) until another command is given. I would be very grateful if you could give some directions.
@@DarkestEngineer That's the right answer. But imagine a AoE worker that you can assign multiple kinds of jobs (forager, farmer, gold miner, stone miner, lumberjack, hunter, fisher). What is the idea? To define a state machine for each possible job an then set the corresponding job on the unit when a new comand is given, or to define a big single state machine and then change the states according to some auxiliary "job" variable? Maybe there are more ways of doing it.
@@jorgegomes83 what you will take as a solution it only depends on you. As state machine you can group jobs as a categories where they are doing the same thing but from different sources. So this way you can create states as mine, harvest, hunt.
@@DarkestEngineer Godot probably already provides a State Machine node, but i'm yet to learn how to use it and see if it works more or less the way I imagine. Thanks for the help, anyways.
@@Kidscancode Thanks for the reply. I was referring specifically to the order of processing: unhandled_input() is handled before input_event(), so a mouse event will first be considered the start of a drag, rather than a press and release
True, but in the main scene you can check for this case first. In practice, you're probably going to want a hover effect on the unit, so you'd use its `mouse_entered` signal and at that point you know you have a unit under the mouse so you don't start a drag.
@@Kidscancode Mouse_entered and _exited is what I'm currently using. However, I feel like this is a non-intuitive approach, especially for beginners. Perhaps something to discuss in a future video? :)
Updated version of the code that I've tweaked to be more like classic C&C selection. extends Node2D var isDragging = false var selectedUnits = [] var dragStart = Vector2() var selectedRectangle = RectangleShape2D.new() func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if event.is_pressed(): isDragging = true dragStart = get_global_mouse_position
for selection in selectedUnits: var selectionCollision = selection.collider if selectionCollision.is_in_group("Selectable"): selectionCollision.DisableSelection() selectedUnits = []
var space = get_world_2d().direct_space_state var query = PhysicsShapeQueryParameters2D.new() query.set_shape(selectedRectangle) query.transform = Transform2D (0, (dragEnd + dragStart) / 2) selectedUnits = space.intersect_shape(query)
for selection in selectedUnits: var selectionCollision = selection.collider if selectionCollision.is_in_group("Selectable"): selectionCollision.EnableSelection()
if event is InputEventMouseMotion and isDragging == true: queue_redraw()
@@Kidscancode I wanted to apply a slow motion effect to my game when my player is stand still/not moving...so i used time_scale like...... If input false.... Engine.time_scale = 0.5 else: Engine.time_scale = 1 But Then my game physics is affected... Like the length of jump height get low... I think it's because it's affecting delta.... So , now help me, how to create a slow motion effect.... When my player not moving with out affecting the jump height.... YOU ARE MY LAST HOPE....
@@Kidscancode Ah ok, I might try to come this week too...The app is going well, just published a big update yesterday, getting a little bit into shader scripting now, and finally got IAP working for iOS and Android after months of trial and error. I'm using match everywhere in my code now, learned so much from you that one time!
Just made a thread about this tutorial on the Godot forums, here's the updated code for Godot 4, the main change is in how the rectangle shape is calculated, this should all be functional, you've just got to finish it off for your particular mechanics. selectedRectangle.size = (dragEnd - dragStart).abs() extends Node2D var isDragging = false var selectedUnits = [] var dragStart = Vector2() var selectedRectangle = RectangleShape2D.new() func _unhandled_input(event): if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT: if event.is_pressed(): if selectedUnits.size() == 0: isDragging = true dragStart = event.position else: selectedUnits = []
When your done with this game you showing us how to make you should show us how to make a game engine I know it’d be very hard but I think it would be a fun project
Making a game engine is an enormous project. Not really something I'm looking to take on, I'm afraid. There are existing resources out there, if you're really interested. Plus Godot's source is all open, so you can look under the hood and see how it's done.
Спасибо за урок. Но как то я уже остыл не знаю зачем я всё это смотрю, хоть и понимаю что написать код мне удастся только для чего? Риторический вопрос.
It's nice to see you back, you are one of my favorite Godot instructor.
An indispensable game mechanic for RTS games.
It's nice to see you again Chris! Thank you very much for helping and teaching us the fundamentals of Godot!
My pleasure - thanks for watching!
2020 starts off good with my fav Godot instructor! thank you sensei
Conveniently, I needed just this recipe for a project I'm working on. Thanks Chris!
intersect_shape() defaults to 32 "max results" if you want to select more make sure to increase this"intersect_shape(query, )" . Was really confused when I created a lot of units. Hope it helps someone. Thx for the videos, very helpful!
Good catch!
Thanks so much for this, you're a lifesaver :)
Thank you. That was doing my head in.
I got this working except that when I select multiple units the units RayCast2D's that detect obstacles in the vehicles path stop working , when a unit gets stuck this way and I click on it the RayCast2D's starts working again and it navigates out of the obstacle with out being given the second click to set its destination. when I select units one at a time the navigation RayCasts don't stop working it only happens when I select multiple units.
How would you select only collision shapes for one physics layer?
I have no idea how to handle a target system do you have any video about that? selecting by clic on enemy and set as a target for a player.
Do you have a link to your video dealing with point and click movement?
Happy new year to KCC! I hope 2020 brings us a ton more videos from this channel. 🧡💛💚
After I have finished your tank tutorial, I started working on my own little game that uses some of the tips and tricks from that tutorial. Here is what I have so far: ua-cam.com/video/RApt-3fIHB8/v-deo.html All the art (except bullets and explosion) I drew myself. I plan on making few different biomes some time later, once I have everything in the game working. It's not the most original game, but I need something I can handle in order to learn the engine. 😁
This tutorial will be awesome when I start making a little selectable hero unit.
Thank you for your tutorials, they really make a difference. Your teaching style just works for me, and I prefer it to any other tutorial series!
Thanks - keep up the good work!
for item in selected:
item.collider.selected = true
it doesn't highlight the units
else:
for item in selected:
item.collider.target = event.position
item.collider.selected = false
selected = []
when I try to run it, crashes
could you make a video where you show how to make a character for an rts game?
How does this implement in a 3D RTS game?
how i fix this ? (Godot3.5)
invalid set index 'selected' (on base: 'KinematicBody2D (Unit.gd) with value of type 'bool'
how do you make this 3d?
By the way, which video shows us how to make click to move? I tried searching for it on the channel but can't find it.
Also, on the website, in the article for this tutorial, "starting project" link is missing. I am guessing it will be added later.
I'm sure I've used it in some demo before. Regardless, see here for an example of click-to-move:
docs.godotengine.org/en/latest/tutorials/2d/2d_movement.html#click-and-move
I'll check the written article - thanks for letting me know.
I tried something like this for CharacterBody2D node:
extends CharacterBody2D
@export var speed = 400
var selected = false
var target: Vector2
func _ready():
target = position
func _physics_process(delta):
velocity = position.direction_to(target) * speed
if position.distance_to(target) > 10:
move_and_slide()
He says he talked about click-to-move in another recipe but I can't find it anywhere! Does anyone know which video he is talking about?
Awesome videos, but why don't you have ssl on your site?
It will definitely help your search engine ranking, more ppl need to see your content.
When I was doing this with a moving camera, my rectangles drew wrong. event.position was giving different values than get_global_mouse_position so i just set both to get_global_mouse_position and it started drawing correctly. I think it was because event.position's 0, 0 coordinates were based on camera position while global was not. I was confused because with a fixed camera it worked as intended.
However, now Im not getting it to return the kinematic2d bodies I have within the rectangle. I just wanted to give folks a heads up that might be doing something similar, however I didnt want to say the solution worked perfectly till I could get thing to show up in my array.
saved me a lot of hassle thank you :D
though mine do still show up in the array (so far lol)
did you get it to detect the kinematic2d bodies? I have no idea how to get it to work
Edit:
Just figured it out. I was using PhysicsShapeQueryParameters instead of Physics2DShapeQueryParameters
took far too long to figure that out
Thank you! Helping me solve bugs in 2023 :D
Yep. event.position was returning local positions not global ones with my set up too, so I use get_global_mouse_position() instead. It's fine so long as you use the same for drag_end, drag_start and in the _draw function.
is it possible to do this with rigidbodies instead of kinematic bodies?
i cant get the mouse detection to work
Body type doesn't really matter.
thanks for the tutorial , I cant seem to figure out how to set this up so I cant select enemy units
you could give each unit a team name eg. ""red"" and then check if the players team is the same as the units
eg if TEAM_COLOR == item.color:
## put the action here
@@camuor3645 thanks, I asked this some time ago and never really got this to work quite this way using Direct space state. I learned how to do box select with an area and defining a collision rectangle. I just used groups [ if body.is_in_group("player"): body.selected = true ]
I learned a lot from this video , I also make some Godot content you may want see see a variation on this method
ua-cam.com/video/9Q8zgXQBinU/v-deo.html
Yeah, unit selection can be quite complicated to implement in the first time, specially in Godot.
Another thing that I find very hard is to automate some unit according to its function: like a lumberjack that receives the command to chop some wood and keep doing its task (find a tree, chop it, collect the wood, carry the wood to the lumberyard, drop the wood, restart) until another command is given.
I would be very grateful if you could give some directions.
make a State Machine
@@DarkestEngineer That's the right answer. But imagine a AoE worker that you can assign multiple kinds of jobs (forager, farmer, gold miner, stone miner, lumberjack, hunter, fisher). What is the idea? To define a state machine for each possible job an then set the corresponding job on the unit when a new comand is given, or to define a big single state machine and then change the states according to some auxiliary "job" variable?
Maybe there are more ways of doing it.
@@jorgegomes83 what you will take as a solution it only depends on you. As state machine you can group jobs as a categories where they are doing the same thing but from different sources. So this way you can create states as mine, harvest, hunt.
@@DarkestEngineer Godot probably already provides a State Machine node, but i'm yet to learn how to use it and see if it works more or less the way I imagine. Thanks for the help, anyways.
Can this be used for 3D RTS ?
Sure, with some modifications.
Sadly, the zip file for the project can't be found on the site anymore. That's kind of an important oversight.
Link fixed.
How would you combine this with a click to select a single unit? I've been trying to find a simple implementation for this
Physics bodies all have _input_event(), so you can detect clicks that are directly on the body.
@@Kidscancode Thanks for the reply. I was referring specifically to the order of processing: unhandled_input() is handled before input_event(), so a mouse event will first be considered the start of a drag, rather than a press and release
True, but in the main scene you can check for this case first. In practice, you're probably going to want a hover effect on the unit, so you'd use its `mouse_entered` signal and at that point you know you have a unit under the mouse so you don't start a drag.
@@Kidscancode Mouse_entered and _exited is what I'm currently using. However, I feel like this is a non-intuitive approach, especially for beginners. Perhaps something to discuss in a future video? :)
@@Kidscancode One more question: if you're developing for mobile it's not possible to check for mouse_entered. What would you recommend in that case?
Updated version of the code that I've tweaked to be more like classic C&C selection.
extends Node2D
var isDragging = false
var selectedUnits = []
var dragStart = Vector2()
var selectedRectangle = RectangleShape2D.new()
func _unhandled_input(event):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if event.is_pressed():
isDragging = true
dragStart = get_global_mouse_position
for selection in selectedUnits:
var selectionCollision = selection.collider
if selectionCollision.is_in_group("Selectable"):
selectionCollision.DisableSelection()
selectedUnits = []
elif isDragging == true:
isDragging = false
queue_redraw()
var dragEnd = get_global_mouse_position
selectedRectangle.size = (dragEnd - dragStart).abs()
var space = get_world_2d().direct_space_state
var query = PhysicsShapeQueryParameters2D.new()
query.set_shape(selectedRectangle)
query.transform = Transform2D (0, (dragEnd + dragStart) / 2)
selectedUnits = space.intersect_shape(query)
for selection in selectedUnits:
var selectionCollision = selection.collider
if selectionCollision.is_in_group("Selectable"):
selectionCollision.EnableSelection()
if event is InputEventMouseMotion and isDragging == true:
queue_redraw()
func _draw():
if isDragging == true:
draw_rect(Rect2 (dragStart, get_global_mouse_position() - dragStart), Color.DARK_GREEN, false)
how to do slow motion effect....?
There are multiple tutorials about this if you search.
@@Kidscancode I wanted to apply a slow motion effect to my game when my player is stand still/not moving...so i used time_scale like......
If input false....
Engine.time_scale = 0.5
else:
Engine.time_scale = 1
But Then my game physics is affected... Like the length of jump height get low... I think it's because it's affecting delta....
So , now help me, how to create a slow motion effect.... When my player not moving with out affecting the jump height....
YOU ARE MY LAST HOPE....
If you're using delta in all your movement calculations then changing time_scale shouldn't change any of your physics.
@@Kidscancode ok , i got it and i solved it...
Awesome! Thanks!! Btw, are you still coming to Burbank coding group? This is Vaughan, the painting app guy.
I'm afraid not - it's been pretty busy. Is there one this coming week, because maybe I could stop by.
How's the app coming along?
@@Kidscancode Ah ok, I might try to come this week too...The app is going well, just published a big update yesterday, getting a little bit into shader scripting now, and finally got IAP working for iOS and Android after months of trial and error. I'm using match everywhere in my code now, learned so much from you that one time!
@@Kidscancode I might not be able to make it this week after all :(
Please do a video on Normal Maps please, pretty please
What about normal maps are you curious about? Is there a particular application? 2D or 3D?
Ooh I use Gimp to make my normal maps, but they don't really affect the surface only the edges of the sprite and it doesn't really look realistic
Awesome
Thanks!
"click to move is pretty easy to implement"
it took me 100 lines of code ;-;
Not sure if you're joking, but here's a great example of how easy it is: docs.godotengine.org/en/latest/tutorials/2d/2d_movement.html#click-and-move
he didnt mean to a pathfinding
Just made a thread about this tutorial on the Godot forums, here's the updated code for Godot 4, the main change is in how the rectangle shape is calculated, this should all be functional, you've just got to finish it off for your particular mechanics.
selectedRectangle.size = (dragEnd - dragStart).abs()
extends Node2D
var isDragging = false
var selectedUnits = []
var dragStart = Vector2()
var selectedRectangle = RectangleShape2D.new()
func _unhandled_input(event):
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
if event.is_pressed():
if selectedUnits.size() == 0:
isDragging = true
dragStart = event.position
else:
selectedUnits = []
elif isDragging == true:
isDragging = false
queue_redraw()
var dragEnd = event.position
selectedRectangle.size = (dragEnd - dragStart).abs()
var space = get_world_2d().direct_space_state
var query = PhysicsShapeQueryParameters2D.new()
query.set_shape(selectedRectangle)
query.transform = Transform2D (0, (dragEnd + dragStart) / 2)
selectedUnits = space.intersect_shape(query)
print(selectedUnits)
for selection in selectedUnits:
print(selection)
if event is InputEventMouseMotion and isDragging == true:
queue_redraw()
func _draw():
if isDragging == true:
draw_rect(Rect2 (dragStart, get_global_mouse_position() - dragStart), Color.DARK_GREEN, false)
When your done with this game you showing us how to make you should show us how to make a game engine I know it’d be very hard but I think it would be a fun project
I prefer small tips to implement features in our Godot game like he does.
Making a game engine is an enormous project. Not really something I'm looking to take on, I'm afraid. There are existing resources out there, if you're really interested. Plus Godot's source is all open, so you can look under the hood and see how it's done.
KidsCanCode thanks I’ll check that out
Спасибо за урок. Но как то я уже остыл не знаю зачем я всё это смотрю, хоть и понимаю что написать код мне удастся только для чего? Риторический вопрос.