track to nearest property axis

How would i track to the nearest property in all axises?

How would i track to the nearest property in all axises using the always sensor?

The API:
http://coredoc.royalwebhosting.net/api/utils.html#core.utils.getNearestObject

I would post the code, but github is down and I don’t feel like rewriting it.

# always -> python-module->script_name.track-> edit object - track_to# and a property "track_distance" on the object using this script
# and place a property on the objects you want to track to: called track_to




def track(cont):
    
    own         = cont.owner
    scene       = own.scene    
    track_to    = cont.actuators['track_to']
    
    ai = [obj for obj in scene.objects if 'track_to' in obj]
    
    if ai:
        
        closest_ai      = sorted(ai, key=lambda enemy: own.getDistanceTo(enemy))[0]    
        distance        = own.getDistanceTo(closest_ai) 
        max_distance    = own['track_distance'] 
        
        if distance <= max_distance:


            track_to.object = closest_ai
            cont.activate(track_to)
        
        else:
            cont.deactivate(track_to)

track_to_closest.blend (942 KB)

2 Likes

A track to nearest property script like this is to be used with npc’s that can jump with me.Following the player as i dig upwards.

To be honest, I can’t imagine how you can track a property, or how you can determine a positional order.

Could it be you mean an object that has a property with a certain name?

Yes it does.

in that case I suggest to split the opertions:

A) find the closest object
B) track it

finding the closest object needs python. You can iterate over a set of candidates (usually the active objects of the scene).


for object in scene.objects:

Ignore the objects that do not match the criteria.


for object in scene.objects:
    if propertyName not in object:
        continue

If the remaining object is closer then any already investigated object, remember that object


referenceObject = ...
propertyName = ...

closestObject = None
closestDistance = None
for object in scene.objects:
    if propertyName not in object:
        continue
    distance = referenceObject.distanceTo(object)
    if closestDistance is None or 
       distance < closestDistance:
        closestDistance = distance
        closestObject = object

print( closestObject, "is the one")

The resulting object is ether None (nothing found) or the object with the closest distance. In case of multiple closest distances it is any of that objects.

Track to nearest property of a object scripts seem to work really well in openworld videogames.Where you end cubes and build on top of cubes.That is why i would like to use it to make npc’s and enemies jump.I was trying to use a track to nearest property of a object script along with disabling of and enabling dynamic.But i could not get it to work yet?

There is no relation between finding objects and “openworld”.

Ending cubes and ading cubes has a sight relation as the obvious question is “what cube to delete?” and “where to create the what cube?”.

Jumping npc’s and enemies do not need cubes or near objects to jump. Jumping is an operation. The question is “when and how strong to jump?”.

Tracking within the BGE usually means that an object points to into a specific direction (typically another object). As said earlier you can’t point to a property. This is like talking to your friends name. You talk to your friend (the person) not to it’s name or color etc… Please be a bit more precise otherwise I can’t understand what you want to do and any help would lead you to something you do not want.

In that topic I do not see how disabling and enabling dynamics fits into your situation.

I have the impression you mix a lot of different (and often unrelated things) together. This makes it really hard to provide any help.

So here is what I interpret from the above statements:

  • you want a large scene (-> open world = large scene) typically with a lot of objects in it
  • this world has a lot of cubes (similar to minecraft) this means there are really many cubes
  • you want to add and remove cubes on the fly -> as mentioned above: what cubes when?
  • you have NPC’s
  • you want that NPC’s can jump - do they already or do you not know how?
  • you want to find certain objects (by distance and property - see post#8) to enable and disable dynamics. Is that the problem you currently have?

What i am doing is having a npc follow a line of instanced cubes with a particular property.When the npc bumps into them and the collision sensor is triggered that cube is ended.Then the npc goes to the next.For jumping i was thinking about doing the same thing.But i think i should add a cube with two properties one that can be used to track to the cube it is on and one that would trigger the jump when it is ended.I would add this cube when i press the jump button.Which is the space bar.Detection of this cubes property could be used to disable dynamics.And a plane parented to the player with property could be used to enable dynamics.My problem is implementation.

It sounds like you are aiming for path-following. The cubes are acting as waypoints while the character knows how to move a near waypoint (jump or move).

I do not think the method you think about is a good one. It is like a breadcrup trail. That in general is not bad, has some weaknesses:

  • you need quite a lot of objects
  • hard to distinguish between different trails
  • just one character can follow a single trail as it gets destroyed while following
  • you need something else to create the path
  • real-time changes to the paths are hard to manage (e.g. when there is a new obstacle that can’t be crossed).
  • you move the “intelligence” away from the single character (thumb NPC)

There are several different things you can change:

  • a path is known to the single character only (e.g. it can be stored in a property of the character). Other characters have other paths
  • a path consists of an ordered sequence of steps. This allows to determine the next step when you know the current step.
  • a step is an operation that continues one item on the path. The character needs to be able to perform this operation from the current status (e.g. move from current position to a certain position, jump from current position to next position, limb … open door …).
  • Some steps might have certain requirements before they can be executed (e.g. the character needs to face a certain direction and stays at a Certain spot). This means all previous steps have to result in exactly that situation. Otherwise the step can’t be performed correctly.
  • The next step does not need to be known before as long as it is known when needed (the current step completed).
  • you might need verification that steps can be performed (by checking the requirements). If the step can’t be performed the path-following needs to end. A new pathfinding + pathfollowing might be necessary.

You also need path-finding. Path finding means determine a path with the steps that the character ends in a certain situation (or achieves a certain goal).

Just now it seams you want to predefine the path by manually adding some “waypoint” objects the character should follow in a certain order.

This is not bad, but why removing the objects? When you leave them there the character can use it as as input again and again. even several different characters might be able to use it as input.

The waypoint objects can represent a specific location to reach (and/or a specific orientation). The waypoints need a specific order (e.g. via property value).

I suggest you create a path in Python e.g. as a list. Be aware you need a specific order (e.g. by name or by property value …).

“pathfinding”


import bge 


scene = bge.logic.getCurrentScene()
waypoints = [object for object in scene.objects if "waypoint" in object] # list of all waypoints (not ordered in right way)
path = sorted(waypoints, key=lambda object: object.name)

print("waypoints:", waypoints)
print("path     :", path)

character = bge.logic.getCurrentController().owner
character["path"] = path



can result in


waypoints: [Waypoint.005, Waypoint.004, Waypoint.003, Waypoint.002, Waypoint.001, Waypoint.000]
path     : [Waypoint.000, Waypoint.001, Waypoint.002, Waypoint.003, Waypoint.004, Waypoint.005]

Be aware this is just a very primitive example of pathfinding (= pathcreating).

now the path following:

Lets assume each step of the path can be performed by turning to the next location and move straight forward until reaching being near that location.

Similar to your idea you just need an object at the next step location, then turn to that object and move forward until collision with that object. [Be aware you will not reach the exact position as the collision will be before!]

You do not need many objects, just one. When colliding the current step is don and the next step can start. So you simple place the target object to the position of the next step. This just needs a little bit of Python for placing the target object:
“nextStep”


import bge


controller = bge.logic.getCurrentController()
    
if (controller.sensors["hit target"].positive or 
    controller.sensors["start following"].positive):
    
    character = bge.logic.getCurrentController().owner
    path = character["path"] 
    
    trackToTargetActuator = controller.actuators["track Target"]
    trackToTargetActuator = controller.actuators["track Target"]
    
    if not path:
        controller.deactivate(trackToTargetActuator)
        controller.deactivate("move forward")
        print("End of path reached")
    else:   
        waypoint = path.pop(0)
        
        targetHolder = trackToTargetActuator
        target = targetHolder.object
        
        target.worldPosition = waypoint.worldPosition
        
        controller.activate(trackToTargetActuator)
        controller.activate("move forward")
        print("Next waypoint is", waypoint, "remaining waypoints:", path)
    

You need an always sensor (no level triggering, but TAP, name see in code).
You need a collision sensor sensing the target object (no level triggering, name see in code).
You need an edit object actuator in trackTo mode tracking the target object (name see in code).
You need an motion actuator that moves the object along the tracking axis (name see in code).

Be aware the “pathfinding” needs to run before “nexStep”, otherwise nextStep will not do anything.

You can follow the path as often as you like as long as pathfinding runs before pathfollowing. This is as the current path shrinks while following. So you need to ceate a new one.

Will that work with digging videogames similar to minecraft?Because that is the type of videogame i am making.Have you tested it?

What I describe has nothing to do with digging. It is a bout path-following.

Sorry for not telling you but that was what this whole question was about.

So what you want to achieve is that characters are digging through the ground?

So all of this just for a raycast…

I mean path following in a minecraft type videogame.

There is no path following in minecraft. If you mean when zombies follow you, that’s just a raycast and a distance check, if you mean the rails, it just checks the direction of the rail under you and the current speed, and applies some constrains, that’s all there is to it.

I have never played minecraft.What i want the npcs to do is follow my player character everywhere he jumps,digs and walks.
It maybe more sophisticated than minecraft ai.