How to detect if a player is within a mob's line of sight, and can that be changed?



  • Is it possible to detect if a player is within a mob's line of sight? And if so, can that line of sight be changed to only see things in 1 axis? For example, only being able to see things in front of it, but not if it's 1 or more blocks away from it.



  • sorry for the late answer but I have found the ultimate trivial method to do what you want. To start off, it involves passenger entities and raycasting. The code is really short but you will still need a datapack for the raycasting function.

    The only downside to this method is that the subject entities that can detect your presence must be unique and summoned manually.

    First, spawn a mob with an armor stand riding it using the following command. summon zombie ~ ~1 ~ {Passengers:[{id:"minecraft:armor_stand",Invisible:1b,Invulnerable:1b,Tags:["probe"]}]}

    In this case a zombie with an invisible armor stand tagged "probe" is spawned.

    Now you want to have this mcfunction in your datapack.

    execute run particle flame 
    execute if entity @p[distance=0..0.99] run say hit!
    execute if block ~ ~ ~ #permeable positioned ^ ^ ^0.2 run function namespace:raycast
    

    It is really short and efficient and the particle command is of no practical use other than displaying to you the ray so you can delete it later. Next up, the command checks for the nearest player within a 1 block radius. Note that the detection range is set to 0.99 so that there is a minimum risk of detecting though blocks. Last command dictates that if the block it is currently in is not classified as permeable, it does not repeat itself (stops raycasting).

    Now what you have to do is simple --- execeute as @e[tag=probe] at @s run function namespace:raycast. Watch as the armor stand detects you within its line of sight and say hit!. The armor stand does not detect you if there are blocks in between.

    A few Tweaks you can bring to the command You might want to consider entities obstacles as well. That is, if you are hiding behind mobs, the armor stand could not detect you. If that is the case, replace the function command in the .mcfunction with execute if block ~ ~ ~ #permeable unless entity @e[type=#exclude,distance=0..0.99,limit=1,sort=nearest] positioned ^ ^ ^0.2 run function namespace:raycast

    As you have mentioned in the question, you would like the mob to have a maximum detection range. I would take it as 10 blocks for example.

    The frequency of raycasting in the function is 5 times/ block, which means that if the function runs 50 times, a maximum total of 10 blocks have been covered within 1 tick. You can set up a dummy scoreboard. scoreboard objectives add count dummy. Insert this into the middle of your function scoreboard players add @s count 1. Replace the run function command with this execute as @s[scores={count=..50}] if block ~ ~ ~ #permeable positioned ^ ^ ^0.2 run function namespace:raycast And at the end of the function you would insert this line of command. execute as @s[scores={count=51..}] run scoreboard players set @s count 0 This way you have limited the range of raycasting. Just for you to double check, the code in raycast.mcfunction should look something like this now.

    execute run particle flame 
    scoreboard players add @s count 1
    execute if entity @p[distance=0..0.99] run say hit!
    execute as @s[scores={count=0..50}] if block ~ ~ ~ #permeable positioned ^ ^ ^0.2 run function namespace:raycast
    execute as @s[scores={count=51..}] run scoreboard players set @s count 0
    

    How to integrate Probe with the mob it rides on Until now although the probe rides the zombie, they are still literally two different entities. To eliminate this discrepancy we use a selector @e[type=zombie,limit=1,sort=nearest] to figure out the closest zombie in relation to the probe armor stand, then execute a function as that zombie.

    It should look like this now.

    execute run particle flame 
    scoreboard players add @s count 1
    execute if entity @p[distance=0..0.99] run execute as @e[type=zombie,sort=nearest,limit=1] run say I see you lmao
    execute as @s[scores={count=0..50}] if block ~ ~ ~ #permeable positioned ^ ^ ^0.2 run function namespace:raycast
    execute as @s[scores={count=51..}] run scoreboard players set @s count 0
    

    Replace the "I see you lmao" with a function of your own choice.

    zombie seeing me

    Killing the Probe In your tick function, execute as @e[tag=probe] at @s unless entity @e[type=zombie,distance=0..2,limit=1,sort=nearest] run kill @s

    All the above code has been verified by myself and all works. There are other variations you can play with the function but I surely won't list out all of them here. Your question is certainly a great one as it is mutually beneficial. I could use this method for my own project as well. Hope that works for you as well.

    Have a good one.

    Edit: the #permeable group is a predefined block type tag in the datapack.

    {
        "values":[
            "air",
            "cave_air",
            "cobweb",
            "water",
            "tall_grass",
            "grass",
            "#flowers",
            "#crops",
            "#fire"
        ]
      }
    



Suggested Topics

  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2
  • 2