In the three steps of the using a behavior class recipe, the two most likely programming mistakes are:
not specifying a scheduling bounds (correctly), and
not adding a behavior to the scene graph.
The intersection of the scheduling bounds of a behavior
with the activation volume of a view determines whether or not Java 3D even
considers the trigger stimulus for the behavior. Java 3D will not warn you of
a missing scheduling bounds - the behavior will never be triggered.
Also, keep the scheduling bounds of each behavior object as small as possible
for the best overall performance. As mentioned above, a behavior object that
is not part of the scene graph will be considered garbage and eliminated on
the next garbage collection cycle. This, too, will happen without error or warning.
Behaviors can be placed anywhere in the scene graph.
The issues in picking a scene graph location for a behavior object are 1) the
effect on the scheduling bounds, and 2) code maintenance.
The bounds object referenced by a behavior object is subject to the local coordinate
system of the behavior object's position in the scene graph. In the scene graph
created in SimpleBehaviorApp, the SimpleBehavior object and the ColorCube are
not subject to the same local coordinate system. In the example application
this does not create a problem. The TransformGroup object of the example only
rotates the ColorCube so that the scheduling bounds for the myRotationBehavior
object always encloses the ColorCube object allowing interaction with the ColorCube
when it is visible 2 .
However, if the TransformGroup object were used to translate the ColorCube object,
it would be possible to move the ColorCube out of the view. Since the bounds
object stays with the behavior object in this scene, the user would be able
to continue to translate the object. As long as the activation volume of a view
still intersects the scheduling bounds for the behavior, the behavior is still
active. Being able to interact with a visual object that is not in the view
is not bad (if that is what you want).
The problem lies in that if the view were to change such that the activation
volume no longer intersects the scheduling bounds of the behavior, even to include
the visual object, the behavior is inactive. So the visual object you want to
interact with may be in your view but not active.
Most users will consider this a problem (even if it is intentional).
There two solutions to this problem. One is to change
the scene graph to keep the scheduling bounds of the behavior with the visual
object.
The alternativesolution uses a BoundingLeaf object for the scheduling bounds.
Consult the Java 3D API Specification for information on the BoundingLeaf class.
The mechanics of writing a custom behavior are simple. However, you should be aware that a poorly written behavior can degrade rendering performance.
While there are other considerations in writing a behavior, two things to avoid are: memory burn and unnecessary trigger conditions.
'Memory burn' is the term for unnecessarily creating objects in Java. Excessive memory burn will cause garbage collections. Occasional pauses in rendering is typical of memory burn since during the garbage collection, the rendering will stop 45 . Behavior class methods are often responsible for creating memory burn problems. For example, in the last example, the processStimulus uses a 'new' in the invocation of wakeupOn (line 24). This causes a new object to be created each time the method is invoked. That object becomes garbage each time the behavior is triggered. Potential memory burn problems are normally easy to identify and avoid. Look for any use of 'new' in the code to find the source of memory burn problems. Whenever possible, replace the use of the new with code that reuses an object.
You will see it is possible to set a trigger condition that will wake a behavior every frame of the rendering. If there is nothing for the behavior to do, this is an unnecessary waste of processor power invoking the behavior's processStimulus method. Not to say that there isn't a good reason to trigger a behavior on every frame, just make sure you have the reason.