Third Person Camera

Do you know how I would disable the WASD controls during certain scenarios using that script? Like if I were to walk the character over to a door and tell her to open it, during the animation of her turning the knob and pushing it open I wouldn’t want to be able to make her move.

If you don’t know much about them yet, I recommend you do some reading on IF statements and programming basics. Once you know what they are and how to use them, I would recommend using a simple property that you can set on your character that enables it to move.

You probably already know how to use and set properties using Blender’s logic brick interface. Here’s a quick example on how to use them with Python:

import bge

# get the current game scene
scene = bge.logic.getCurrentScene()

# get the object in the scene named "Cube"
cube = scene.objects['Cube']

# object properties can be created, modified, and read
# by using [<property_name>] after the object

# this creates the property "myProp" on the cube and sets
# its value to 1 (or overwrites it if it already exists)
cube['myProp'] = 1

# add 5 to the existing property
cube['myProp'] += 5

# you can check the value of properties using if statements
if cube['myProp'] == 1:
    print('myProp is equal to 1')
else:
    print('myProp does not equal 1')

Whenever you start an animation, you can set your property to False. Then in your movement code, you might have a line that looks like this:

if obj['canMove']:
    # code that applies movement

This will ensure the movement code is only executed when it’s specifically allowed to. After the animation completes, you can set the property back to True to re-enable movement.

How could I make that over the shoulder look work like this:
If camera is looking at player from right then look over the right and if camera is looking from the left look over the left?

Replace lines 128-130 with this:

    viewVec = -own.worldOrientation.col[2].normalized()
    playerXVec = player.worldOrientation.col[0]
    dist = viewVec.dot(playerXVec)*HOR_OFFSET - own['LR']

If you want the offset to take effect even when the camera is looking up or down, use this instead:

    viewVec = -own.worldOrientation.col[2].to_2d().normalized()
    playerXVec = player.worldOrientation.col[0].to_2d()
    dist = viewVec.dot(playerXVec)*HOR_OFFSET - own['LR']

Thanks! It works well.

I noticed when i turn MIN_ANGLE to this
MIN_ANGLE = math.pi/3

The mouse rotation up and down is stopped.
I don`t want the mouse/camera to rotate up and down so this is good.

However now the angle is off and i cant seem to make it face dead on straight. I tired playing with z ofset and moving the focus point, but without moving mouse up and down it wont face the angle i want it too. It just looks slightly down :frowning:

In a nutshell can i change the mouse pos ? which i think is the reason this is happening or is it ?
Thanks again.

Replace 2*MIN_ANGLE with just MIN_ANGLE in lines 122-123. Set MIN_ANGLE to math.pi / 2 (which should now correctly correspond with looking straight ahead).

Thank you so much

Hey there Mobious, first of all I wish to thank you for this awesome script, it’s been doing wonders to my project.
Second, I’d like to ask you help with an issue I found. So far I could manage to fix all of them by my own, with the due research and effort, but I lost quite some time on that one already and I don’t seem to be close to the solution.
To be quick about it: I want to disable the “bge.render.setMousePosition(xpos,ypos)” line when the player enters a puzzle interface, so he can grab and move items freely. I tried to add a conditional “if scene.active_camera == own” so that it only centers the cursor when the player’s camera is the active one, but that doesn’t seem to “kind of” fix the issue. Basically it do works, but not as expected: when the active camera is the player’s one it centers the mouse and doesn’t allow it to roam away of the center, which is ok, but when the active camera is the one of the puzzle interface it let you move the mouse for one second or so and then it centers the mouse back. There is only a difference of delay between those two situations, but the mouse keeps being centered on the screen.
I’m using your script for quite a while now and I understand it rather well, just not the deep vector and angle code stuff.
To conclude: besides this specific “bge.render.setMousePosition(xpos,ypos)” line, is there another part of the script that needs changes in order to deactivate the mouse centering when there’s another active camera?
Thanks in advance.

There isn’t anything else you should need to disable (though you may want to disable the rest of the script as well, otherwise the camera will continue to move as you move the mouse even though it’s not currently active). I tested the script as you described with the exact conditional statement and it worked fine: the mouse was free to move around and did not return to the center while a different camera was active. I can only assume something else in your game is periodically reactivating the 3rd person camera causing the mouse to be re-centered again. Maybe you can post a simplified .blend file demonstrating the problem.

Man you’re my hero. I thought about what you said (something reactivating the camera) and realized it would be much better if I suspended the whole main scene when there’s a interface on. That took care of the problem. I don’t know why I didn’t thought about it earlier as I did that already with the menu interface, but well, sooner better than later I guess. Just to mention I think I have something else centering my mouse on the screen on the main scene, 'cause I even deleted the line we discussed about and it kept centering it, so I guess it’s time I do some good review on the scripts I’m using to see if I didn’t run over something.
Anyways thank you again for your help and for this great script. Keep up your great work. Cheers from Brazil!

Hey there again Mobious, if you have time I’d like to ask for your help again. My character is obstructing a bit the view of the player, so I’d like to make it in a way so that the camera have a little horizontal offset at max distance and would rise it along the zooming until a larger amount at the min distance. Is there a way to put that horizontal offset on the max distance and make it rise progressively to the end?
Thank you again!

You’ll need to change a few things, but it’s doable.

  1. Add these constants to the top of the script. You can change MIN_HOR_OFFSET and MAX_HOR_OFFSET to be whatever you’d like.
MIN_HOR_OFFSET = 3.0  # horizontal offset when the camera is zoomed all the way out
MAX_HOR_OFFSET = 6.0  # horizontal offset when the camera is zoomed all the way in
  1. In the “initialize vars” block, set own[‘LR’] = MIN_HOR_OFFSET instead of the old HOR_OFFSET constant (you can remove this constant while you’re at it since it will no longer be used)

  2. Replace the code in the “LR toggling and smoothing” block with this:

    # LR toggling and smoothing
    if keys[ToggleLR] == 1:
        own['LRinv'] *= -1
    distScale = 1.0 - (own['dist'] - MIN_DIST) / (MAX_DIST - MIN_DIST)
    horShift = own['LRinv'] * ((MAX_HOR_OFFSET - MIN_HOR_OFFSET) * distScale**2 + MIN_HOR_OFFSET)
    own['LR'] = own['LR'] + (horShift - own['LR']) / LRSMOOTH
    dist = own['LR']

Sweeet
I owe you a lot Mobious, it works tip-top, just the way I wanted.
I’ll keep the old HOR_OFFSET constant in case I want to go back to the previous setting or implement it on another feat.
You’re really great man, thank you for your help. Hope I don’t need to annoy you again hahaha

Ermm i dont know if this has been asked but here it goes. Why dont this script work if it`s linked ? i have it grouped to my female setup, but when
i link it to a new scene it no longer works. Work around ?

Only work around i found is too not have my female grouped and just keep it in the scene.
This is okay, but as i want everything optimized in my game, it`s best to have everything in separate files.

Any help is appreciated.

Can you describe exactly what isn’t working? Are there any errors in the console? A more detailed description of your setup would be helpful.

Make sure you’ve also linked the “3rdPersonCamera.py” script. You may also need to set the linked camera to be the active camera after the game has started.

Hello Mobious! I’ve been messing around with your script lately (again) and I came to some problems understanding it. Could you explain to me what’s the difference between the variables own[“dist”] and own[“zoom”]?
Also, if I wanted to set the camera position according to a wall’s surface (aligning it’s axis as well) which variables should I look for to change accordingly? I know that in the case of the axis it’s the vec variable at the end of the script, but I can’t figure the whole position math of it.
I’d really appreciate if you could give me some directions on those variables, so I can keep working on it and maybe get somewhere.
Thanks!

“zoom” is the current desired distance from the player to the camera controlled by the mouse wheel, while “dist” is the actual distance from the player to the camera. They are separate so that the camera can smoothly zoom in and out (rather than just instantaneously jumping to the new position) and so that the camera can move back to the desired zoom level after it has been forced to move (due to camera collisions).

I’m not sure exactly what you’re asking regarding setting the camera’s position based on a wall. Can you maybe provide a diagram of what you’re trying to achieve? The other main properties that control the camera are own[“x”] and own[“y”]. “x” is the angle the camera is facing the in horizontal plane relative to the positive y-axis, while “y” is the angle the camera is facing in the vertical plane relative to the negative z-axis.

Thanks Mobious!
I’m facing a problem regarding the camera going through walls. Currently I’ve put another 2 rays on it, for left and right angles, and made the camera zoom in when the player gets near to walls, also making it toggle the side of the horizontal offset if the wall is on the same side of it. It’s still buggy on too narrow halls so I’m avoiding that. But now, I still didn’t figure out why, the camera is rotating in an odd way around the global Z axis, like in an elliptical orbit. Would you have any clues on that? I thought maybe the horizontal offset could be it, but no changes I made helped. I’m fiddling on the “# calculate and set new camera position” section for now.

EDIT: Never mind, I found the odd movement of the camera happened due to the object I defined as the player, somehow it was circling around the physics object instead of just copying it’s transformation (they were parented, so I don’t know what happened). I solved this by defining the own physics object as the player.

With the current setup, there’s no way to fully prevent the camera from clipping through walls since the collision detection logic only moves the camera closer to the player. To achieve what you want, you’d need the camera to actually navigate around obstacles which would take a bit more work to implement.

You can currently reduce the FSMOOTH constant to 1 (so that there is no forward obstacle smoothing) so the camera spends less time moving through obstacles.