Unique Conditions for Each Clone and Instance

Hello everyone,

In the PG below, grey boxes move around looking for “food,” which are the yellow boxes.

https://www.babylonjs-playground.com/#UPRU8R

I’ve been able to create certain game mechanics for individual meshes, but I’m not sure how to apply these to the clones (grey boxes) and instances (yellow boxes).

  1. Each grey box starts with 100 health, and loses it steadily over time (example 10 seconds).

  2. When a grey box and a yellow box collide, that grey box’s health resets to 100, and the yellow food box disappears.

  3. If a grey box does not collide with a yellow box within 10 seconds, the grey box disappears.

Again, I’m not having trouble creating these mechanics for individual meshes (i.e. “box” and “food”), but rather for all the other clones and instances (i.e. “box24” and “food116”).

Any help or suggestions would be greatly appreciated :smiley: :+1:

why not storing the info in mesh.metadata ? it is a free bag you can use for any of your custom needs ???

So each mesh/instance could store its health and time until die and it would then be easy to iterate through them ?

Hello @sebavan,

I have no idea what mesh.metadata is, but it sounds like a great solution! Hopefully I can find documentation or examples of how to implement this.

However, even if I can get each instance or clone to store metadata, I still can’t figure out how to get hundreds of different meshes all with unique names to recognize each other (i.e. an intersection).

For instance, in the code below, when I reference ALL of the 200 food instances from the foodArray (foodArray[i]), the scene crashes :thinking: However, this code works if I check for an intersection with just a single instance (replace foodArray[i] with just “food”).

scene.registerBeforeRender(function () {

    for (var i = 0; i < 200; i++) {

    if (cloneArray[i].intersectsMesh(foodArray[i], false)) {
        cloneArray[i].material.diffuseColor = new BABYLON.Color3(1, 0, 0);
    }else{
        cloneArray[i].material.diffuseColor = new BABYLON.Color3(0, 1, 0);
    }

    }
});

metadata is just a json object you can use as you want completely untyped.

About your issue maybe @Cedric or @RaananW have a proposal ???

Thanks again for the help @sebavan!

I’m still unable to solve this problem unfortunately, so I’m going to try and simplify the question below for anyone who might know the solution.

How can two objects from different arrays detect an intersection when their specific ID is not known by the user? Example: “box12” and “food143” (named when created: (“box” + index), and (“food” + index)).

Have you ever thought about the Solid Particle System https://doc.babylonjs.com/How_To/Solid_Particles

There are snippets looking at multiple collisions with SPS Babylon.js Documentation

Without a playground I cannot work out why it crashes but with the code you show

registerBeforeRender(function () {

Copy to clipboard


    for (var i = 0; i < 200; i++) {

    if (cloneArray[i].intersectsMesh(foodArray[i], false)) {
        cloneArray[i].material.diffuseColor = new BABYLON.Color3(1, 0, 0);
    }else{
        cloneArray[i].material.diffuseColor = new BABYLON.Color3(0, 1, 0);
    }

    }
});

each cloneArray will only be checked against the one entry in the foodArray, the one with the same index. For any in the cloneArray to be checked against any in the foodArray you need two loops with i and j and check

clineArray[i] against foodArray[j]

Hello @JohnK! Thanks for taking a look at this!

I was actually able to get things working with the code below. I will definitely investigate the SPS, as it might be a better option for my project in the long run. Does the SPS offer any advantages over using instances? I’ve only been programming for a month, so I’m not sure if what I wrote below is the best solution, but it works! :thinking:

    for (var i = 0; i < cloneArray.length; i++) {

    cloneArray[i].actionManager = new BABYLON.ActionManager(scene);
    foodArray.forEach((food) => {
        
        
        cloneArray[i].actionManager.registerAction(
    new BABYLON.ExecuteCodeAction(
        {
        trigger:BABYLON.ActionManager.OnIntersectionEnterTrigger,
        parameter:food
        }, 
        function(){
            food.dispose();
        }
    )
);
        
        });
      }

Hello again @JohnK,

I just realized that there actually is one element of the code above that is not 100%. I’m unable to get both the “food” and the cloneArray[i] mesh to disappear.

I’ve tried the following:

 function(){
        food.dispose();
        cloneArray[i].dispose();
    }

If it’s not obvious and a PG is needed, just let me know.

Thanks again!

Here’s the PG :smiley: :+1:
https://www.babylonjs-playground.com/#2CHIX4

Interesting project so played around a bit. Here’s my version of food removal https://www.babylonjs-playground.com/#2CHIX4#1

Also added predator removal using a metadata and a set time https://www.babylonjs-playground.com/#2CHIX4#2 see lines 73, 74 and 167 to 171 and 183

lines 73, 74 could just have been cloneB.lifeTimeRemaining = 60 * 1000; I believe the advantage of using metadata is that Babylon.js picks the metadata property up when the mesh is exported and serializes it.

2 Likes

Thanks for the updates to the code! Someone else also mentioned that metadata would be useful for this project, but I couldn’t at the time find any examples, so it’s really helpful that you added it. When I researched it, it seemed like metadata was something that got imported along with a mesh, or was contained in a separate file. It seems like metadata will help me accomplish the most important part of this project, which is to have randomly-generated creatures with various traits that can change over time.

When the creatures (grey boxes for now) move around, they will continuously lose energy. It looks like you set this up with lifeTimeRemaining (60 seconds). This is perfect because I had no idea how to accomplish this. Now, I’ll see if I can reset that 60-second clock for each individual creature when it intersects with a food item.

The most challenging part of this project (I think :thinking:), will be the digital DNA element involving the inheritance of metadata. I don’t even know if this will be possible, but I hope so!

For instance:

Creature 1: metadata trait A = 1, metadata trait B = 2

Creature 2: metadata trait A = 3, metadata trait B = 4

When they intersect (reproduce) “offspring” with random trait values:

Offspring creature: metadata trait A = (1 or 3), metadata trait B = (2 or 4)

Thank you again @JohnK for the help and suggestions! :smiley: :+1:

1 Like

This should be straightforward to do on intersection.
It could be interesting to vary the life time for each predator and for each food item to be of varying size and add an amount of life when eaten proportional to its size.

I actually made some progress with that today:
https://www.babylonjs-playground.com/#2CHIX4#3

I randomized their speed and made that inversely proportional to their lifespan.

There are two issues now:

  1. I can only use one action manager for the clones. One removes the food, the other scales the y axis, but only one at a time works (whichever is read last by the scene).

  2. I have absolutely no idea how to combine metadata randomly when two clones intersect to create a new clone “offspring.” :thinking:

Forgot to add that having the food provide different amounts of energy is a great idea :smiley: :+1:

1 Like

Still playing - made changes to some of your methods and corrected some mistakes I had made https://www.babylonjs-playground.com/#2CHIX4#5

The dance two box clones make on meeting is completely accidental but I think adds something.

From my personal point of view the use of actionManager in this particular situation with multiple loops on the same array is a bit messy so I have still avoided them. Obviously you may prefer them, its up to you.

I am thinking about offspring and have the seed of an idea. Hope you don’t mind the continuing interruptions.

These are just wild thoughts on model genetics that I am making up as I go along, so please bear that in mind.

Currently too related traits are used speed and life/energy which directly relate, ie faster speed less life. Obviously this is a bit too simple. Lets make it a little more complicated. (Hopefully I will not get too carried away.

First of all I added whole life and whole life decay so that when the predator eats it can never completely get back to full life time so must die eventually.

consider these as traits

P Energy Potential - the maximum energy storeable
D Energy Decay - fractional decrease of energy potential over time
T Decay Time - the rate of decay of energy over time
B Energy Burn - the fractional amount of energy used just by moving
S Speed Potential - maximum speed
Mass - scale of size constant over time

With these you could work out current speed and current energy (somehow or other but I want to concentrate on made up genetics)

Consider two type of entities A and B with traits inherited from either A or B type
So new traits A and B and offspring only produced when A and B meet

Type P D T B S M
From A B A A B B
. . . . . 1 0 1 1 0 0 using binary for A and B

for variation use 80% from A and 20% from B for a 1 or vice versa for a 0

Further vary this by having weak types a and b

So intersections that produce offsprings can be AB, aB, Ab, ab

AB or ab
1 80% A 20%B
0 20% A 80% B

aB
1 60% A 40%B
0 10% A 90% B

Ab
1 90% A 10%B
0 40% A 60% B

AS I said just first thoughts

Hello John!

Glad to see you’re still following this project :smiley: :+1: I definitely need and appreciate the help!

I’m a biology teacher, and I got into programming about a month ago to make educational games and simulations. Eventually, these digital creatures will have a full array of traits that follow the actual rules of genetic inheritance. They’ll have realistic metabolisms, movements, and behaviors as well (I hope!). I’ll want this project to be a fun educational simulation that students can use to study genetics, ecology, and evolution. I’m finding out that this was a very ambitious first project from a new programmer perspective!

So, with that backstory, you’re ideas are excellent and definitely in line with what I’m trying to accomplish.
You suggested programming variation in trait inheritance probabilities and including “weak” types. Both ideas are great, and would simulate how actual genes (alleles) are passed from parent to offspring, and how some genes are recessive to others.

So, back to the programming questions!

You added some new code that I don’t yet fully understand and will have to study. I don’t want to ask too many questions, so I suppose I’ll ask about using different variable letters for the various arrays (i, k, and j). My guess is that the different letters allow the program to store different states of the same mesh (i.e. box1 from the “i” array, and box1, from the “j” array…)?

Also, for the inheritance component, any suggestions for combining metadata from two meshes when they intersect?

For instance, similar to what you referenced in your last post, let’s say:

box1 has a maxSpeed of 0.4
box37 has a maxSpeed of 0.2

When they intersect, they create a NEW clone with a maxSpeed of 0.3 (average from the two parents).

1 Like

We are obviously in different time zones Midnight here in UK so off to bed. Give more answers tomorrow. I am a retired maths teacher.

I love your thread !!! keep the good thing coming :slight_smile:

Please ask any questions you wish.

Not sure from the question what you understand about arrays, so I hope my answer is not teaching my Gran to suck eggs.

TL; DR JavaScript stuff

let A = [ 1, 2, 3];
let B = ["a", "b", "c"]

it follows that A[0] = 1, A[1] = 2, A[2] = 3, B[0] = “a”, B[1] = “b”, B[2] = “c”;

let variable (letter) in a for…loop can tell you how far you are through an array

for (let i = 0; i < A.length; i++) {
   //do something with A[i]
}

for (let i = 0; i < B.length; i++) {
   //do something with B[i]
}

The above code works because there is no overlap between the uses of i.
Suppose we want to make a list “a1”, “a2”, “a3”, “b1”, “b2”, “b3”, “c1”, “c2”, “c3” we can do that with an inner and outer loop

for ( let i = 0; i < B.length; i++) {
    for (let j = 0; j< A.length, j++) {
          // combine B[i] with A[j]
    }
}

If you try

for ( let i = 0; i < B.length; i++) {
    for (let i = 0; i< A.length, i++) {
          // combine B[i] with A[i]
    }
}

Things mess up because the outer and inner loop overlap the use of i. The inner loop increments i past its limit in the outer loop.

As you have know you can get away without using i, j etc by using forEach

B.forEach  (itemB) {
   A.forEach  (itemA) {
          // combine itemB with itemA
    }
}

but again you cannot just use item for both loops.

There are advantages to doing it this way but for combining ‘like with like’ using indices allows you to miss out combinations already undertaken (unless order matters eg a[i] - a[j] is not the same as a[j] - a[i] )

for ( let i = 0; i < A.length; i++) {
    for (let j = i + 1; j< A.length, j++) {
          // add A[i] + A[j] is only done once
    }
}

hence lines 160 to 165 in PG ref #2CHIX4#5