Difference between revisions of "Modular Pathfinding Kit"

From Second Life Wiki
Jump to navigation Jump to search
m
(major content addition)
Line 5: Line 5:
     2. mixing physics and pathfinding (for instance using llApplyImpulse with a pathfinding character)
     2. mixing physics and pathfinding (for instance using llApplyImpulse with a pathfinding character)


This guide has two paths:
=Quick Guide=
 
> object + pathfinding character skeleton + behavioural tropes = autonomous pathfinding creature
 
This guide gives quick guidance of how to create specific behavioural tropes (commonly found autonomous characteristics) and doesn't go into detail about individual functions - see [[Pathfinding LSL Functions]] for more details.
 
=Components=
 
==pathfinding character skeleton==
 
<lsl>
doSomething()
{
//insert pathfinding functionality here
}
 
default
{
startup() //called as necessary from events such as script reset or rezzing
{
llCreateCharacter([CHARACTER_MAX_SPEED, 25, CHARACTER_DESIRED_SPEED, 15.0]); //create the character
doSomething();
}
state_entry() //standard event, called when the script resets
{
startup();
}
on_rez() //good to include so it scuttles off when rezzed from inventory or a rezzer
{
startup();
}
}
</lsl>
==Behavioural Tropes==
 
===flying/hovering===
3D spatial free flight is at present unavailable. We can however fake it but one of the following methods:
 
# create a small object with a tall root prim - not recommended, causes excessive collisions
# create a small object and create a large character envelope - recommended
 
The example below creates a character with a 1.5m tall and 0.25m wide envelope. If the object itself if 0.25 it will appear to be "flying", or, more accurately, hovering.
 
<lsl>
llCreateCharacter([CHARACTER_MAX_SPEED, 25, CHARACTER_DESIRED_SPEED, 15.0, CHARACTER_RADIUS, 0.25, CHARACTER_LENGTH, 1.5]);
</lsl>
 
In order to further the illusion of flying we can do a number of things. If the creature is something that works at near ground height, such as a hummingbird or dragonfly just use one of the movement tropes, such as wandering.
 
If you want the creature to fly higher than the 10.0m maximum character height (which will give a centre of mass height of 5.0m), we can use a platform. If you want a parrot to fly between trees place a prim or series of prims that stretch between them and use something like [[llPatrolPoints]] or [[llWanderWithin]]. Even if you use a series of narrow pathways the pathfinding will find a way to valid targets.
 
We can make a really nice effect by using a mesh surface with an undulating form - the creature will follow the dips and rises giving the appearance of varying flight.
 
For ground hugging creatures we can something similar that looks natural for hovering creatures by dynamically changing the envelope size of the creature by calling [[llUpdateCharacter]], as below. Call this function repeatedly with different values and the character will change the level it hovers at.
 
<lsl>
llUpdateCharacter(CHARACTER_LENGTH, 6.5);
</lsl>
 
===fleeing===
 
There are two distinct behaviours we can exploit. If we wanted a character to run from a specific point such as an explosion we can use [[llFleeFrom]]. If we want to run from a specific object or agent (avatar) use [[llEvade]]
 
===hiding===
 
Part of [[llEvade]] is hiding (blocked line of sight) from the agent/object the character is fleeing from. See [[llEvade]] for more details.
 
===move-wait-repeat===
 
By responding to path events we can create varying behaviour. All pathfinding functions are moving to specific targe coordinates, whether determined randomly by something like [[llWanderWithin]], specific as in [[llPatrolPoints]] or even [[llPursue]].
 
Have a look at [[Path update]] for guidance, and see the example script in the multiple states discussion at the end of this article.
 
===chase===
 
Use [[llPursue]] and specify a target object or avatar.
 
===hunt===
 
Use a sensor of some description, such as [[llSensorRepeat]] or some sort of collision detection such [[llVolumeDetect]]
 
===wait===
 
To make a character pause you can use a state change with a new event trigger making the character active again, or simply use something like:
 
<lsl>
llExecCharacterCmd([CHARACTER_CMD_STOP]);
llSleep(15.0);
llWanderWithin(llGetPos(), <10.0, 10.0, 5.0>, []); //resume with any desired pathfinding function
</lsl>
 
It's a personal preference but generally speaking state changes are easier to manage and debug.
 
===wandering===
 
Use [[llWanderWithin]] to specify an area to wander within.
 
==Optional Extras==
 
To add to immersion it's worth adding some extras. If desired add...
 
===animation===
see [[Animation Streamlined]] for tips
 
 
===sounds===
see [[Creature Sounds]] and [[Event Driven Sounds]]
 
===more than one state===
 
States are an excellent way of managing pathfinding creatures, but note however that pathfinding behaviour survives state changes - it's simple a simpler way of managing a status than using a variable. See the example below, which simulates a rabbit grazing.
 
<lsl>
animateGrassEating()
{
//insert a cunning grass eating animation here
}
 
animateTailWiggle()
{
//insert very cute tail wiggle animation here
}
 
default
{
startup() //called as necessary from events such as script reset or rezzing
{
llCreateCharacter([CHARACTER_MAX_SPEED, 2, CHARACTER_DESIRED_SPEED, 1.0]); //create the character
state wander;
}
state_entry() //standard event, called when the script resets
{
startup();
}
on_rez() //good to include so it scuttles off when rezzed from inventory or a rezzer
{
startup();
}
}
 
state wander
{
state_entry()
{
llWanderWithin(llGetPos(), <10.0, 10.0, 5.0>, []);
}
path_update(integer type, list reserved)
{
if (type == PU_SLOWDOWN_DISTANCE_REACHED)
{
//we're near the goal, we need to switch behaviour
llExecCharacterCmd([CHARACTER_CMD_SMOOTH_STOP]);
state graze;
}
}
}
 
state graze
{
state_entry()
{
animateGrassEating();
llSetTimerEvent(15.0);
}
timer()
{
llSetTimerEvent(0);
animateTailWiggle();
state wander;
}
}
</lsl>


# [[Modular Pathfinding Quick Reference|Quick Reference]] - a quick guide
# [[Modular Pathfinding Detailed Guide|Detailed Guide]] - a through look at pathfinding scripting theory


----
----
Return to [[Good_Building_Practices]]
Return to [[Good_Building_Practices]]

Revision as of 21:59, 8 July 2012

There is a lot of options for how to create pathfinding creatures. It’s best to start by having an idea of what you want to create, either a real world analogue like a horse or a dog, or something mythical such as a ghost or fairy.

things that don’t work (at present):
   1. 3D spatial movement - for example underwater free movement or aerial free movement
   2. mixing physics and pathfinding (for instance using llApplyImpulse with a pathfinding character)

Quick Guide

> object + pathfinding character skeleton + behavioural tropes = autonomous pathfinding creature

This guide gives quick guidance of how to create specific behavioural tropes (commonly found autonomous characteristics) and doesn't go into detail about individual functions - see Pathfinding LSL Functions for more details.

Components

pathfinding character skeleton

<lsl> doSomething() { //insert pathfinding functionality here }

default { startup() //called as necessary from events such as script reset or rezzing { llCreateCharacter([CHARACTER_MAX_SPEED, 25, CHARACTER_DESIRED_SPEED, 15.0]); //create the character doSomething(); }

state_entry() //standard event, called when the script resets { startup(); }

on_rez() //good to include so it scuttles off when rezzed from inventory or a rezzer { startup(); } } </lsl>

Behavioural Tropes

flying/hovering

3D spatial free flight is at present unavailable. We can however fake it but one of the following methods:

  1. create a small object with a tall root prim - not recommended, causes excessive collisions
  2. create a small object and create a large character envelope - recommended

The example below creates a character with a 1.5m tall and 0.25m wide envelope. If the object itself if 0.25 it will appear to be "flying", or, more accurately, hovering.

<lsl> llCreateCharacter([CHARACTER_MAX_SPEED, 25, CHARACTER_DESIRED_SPEED, 15.0, CHARACTER_RADIUS, 0.25, CHARACTER_LENGTH, 1.5]); </lsl>

In order to further the illusion of flying we can do a number of things. If the creature is something that works at near ground height, such as a hummingbird or dragonfly just use one of the movement tropes, such as wandering.

If you want the creature to fly higher than the 10.0m maximum character height (which will give a centre of mass height of 5.0m), we can use a platform. If you want a parrot to fly between trees place a prim or series of prims that stretch between them and use something like llPatrolPoints or llWanderWithin. Even if you use a series of narrow pathways the pathfinding will find a way to valid targets.

We can make a really nice effect by using a mesh surface with an undulating form - the creature will follow the dips and rises giving the appearance of varying flight.

For ground hugging creatures we can something similar that looks natural for hovering creatures by dynamically changing the envelope size of the creature by calling llUpdateCharacter, as below. Call this function repeatedly with different values and the character will change the level it hovers at.

<lsl> llUpdateCharacter(CHARACTER_LENGTH, 6.5); </lsl>

fleeing

There are two distinct behaviours we can exploit. If we wanted a character to run from a specific point such as an explosion we can use llFleeFrom. If we want to run from a specific object or agent (avatar) use llEvade

hiding

Part of llEvade is hiding (blocked line of sight) from the agent/object the character is fleeing from. See llEvade for more details.

move-wait-repeat

By responding to path events we can create varying behaviour. All pathfinding functions are moving to specific targe coordinates, whether determined randomly by something like llWanderWithin, specific as in llPatrolPoints or even llPursue.

Have a look at Path update for guidance, and see the example script in the multiple states discussion at the end of this article.

chase

Use llPursue and specify a target object or avatar.

hunt

Use a sensor of some description, such as llSensorRepeat or some sort of collision detection such llVolumeDetect

wait

To make a character pause you can use a state change with a new event trigger making the character active again, or simply use something like:

<lsl> llExecCharacterCmd([CHARACTER_CMD_STOP]); llSleep(15.0); llWanderWithin(llGetPos(), <10.0, 10.0, 5.0>, []); //resume with any desired pathfinding function </lsl>

It's a personal preference but generally speaking state changes are easier to manage and debug.

wandering

Use llWanderWithin to specify an area to wander within.

Optional Extras

To add to immersion it's worth adding some extras. If desired add...

animation

see Animation Streamlined for tips


sounds

see Creature Sounds and Event Driven Sounds

more than one state

States are an excellent way of managing pathfinding creatures, but note however that pathfinding behaviour survives state changes - it's simple a simpler way of managing a status than using a variable. See the example below, which simulates a rabbit grazing.

<lsl> animateGrassEating() { //insert a cunning grass eating animation here }

animateTailWiggle() { //insert very cute tail wiggle animation here }

default { startup() //called as necessary from events such as script reset or rezzing { llCreateCharacter([CHARACTER_MAX_SPEED, 2, CHARACTER_DESIRED_SPEED, 1.0]); //create the character state wander; }

state_entry() //standard event, called when the script resets { startup(); }

on_rez() //good to include so it scuttles off when rezzed from inventory or a rezzer { startup(); } }

state wander { state_entry() { llWanderWithin(llGetPos(), <10.0, 10.0, 5.0>, []); }

path_update(integer type, list reserved) { if (type == PU_SLOWDOWN_DISTANCE_REACHED) { //we're near the goal, we need to switch behaviour llExecCharacterCmd([CHARACTER_CMD_SMOOTH_STOP]); state graze; } } }

state graze { state_entry() { animateGrassEating(); llSetTimerEvent(15.0); }

timer() { llSetTimerEvent(0); animateTailWiggle(); state wander; } } </lsl>



Return to Good_Building_Practices