Behavior API doesn't match documentation?

In the documentation the detach method on the Behavior interface receives the target as an argument much like the attach method but when using them the detach method no longer receives any arguments.

Personally I think passing the target in is a great idea. I really like the idea of behaviours and think it covers a lot of use cases for me but they might be a bit limited by this change.

Please provide a playground example illustrating the issue you found. It really helps in getting a quicker solution.

Sorry about that, I completely forgot: https://www.babylonjs-playground.com/#ZKNDF3#0

In the example you can see that the TS compiler detects there are no arguments for detach, but in the documentation there is: Behaviors - Babylon.js Documentation

It’s not a deal-breaker by any stretch but I do think it would be useful to have.

Guess you are right! If I understand the source code correct:

then detach() has no parameters!:dizzy_face:

Yes you are correct it is a mistake in the docs and I have submitted a PR

You do not need a parameter as the method you write for detach will give the targets.
[I am not that good with interfaces but as far as I understand it they give a structure that needs to be used when forming a class from the interface - I may well be wrong]

Here is an example of a constructed behavior.

https://github.com/BabylonJS/Babylon.js/blob/master/src/Behaviors/Meshes/pointerDragBehavior.ts

You probably know more about Typescript than I do so my advice may not be that good.

However I would ask what you are trying to do and whether writing your own behavior is the way to go :slightly_smiling_face:

1 Like

Yep! You can see them as a contract

Generally, the rule goes something like this:

  • Inheritance describes an is-a relationship.
  • Implementing an interface describes a can-do relationship.

Here is a little example for you because I just want to learn them too :relaxed:
(also as PG Babylon.js Playground)

interface IMoveable {
    speed: number;
    move(): void; 
}

abstract class Vehicle implements IMoveable {
    hasPassengers: boolean;
    hasTires: boolean;
    speed = 10;
    move(): void{
        console.log("Vehicle is moving with speed: " + this.speed);
    }
}

class Car extends Vehicle {
    hasTires = true;
    speed = 20;

    move(): void{
        console.log("Car is driving with speed: " + this.speed);
    }
}

class Plane extends Vehicle {
    hasTires = false;
    speed = 1000;

    move(): void{
        console.log("Plane is Fyling with speed: " + this.speed);
    }
}

class Human implements IMoveable {
    speed = 2;
        move(): void{
        console.log("Human is walking with speed: " + this.speed);
    }
}

Imagine you want your classes to have a move() method. In the example I have an abstract baseclass Vehicle which extends Car and Plane. The child classes are implenting their own move() because a Car is driving and a plane is flying.
Now you want to have a class called Human. Humans can also move() but are no Vehicles.

The solution is the use of interfaces. We describe what our classes can do!
The huge benefit is that you later can call them like this:

var movObjArray: Array<IMoveable> = new Array<IMoveable>(
    new Car(),
    new Plane(),
    new Human()
);

for(let i = 0; i < movObjArray.length; i++){
    movObjArray[i].move();
}

We don’t care anymore which specific type we have, we just care if our type implements the IMoveable Interface! So we can create a list of IMoveable-objects and just call the move()-method.

You can see it like some kind of multiple inheritance!

That said, I am still not good at pre-thinking how to design my code to make it as flexible like that…
Still need to refactor a lot and double write everything…maybe someone has some experience to share :sweat_smile::nerd_face:

Thank you very much :slightly_smiling_face:

I’m not entirely sure this is true, I ran it in JS and the target argument is still undefined. In the file you linked the detach() method still doesn’t take arguments. I worked around it by creating my own method that handles that, though it may not be that necessary.

That is a good question and I may not have a good answer, I just found that Babylon already has a very nice scene graph that sort of went to waste a bit when I was using a pure ECS library to handle my logic. Attaching behaviours to meshes seems like the best of both worlds in a way as you can have independent systems working on multiple meshes just like in an ECS but a bit more OOP focused and using only Babylon. Combine them with observables and you have a pretty powerful system I think.
Then again I could be totally wrong :grin: