Hi everyone! It's been a minute. Progress on my game has been going well, but I hit another wall and was wondering if anybody might be able to help me figure out how to implement something specific.

I have a system in my game whereby enemies project a ray that starts at their position and ends at the player's position once the player is in their line of sight. Below is what that looks like in-game. The green lines are the rays that are being connected to the player.

My issue is that I want this raycast to be visible to the player as a way of warning of oncoming enemies. Right now I'm using debug to show the rays, but I want players to be able to see them too. What might be a good way to do this? Please reply if you know! Thank you :]

  • xyz replied to this.
  • crobison Make a line mesh using immediate mesh or array mesh with line or line strip primitive and transform it to match the raycast line.

    crobison Make a line mesh using immediate mesh or array mesh with line or line strip primitive and transform it to match the raycast line.

      xyz I tried this solution, and it worked well when there's one enemy on the field! However, when there is more than one enemy, things get a bit wonky. The second enemy to sense the player draws the same line as the first one rather than drawing its own line that will reach the player. You can see it in this screenshot here:

      What might I have to do to get each enemy I instantiate to draw a unique line?
      Here's my immediate mesh code if it helps:

      `
      extends MeshInstance3D

      @onready var player = $"../../player" #I'm not using this in the script right now, but it connects to the player in case I need it.
      @onready var raycast = $RayCast3D
      
      func _process(delta):
      
      	mesh.clear_surfaces()
      	mesh.surface_begin(Mesh.PRIMITIVE_LINES)
      
      	mesh.surface_add_vertex(Vector3(0, 0, 0))
      
      	mesh.surface_add_vertex(raycast.target_position)
      
      	mesh.surface_end()

      `

      • xyz replied to this.

        crobison Create a new mesh resource for each mesh instance. Currently it looks like all of them are sharing the same resource. If this is inside an instantiated scene, you can just enable mesh's resource_local_to_scene flag and it should work as you expect.

        Repositioning vertices each frame is not the most efficient way to do it though, but if you don't have hordes of enemies it likely wouldn't matter.

        My suggestion in fact implied that you construct only a single line mesh resource that's shared among all instances, and then translate/rotate/scale it into proper place via each mesh instance's transforms. That way you don't need to construct any mesh resources on the fly.

          a month later

          xyz Hi, sorry for the late reply! Since there are gonna be pretty big numbers of enemies I'm thinking the solution you originally implied would be best. What might be the best way to go about that? Currently I have my sightline meshinstance3D as a child of my enemy scene. Should I instead have it as a child of my player so it connect to all of the nearby enemies at once? If I'm still misunderstanding what u meant let me know. Thank u for your help!!

          • xyz replied to this.

            crobison It doesn't really matter where the nodes are situated. You need to calculate their proper transforms each frame either way. If only the nearby enemies will have this, then perhaps better to instantiate as needed and put instances under the player, or just directly in the scene and keep them easily accessible by assigning them to a group.

            The advantage of putting it inside each enemy is that you don't need to manage the cleanup when enemy dies. The disadvantage is that enemies that never reach the player proximity will drag along an extra unused node.