How to copy player location to other object in Real Time?

I have a game with multiple players (Tanks, Car, Heli and the player.) I can easly switch my view and the keys controls from one to the other. But the sun is parented to a player vertex. When I transfer the player controls over to the tank the sun is left attached to the player. My view is now from the tank and as I drive away I leave the shadow box that is still attached to the player.
I thought that instead of parenting the sun to the player it might be better to copy the player location. Then when I change the view and controls over to the tank I could tell it to now copy the tank location.
Does anybody have a script that accomplish this in real time?
Or is there a better way to handle it altogether?

requires property ‘Target’ = A String that is the name of the object to target or it can be set directly as a game object reference.

import bge

cont = bge.logic.getCurrentController()
own = cont.owner

if type(own['Target']) is str:
    target = own['Target'] 
    if target in own.scene.objects:
        own['Target'] = own.scene.objects[target]
        print(target+' was not found in this scene')

elif type(own['Target']) is bge.types.KX_GameObject:
    if not own['Target'].invalid:  
        own.worldPosition = target.worldPosition
         print('target no longer exists')

type(own['Target']) is bge.types.KX_GameObject

# should be

isinstance(own['Target'], bge.types.KX_GameObject)

Because you could want to follow things like armatures, or any other subclass of gameobjects (its more general).

Code a bit more verbose, based on BPR’s (in module mode this time)

import bge

def copy_location(controller):
    owner = controller.owner

    # get the name string in the gameproperty ""
    target_name = owner.get('', None)

    if target_name is None:
        return # stop function execution if nothing to do

    # fetch the targeted object from the scene
    target_object = owner.scene.get(target_name, None)

    # check if the object was in the scene
    if target_object is None:
        del owner['']
        raise ReferenceException('no such object in the scene: ' + target_name)

    owner.worldPosition = target_object.worldPosition

This does not use a cache, but it may be simplier if you are starting. You can try to understand what is happening here :slight_smile:

You could wonder where to execute this script too ?

It depends on the approach. The above script can be run on each frame, it will constantly update the position of “owner” to the position of its “target”.

A second approach would be to have a function, say “set_location” where you can specify a target, and it will move the object to its target, and then parent the owner to its target. This way if the owner is your object as a vertex parent, you can let Blender parenting system do all the work and forget about moving something on each frame.

use on the sunlamp:

import bge

scene = bge.logic.getCurrentScene()
owner = bge.logic.getCurrentController().owner

owner.worldPosition = scene.active_camera.woldPosition.copy()

now the sun follows the camera, no matter how many times its changed.

NOTE: sunlamp should not be a child of any object.

Thanks everybody- I will try all the above solutions. Wonderful responses from the forum as usual.

I suggest following:

  • Have an object with a mesh with one vertex. Call it “base”.
  • Add the lamp via vertex parent to this one vertex
  • Parent base to the player object (normal parent)

In game you can assign any parent to base as you like.

I am curious as to why? Have I been doing something wrong all this time? Does it adversely impact performance…??? I have not even done any tests regarding this.

if you are going to use the active camera, its often better to add an offset to the sun, so that shadows can start from above your head (else you will have shadows below the view but not above)

import bge

scene = bge.logic.getCurrentScene()
owner = bge.logic.getCurrentController().owner
distance = 32

owner.worldPosition = scene.active_camera.woldPosition + owner.getAxisVect((0, 0, distance))

thanks for pointing that out WKnight02, i forgot to mention that i parent the sun to an empty, move the sun up along the local Z, then rotate the empty for sun angle. attach the script to the empty.

the reason the object running the script shouldnt be a child is that its not necessary. the point of the script is to place the object at a location in the scene. if it had a parent, then 2 things would be telling it where to go each frame, which is a total waste.

oh…well yes…I was referring to it in a completely different manner that had nothing to do with the code…ok…please ignore my previous question. :slight_smile: