Important note! In this video I use the _process function, but ideally you should use the _physics_process function instead due to RayCast calls and movement.
@tompo1975 Bit late, but if you haven't found an answer yet you can give reference a script as a class using 'class_name `, other scripts can then inherit from that by using `extends ` at the top, much like a regular script will have `extends Node` or similar at the top. Hope that helps!
@@CodeWithTom no that doesn’t work it just goes backwards in the same direction no matter where I put it and when I rotate it it just goes forward in the same direction
If you're having issues with "Invalid get index 'collider' (on base: 'Dictionary'). Add if not result.empty(): before if result.collider.is_in_group("player"): My code looks like this: if target: var result = space_state.intersect_ray(global_transform.origin, target.global_transform.origin) if not result.empty(): if result["collider"].is_in_group("Player"): Thanks to the people in the Godot discord for helping me out.
Thank you! This helped so much! I am trying to get back into game design after years, totally new to Godot, and this helped a LOT. Just a couple bugs I am sure there are easy fixes for that I just can't figure out. 1) I added two AIs to a scene and both turn red when one sees the player character. 2) If the player character is standing on an elevated surface, the AI will turn until it is practically horizontal to look at the player. The AI used to literally fly to reach the player if the player was elevated, but I fixed that easily (watched the gravity tutorial you made and that kept them from flying).
FOR ANYONE WITH THE GET INDEX COLLIDER ERROR!!!: Check and see where the origin of the player and the enemy nodes are. In my case they were at y= 0 and the floor level was also at y=0 which means the raycast is in the floor, thus cant reach the player, if anything for that matter. I fixed it by placing a spatial node on both the player and on the enemy at about half the body height and raycasting from there.
I originally found your channel because I was stuck on a specific problem for a specific game jam... but I've decided to stick around because all of the content is pretty good.
You're very welcome Jo. I'm planning to refine these lessons and extend them into a full fledged course at some point. I'm also toying with the idea of releasing an open source first person framework
@@CodeWithTom fwiw I think releasing the core functionality as a plug-in framework would be a nice gesture, very much in the spirit of Godot. I'm actually making some changes to what we've done so far, as the game I have in mind is a stealth game where the player has a slingshot as opposed to a hitscan weapon. But! Just having core stuff like movement keys, mouse look, interactable objects, and a basic raycast in place demonstrating layers and groups, it all makes for a nice base on which to build.
@@jowilson5581 absolutely! The Ludum Dare entry I made uses projectile bullets instead of hitscan so id probably add that in too. Although it's a little buggy right now which I believe is to do with the speed of the bullet and the rate at which the collision area node reports bodies entering it. Will need to figure out the issue first. Also thinking of adding in things like customizable head bobbing, sway, camera shakes etc.
Does the enemy have a problem where it points at the player but there orientation is wrong (e.g face down) and it won't track the player? I might have a fix, otherwise, no idea
Thanks for continuing this series, i was using it to guide me through 3d in Godot and noticed that it cut off at part 3. Youve definitely made my quarantine project easier!
Was about to subscribe until I realised it's Code with Tom no surprises there best Godot tutorials on youtube, making my beginner coding journey possible.
Absolutely awesome tutorials. It’s perfect for someone with attention span issues. Fast, efficient and to the point. I’ve watched other tutorial videos that give the same amount of instruction, but the video is over an hour long because they keep going off on tangents. Drives me nuts. Anyway, I’ve subscribed and can’t wait for more videos. Are you gonna do any about how to do build a scene with textures and objects. I have no idea how all that works. Thanks again.
Yeah hes right, I can listen and know whats going on while not even watching the video, Voice is perfect. I like how he isnt overly funny neither, but if you pay attention closely there some funny jokes in there somewhere lol
im having a problem at 13:25, for some reason when the enemy sees me they turn the opposite way of me. Every time i go into their FOV they just turn by 180°
The issue with enemy clones turning red/green together is that they share the same spatial material instance. The solution is to create new one for each of them at the creation or update
I love the way you do the tutorials---describing everything in detail as you add it, and then doing a full recap at the end. Fantastic....makes it much easier for someone who, during his first cancer, had 3 brain tumors, three very severe brain surgeries, whole-brain/max-dose radiation therapy, plus very severe chemo which does cross the barrier into the brain, to learn from. Btw, minor point: are there supposed to be two part 4s? :-)
Hi Jim, thank you so much for the feedback. I'm really glad you find my method of teaching useful. It sounds like you've gone through an awful lot, but it fills me with joy to hear that my videos are helping you to learn game development and I wish you every success in your journey! 😁👍
Is there supposed to be a part 5? The title and video for four and five are the same. Just wondering. Don't want to miss the end of this tutorial set! :-) In part four (the actual part four not part four that's #5), you mention that the new setting is for something you'll be adding later. I gather, since it really wasn't used in part four, that there is a missing part five. But I could be mistaken. Oh, and the zip with the code is also labelled part 4. As for going through a lot, yes, definitely. But I put cancer #1 through hell. Every time it tried to kill me, the only thing it accomplished was to make me more furious with it and that much more defiant towards it. We caught cancer #2 so early it was just one surgery and done. And we caught #3 before it even became #3 (pre-cancerous mass). My email signatures read: The score: Me: 2 + 1-ish Cancer: 0The really bad thing is that #1 forcibly retired me and dumped me into Social So-Called Security Disability. Gamedev is my latest attempt at (eventually) making enough money to escape from this financial hell.
Fantastic i am surprised that these videos have so much low like, but keep up the good work. from the last three episodes i can even create my idea that i had struggled with in past 5 month.
Nice content, only some comments: 1. Why not use _physics_process instead of _process? All physics stuff must be handled in _physics_process(): move_and_slide -- This method should be used in Node._physics_process (or in a method called by Node._physics_process), as it uses the physics step’s delta value automatically in calculations. Otherwise, the simulation will run at an incorrect speed. 2. move_and_slide() doesn't need multiplication by delta: move_and_slide -- Unlike in move_and_collide, you should not multiply it by delta - the physics engine handles applying the velocity. 3. Why not to give each entity a class_name and then check it using "colider is Player" instead of using groups?
Hey Bogdan, you're absolutely right! It's been a few months since I've touched Godot and I'm a little rusty as you can tell 😂 All of your points are 100% valid and I appreciate you pointing them out. I like your type checking solution rather than checking the groups too! Thanks for the constructive comments. 😁👌
To those having the "Invalid get index 'collider' (on base: 'Dictionary')" error, it does (to me at least) seem to be an OSX-specific issue. Unfortunately this isn't the first time I've had OSX-specific issues with Godot. I'm now running the project on Linux and of course Tom (and many others I assume) are running it on Windows with no issues.
Hello, for those whom are having the albedo problem "attempted to call function 'albedo_color' in base 'null instance'" when running the get_surface_material. The only solution around it with the same architecture of code is to use get_active_material instead. At least for Godot version 3.4.4. My 'guess' to why get_surface_material doesn't work is that it only returns the material for the surface of the mesh and that material is something different than the material used for drawing the mesh? Godot says that it is null which means it hasn't been assigned anything. When using get_active_material it returns the correct material. This is just my ignorant guess lol. No idea why it works for some and doesn't for others? If it helps I am on Linux, Arch 5.18.3, LLVM 13.0.1, and Godot 3.4.4.
so instead of the enemy looking at me, he looks in opposite direction, I follow the same code as you did edit: The rotation works, but how do i lock the y rotation?
King Dunnad 8 months ago This happens because your enemy turns the wrong way, and then the player is out of the enemy's line of sight. To fix this: (You don't have to set the translation to be exactly the same as I have, roughly the same should work) Go to Enemy scene. Click on the MeshInstance node (the capsule). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: -180, z: 0. Scale is fine as it is. Click on the MeshInstance2 node (the cube to point where it's going). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0.7, z: -0.8. Set Rotation Degrees to x: 0 y: 0, z: 0. Scale is fine as it is. Click on the CollisionShape node (to collide with the enemy). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Scale should be all 1. Click on the Area node (the field of view). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: -1.063. Set Rotation Degrees to x: 0, y: 90, z: 0. Scale should be all 1. Click on the CollisionPolygon node (the field of view collision area). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Hopefully that helps.
I AM JUST GETTING STARTED IN THIS, SO I LOOK FOR HELP , AND IN THIS VIDEO, THE ONLY THING THAT IS WORKING FOR ME IS THE COLOR AND THE PART THE ENEMY IS LOOKING AT ME, NOTHING ELSE WORKS. ANY ANSWERS / TOM.
How computationally expensive is directspacestate? Wouldn't it be more optimized to have a raycast node that only gets enabled when a non-world object enters the viewing area? I could see grabbing the whole world stare getting *really* bad in terms of cpu and ram use if you have a large map with lots of enemies
Good question. I've not ran any benchmarks but I believe it is extremely cheap to run raycasts in this way. Especially since we only grab a reference to the space state object once (during the _ready call). It's main purpose is to make physics queries like we're doing here. docs.godotengine.org/en/3.2/classes/class_physicsdirectspacestate.html
Instead of making groups you could just use the collision layers inside of the engine in the inspector, in the game i'm currently working on instead of using the groups i used layers, and it's quite the same thing but I prefer the layers method
Awesome series, thanks a lot! I'm trying to apply this to a Doom Clone, it's all good except there aren't many tutorials on Doom-like billboards with directional sprites in a 3D environment.
i actualy followed this tutorial and in part when enemy doesnt see us behind the wall dont work every time i go away from wall he can see me and chase me
can the next episode be another episode on the enemy AI system? The one that I am currently using isn't working for the game I'm busy making. I am just asking if it can be in the next episode, thanks. Great tutorials btw!
@deadninja Did this work for you? As collider isn't a function, so I can't see how it would. I added a check for the presence of a collider property and it seems that the result does not have one. Also added a breakpoint and inspected it and there is no collider property.
@deadninja Odd! What version of Godot are you running if you don't mind me asking? Might be a small difference between versions or something. There seems to be both a lot of people where this tutorial works fine and a lot who are having this particular issue. Very strange!
@deadninja Looks like it's an OSX problem, started the tutorial on OSX. Moved across to Linux once I couldn't find a simple solution and everything worked fine. Pulled the changes back to OSX to verify it was OSX and it crashed again when spotted by an enemy.
Thank you very much! Your tutorials are the best. I try to make a simple fps engine with some modern features like camera shake when shooting or blood overlays splat to walls when enemies are hit. Could you include something like that? A sprite weapon and sprite enemy would be nice too. I aim to have 4 directional sprite enemies. Aaand are trigger areas possible? Lets say the player walks into an area, the light goes out and a sound plays.
It seems like it would be better to create a more cone shaped trapezoid for the viewing area rather than a completely flat one, can you do that with the collision polygon?
Hey James, very good point. The CollisionPolygon, from what I can tell, has a set height. You may want to opt for a CollisionShape to do something more like a cone. Or simply use a Sphere and check the angle to the player to see if it falls within your desired FoV. But good point! :)
I'm not sure why.. But when I enter the Area, it prints myself as "Player entered" just fine, but when I put if body.is_in_group("Player"): it doesn't detect or print anymore. Have I somehow changed my group? But exiting still prints, just not entering. Thank you. func _on_Sight_body_entered(body): if body.is_in_group(Player): print(body.name+" entered") func _on_Sight_body_exited(body): print(body.name+" exited")
Hello Tom! Can you help me with my problem please? Debugger: "Invalid get index 'collider' (on base: 'Dictionary'). It's happening when I exiting Area. I don't know what to do
Try this: King Dunnad 8 months ago This happens because your enemy turns the wrong way, and then the player is out of the enemy's line of sight. To fix this: (You don't have to set the translation to be exactly the same as I have, roughly the same should work) Go to Enemy scene. Click on the MeshInstance node (the capsule). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: -180, z: 0. Scale is fine as it is. Click on the MeshInstance2 node (the cube to point where it's going). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0.7, z: -0.8. Set Rotation Degrees to x: 0 y: 0, z: 0. Scale is fine as it is. Click on the CollisionShape node (to collide with the enemy). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Scale should be all 1. Click on the Area node (the field of view). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: -1.063. Set Rotation Degrees to x: 0, y: 90, z: 0. Scale should be all 1. Click on the CollisionPolygon node (the field of view collision area). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Hopefully that helps.
King Dunnad 8 months ago This happens because your enemy turns the wrong way, and then the player is out of the enemy's line of sight. To fix this: (You don't have to set the translation to be exactly the same as I have, roughly the same should work) Go to Enemy scene. Click on the MeshInstance node (the capsule). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: -180, z: 0. Scale is fine as it is. Click on the MeshInstance2 node (the cube to point where it's going). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0.7, z: -0.8. Set Rotation Degrees to x: 0 y: 0, z: 0. Scale is fine as it is. Click on the CollisionShape node (to collide with the enemy). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Scale should be all 1. Click on the Area node (the field of view). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: -1.063. Set Rotation Degrees to x: 0, y: 90, z: 0. Scale should be all 1. Click on the CollisionPolygon node (the field of view collision area). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Hopefully that helps.
look_at(target.global_transform.origin, Vector3.UP) at this line why my enemy is looking in opposite direction its not following my player . please help me hahah
totally loved your tutorial... part-4 is really amazing... but I ran into a problem... kindly help!!! in the enemy script|func _on_Area_body_entered(body)|.... there is an error that popped up "Attempt to call function 'Albedo_color' in base 'null instance' on a null instance". please help! I want my game to work properly... the game crashes whenever I come across the enemy.
Hey Ish, thank you! Looks like you're trying to call a function called "Albedo_color". It should be "set_albedo". Give that a go and let me know if that fixes it. Also feel free to join the discord if you need further assistance 😁
@@CodeWithTom well I used |func set_color_red(): $MeshInstance.get_surface_material(0).set_albedo(Color(1,0,0)) | as the function and |set_color_red()| to call the function.... but every time I run this... |Attempt to call function 'set_albedo' in base 'null instance' on a nullinstance.|
King Dunnad 8 months ago This happens because your enemy turns the wrong way, and then the player is out of the enemy's line of sight. To fix this: (You don't have to set the translation to be exactly the same as I have, roughly the same should work) Go to Enemy scene. Click on the MeshInstance node (the capsule). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: -180, z: 0. Scale is fine as it is. Click on the MeshInstance2 node (the cube to point where it's going). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0.7, z: -0.8. Set Rotation Degrees to x: 0 y: 0, z: 0. Scale is fine as it is. Click on the CollisionShape node (to collide with the enemy). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Scale should be all 1. Click on the Area node (the field of view). Go to the Inspector tab and click to expand Transform. Set Translation to x: 0, y: 0, z: -1.063. Set Rotation Degrees to x: 0, y: 90, z: 0. Scale should be all 1. Click on the CollisionPolygon node (the field of view collision area). Go to the Inspector tab and click to expand Transform. Translation should be all 0. Set Rotation Degrees to x: 90, y: 0, z: 0. Hopefully that helps.
Valid point, this was mostly for demonstration purposes. But you can achieve this by using linear interpolation between the enemy's current direction and the direction to the player. I will cover this in another tutorial in the future.
I am doing something like this in _process(): var needed_angle = get_angle_to(player.global_position) rotation = lerp_angle(rotation, needed_angle, delta)
Hey, I just finished coding the part of the tutorial which is debugged at 13:48 and I can't seem to get it working. Before I started this step it was working fine (The change color when in line of sight part). But now when I add in the 'following the player' step, the enemy just sits there and doesn't move, change colors, or anything else. There also isn't an error popping up in the engine after I have tried the debug. Thanks for the help!
i understand that it is old tutorial but if anyone can help me, problem "Invalid call to func "intersect_ray" in base 'GodotPhysicsDirectSpaceState3d', here the code at whitch i stuck: extends CharacterBody3D var _space_state var target func _ready(): _space_state = get_world_3d().direct_space_state func _physics_process(delta): if target: var result = _space_state.intersect_ray(global_transform.origin, target.global_transform.origin) if result.collider.is_in_group("Player"): look_at(target.global_transform.origin, Vector3.UP) set_color_red() else: set_color_green() func _on_area_3d_body_entered(body): if body.is_in_group("Player"): target = body print(body.name + "entered") set_color_red() func _on_area_3d_body_exited(body): if body.is_in_group("Player"): target = null print(body.name + "exited") set_color_green() func set_color_red(): $MeshInstance3D.get_active_material(0).set_albedo(Color(1, 0, 0)) func set_color_green(): $MeshInstance3D.get_active_material(0).set_albedo(Color(0, 1, 0))