Hello guys,
In my game, I have a flashlight that can be turned on or off. I want to detect whether the flashlight is shone on a particular object.how do I do this?
I came up with an idea:
I can use a cone mesh and detect collisions without having the mesh to collide. Is there an easier way to do this?
But itâs a flashlight which means that I have to check if the ray is in the correct direction as well.
I thought that a cone would be easier.
Btw I need help with the raycasting end everything bcoz Iâm noob and dont know anything about rays.
option 2: is as simple as slapping on a ray sensor, set itâs direction and do whatevery you like with it when it getâs positive. (so all logic bricks)
option 3:
hook up this script to your flashlight.
always -> python (module(hit script button) mode)-> scriptname.test (scriptname in text editor should end with .py.
def test(cont):
own = cont.owner
distance = 10
vec_y = own.worldPosition - own.worldOrientation.col[1]
ray = own.rayCast(own,vec_y,distance)
if ray[0]:
hit_obj = ray[0]
dist = own.getDistanceTo(hit_obj)
if dist<= distance:
print('Object', hit_obj, 'is lit')
assuming you modelled it in the y direction as forwards
The easiest way is to parent a cone shaped sensor object to your flashlight that matches the size of your light cone with a collision sensor attatched to it. You could either set the collision brick to detect a property or a material or use specific collision groups on your sensor and detectable objects.
The only drawback to this is that it will detect your objects through walls or other things in the way. Thatâs where the raycast comes in handy. When your cone detects an object, you cast a ray at it. If it hits the object, you know itâs actually in sight of your flashlight.
This also has a slight problem. A collision sensor doesnât return a hit point, only the object or a list of objects. So, if your object is sticking out from behind a wall but the origin is still behind the wall, the ray cast wonât see it because it is firing at the objectâs origin. That is why I recommend using a collision callback on the cone since it does return hit points. This is slightly more advanced scripting. If this situation wonât ever be an issue then donât worry about it.
I get your Idea of raycasting (and Cotaksâ idea too).
I need a way to get angle between the cast ray and the playerâs local Y axis.
by doing this, i can simply check if the angle is less than the fov of the flashlight.
how do I do that?
I guess your flashlight moves independently of your player? Usually you would keep the flashlight locked to the camera and the camera is usually locked to the playerâs forward axis(though x axis is made independant to look up and down). But you may be doing things differently soâŚ
To get the angle between the two, you need the vectors corresponding to your desired axis.
The playerâs Y+ axis vector is player_object.getAxisVect([0,1,0])
Use the same method to get the flashlightâs forward vector. Depending on how you built the flashlight, forward would be [1,0,0] if X+ is forward, [0,1,0] for Y+, [0,0,1] for Z+.
When you have the two vectors, you get the angle with angle = vector1.angle(vector2)
This returns in radians. If youâre more comfortable with degrees, you will have to import the math module - import math and use the degrees() method angle = math.degrees(vector1.angle(vector2))
There may be much simpler ways to do this but it all depends on how you have constructed your player-flashlight hierarchy. Thereâs no one right way to do it but most of the time there are more efficient ways to do it that will save CPU/GFX resources.
No, the flashlight follows the player.
your post may help me but im noob and know nothing about rays or vectors.
let me illustrate the problem of my previous post.
imagine that this is the top-down view of the scene:
The issue with this approach is you will have to check the angle of every object in the entire game to see if it is in the flashlightâs FOV. And then it would also have to be in the distance you chose. Even if you differentiate them by properties you still have to check all of them for the property first and then check if they are in range. If your map has 1000 objects(pretty easy to do when everything is an object), thatâs 1000 things you are looking at every frame.
Imagine this code running every single frame:
for obj in owner.scene.objects: # Could be 1000's of objects
vecTo = owner.getVectTo(obj)
angle = mathutils.Vector([0,1,0]).angle(vecTo[2]) # Create temp local Y+ vector and compare it to the local vector returned by getVectTo
if angle < pi/4 and vecTo[0] < some_distance:
print("Object in light field.") # Or whatever happens with it.
You can decrease this overhead by making sure you are only checking the angle of objects within a certain distance to the player. But you wonât know the distance until you check itâs distance. So again you are looking at every object in the map. There are other ways you can mitigate this brute force searching for objects like populating a list of only things you want to detect at the start of the map and then searching that smaller list later but these methods are only slightly better(and you would have to maintain the list manually as things come and go from the map).
This is why collision sensors are so useful. They donât interact with something unless they are touching it. By using a cone shaped sensor object that matches your flashlight cone, you will detect everything the light would hit. When you turn off the flashlight, you can turn off the sensor and vice-versa.
I understand that this method is inefficient but i have to check this only for the âenemyâ objects.
that reduces the clutter but the cone is way better.
I just learnt about radar sensors that @RPaladin mentioned and it does exactly what I wanted.
sorry for the delay and inconvenience
I have encountered another problem.
as soon as the radar detects an object (even just one object) , the framerate drops to like 5fps.
any help?
is there a more efficient way?
yup the power of bricks, thatâs why everyone should learn python, easiest language on the world.
cast ray to the collosion.hitObjectList, and see if they are hit instead of the wall or scale the plane to adjust itâs size, both wich require python