detect player looking at object

I am trying to create a system that allows objects to detect when a player is looking at them. I did this successfully by parenting a sensor rectangle in front of the players face, but this will also make object think the player is looking at the object even through walls. How can I fix this?

You could cast a ray from the camera at the object and see if it hits a wall first.

A ray? How do I cast a ray?

You use the Ray sensor in the logic editor. Here’s a tutorial/explanation by Goran:

This doesn’t exactly work for what I need, I am using the box in-front of the player so that items can detect when the player is looking at it. This ray detects when the player looks at items, but the item can’t sense that.

  1. Use the sensor-type object to tell if the player’s looking at an item (if it’s touching the sensor).

  2. Use the Ray sensor or a Python rayCast() function from the player to the object (which is generally better, since the Python function runs in the direction you tell it to) to tell if there’s something between them.

  3. Use Python to set a variable on the object (which you can get by accessing the Ray Sensor’s hitObject property, or as part of the returned list for a rayCast() function) to let it know that it’s being looked at.

If you’re using python you can use the object.rayCast function to shoot a ray from the camera to the object to test for occlusion, and use the camera.boxInsideFrustum command to test if the object is inside the camera’s view (this should be more efficient than doing a collision check, although you might want to benchmark it to be sure). If you want to activate logic on the object that’s being tested, you can run the script on that object and get the active camera with bge.logic.getActiveScene().active_camera.

Attach the Ray sensor to a message actuator? The item will receive the message, and then you can have the item do what you need.

or maybe have an empty parented to the item, which tracks to the player, and casts a ray, this way its the object casting the ray, not the player? Just an idea.

Ray is not a good idea if you are making 3rd person game. It depends, where is the ray altitude and where is the object located. The end result is hard and unnatural experience looking at objects. This is from my personal experience. In other hand, using radar is not a good idea, even though it is a cone of rays it slows your performance big time. What I made in my game is a dictionary, that holds all interactable objects in the scene and a scripts linked to your player and the objects.
This is what you should do(The code is in Python 2.6, but it can easily be translated to Python 3):


#Create the dictionary in a script, that executes only once in the beginning.
import GameLogic as g
g.InteractableObjs={}


# Attach this script to every interactable object.
import GameLogic as g
cont=g.getCurrentController()
own=cont.owner
g.InteractableObjs[id(own)]={}
g.InteractableObjs[id(own)]['id']=id(own)
#g.InteractableObjs[id(own)]['name']....
#g.InteractableObjs[id(own)]['prop1']....
#g.InteractableObjs[id(own)]['prop2']....
# and whatever properties you want to hold in this dictionary


# Attach this script to the Player with always sensor set to 10-20-30 whatever the value.(never use 0)
import GameLogic as g
current_obj=g.getCurrentScene().objects
cont=g.getCurrentController()
own=cont.owner

nearestObj=[] # create a list        
    for name in g.InteractableObjs:
        obj=current_obj.from_id(g.InteractableObjs[name]['id'])
        if obj.getDistanceTo(own)< 1 :# set your own distance
            dist=obj.getDistanceTo(own)
            nearestObj.append((dist,obj)) # fill the newly created list
            nearestObj.sort() # This function sorts objects by distance in the list
            lookObjects.frequency=1 # 'lookObjects' is the always sensor of your player that is attached to this script. 
    if len(nearestObj)>0:
        found_obj=nearestObj[0][1] #[0] is the distance,[1] is the object
        g.found_obj=found_obj # assign the object to a random global variable you can use later in you game.

That way you can easily look at any object within your grasp. No matter what the angle between you and the object is and the script is faster, than rays or radar sensors.

The code is in Python 2.6, but it can easily be translated to Python 3

Maybe I’m not seeing this correctly, but these scripts don’t seem to work for OP’s question.

This doesn’t take into account that the nearest object may be behind the player or not physically onscreen (i.e. a low distance to the player, but still not onscreen).

Also, it doesn’t take into account if something is between the player and the object (i.e. a wall of a house).

Also, why do you sort the nearestObj list while you’re adding to it? It would be more efficient to sort when you’re finished adding to it…?

And why do you think a ray cast isn’t a good idea?

Using a ray-cast should be fine in a 3D third-person game. In your example, you’d get the list of available, interact-able game objects, sort them by distance, and then loop through them to check to see if they’re onscreen and if a ray can get from the player to the object.

I took a break over the summer from programming, But I’m back. Okay so I have a 1st person game with a current system of a box colliding with other objects to detect looking, but if there are two items in-front of each-other it will detect them both, not the one in front… Or it will still detect objects even if there is an obstacle int eh way Eg- a wall.

I don’t want to use python, because I don’t know it well enough(All the BGE hook and such), but if it is the ONLY way to do it I will try… Logic bricks are preferred.

Screenshot of player rig:

How can I make other objects detect that ray collide with them? (otherwise how can I have that object carry out a task, when the play looks at it (and hit s E or something, But that bit is simple enough.))

i think it should be rather simple, I’m not really good at programming, but the rayCastTo function returns a game object, so if you have all your interact able objects with say a property called “canInteract” and you run the rayCastTo function when you hit like “E” on the keyboard, it would shoot the ray out and if it hits an object that has the property all you do is add it to a variable. something like obj = own.rayCastTo(Target,5,“canInteract”). then you are free to change whatever property you would like to the object.

So I guess in essence the objects don’t detect the ray is hitting them, we tell them that they are being hit.

I’m a noob at python, can you give me an example?

Sure, but be aware so am I lol, but this is a simple example. You should see 3 boxes in front of you, the farthest box is about the max distance you can interact with, if you use wasd to move to the left you should see a small plane, if its in the way a box it should stop you from interacting with a box

Attachments

example.blend (548 KB)

Thank you.

EDIT: I’m taking a look at your code, I’m starting to understand it a bit. So thanks again. :slight_smile: