Hello!
Right now I am using the raycast function on this way:
// Sensors
var sensorLeftFront = this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition());
var sensorLeftFrontBottom = this.app.systems.rigidbody.raycastAll(this.sensorLeftFront.getPosition(), this.sensorLeftFrontBottom.getPosition());
// Detections
if (sensorLeftFront && sensorLeftFront.entity.tags.has("Obstacle") || !sensorLeftFrontBottom) {
detectionLeftFront = true;
if (visibleSensors) {
this.app.renderLine(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition(), colorRed);
this.app.renderLine(this.sensorLeftFront.getPosition(), this.sensorLeftFrontBottom.getPosition(), colorRed);
}
}
else {
detectionLeftFront = false;
if (visibleSensors) {
this.app.renderLine(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition(), colorGrey);
this.app.renderLine(this.sensorLeftFront.getPosition(), this.sensorLeftFrontBottom.getPosition(), colorGrey);
}
}
But I get an error on the tags check:
Cannot read property 'tags' of undefined
I think there is a new way to do this…
will
April 29, 2020, 11:17pm
2
raycastAll
returns an array of pc.RaycastResult
s. Not a single pc.RaycastResult
.
So how can I check if there is one of them with the tag?
will
April 29, 2020, 11:20pm
4
this.app.systems.rigidbody.raycastAll(start, end).forEach(function (result) {
console.log('Name: ' + result.entity.name);
result.entity.tags.list().forEach(function (tag) {
console.log('Tag: ' + tag);
});
});
Ah I see, that is working. I will work it out later.
Thanks! I am happy with this new feature!
2 Likes
How can I create a list of this:
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition());
and how do I check if that list is empty or not?
will
May 5, 2020, 8:28pm
7
I’m not sure I understand your question. Can you rephrase it please?
I started using your first example with something like this:
// Left Front Sensor
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition()).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
});
But I also have to set this.detectionLeftFront on false if there is no result.
I don’t think I can do that inside that function?
will
May 5, 2020, 9:59pm
10
Oh, this is another problem with the value of this
. So you could do one of these options:
Option 1: Use Function.prototype.bind
// Left Front Sensor
var start = this.frontSensors.getPosition();
var end = this.sensorLeftFront.getPosition();
this.app.systems.rigidbody.raycastAll(start, end).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
}.bind(this));
Option 2: Cache this
in self
// Left Front Sensor
var start = this.frontSensors.getPosition();
var end = this.sensorLeftFront.getPosition();
var self = this;
this.app.systems.rigidbody.raycastAll(start, end).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
self.detectionLeftFront = true;
}
else {
self.detectionLeftFront = false;
}
});
Option 3: Pass second argument to forEach
// Left Front Sensor
var start = this.frontSensors.getPosition();
var end = this.sensorLeftFront.getPosition();
this.app.systems.rigidbody.raycastAll(start, end).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
}, this);
I’d go with Option 3.
1 Like
Ah that’s not the problem, but thanks for solving a future error!
// Left Front Sensor
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition()).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
}, this);
How do I set this.detectionLeftFront on false if there is no result.
I don’t think I can do that inside that function?’
With raycastFirst I did this:
// Sensors
var sensorLeftFront = this.app.systems.rigidbody.raycastFirst(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition());
// Detections
if (sensorLeftFront && sensorLeftFront.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
result
in the callback should never be null as raycastAll
only returns a list of entities that it has hit.
Sounds like you want is:
// Left Front Sensor
this.detectionLeftFront = false;
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition()).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
this.detectionLeftFront = true;
}
}, this);
That way, this.detectionLeftFront
is only true if the raycast has hit something.
Oke, can I do that both in the update?
I mean do I not get a true/false/true/false/true effect?
As long as this block of code stays together, you should be fine. (ie you don’t add any extra code between that relies on detectionLeftFront
between it being set to false and the raycastall call)
Basically, you are just doing this:
var hasLeftFrontHitSomething = false;
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition()).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
hasLeftFrontHitSomething = true;
}
});
this.detectionLeftFront = hasLeftFrontHitSomething;
But it gets a bit more complex.
Before setting this.detectionLeftFront on false i have to check another sensor that checks if there is ground.
So if there is no obstacle and there is ground then this.detectionLeftFront = false .
Else if there is an obstacle or there is no ground then this.detectionLeftFront = true .
Because i have a lot of sensors the code should be as minimal as possible.
With raycastFirst I did this:
// Sensors
var sensorLeftFront = this.app.systems.rigidbody.raycastFirst(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition());
var sensorLeftFrontBottom = this.app.systems.rigidbody.raycastFirst(this.sensorLeftFront.getPosition(), this.sensorLeftFrontBottom.getPosition());
// Detections
if (sensorLeftFront && sensorLeftFront.entity.tags.has("Obstacle") || !sensorLeftFrontBottom) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
From the code you have written above, this looks like what you need:
var sensorLeftFrontHitObstacle = false;
this.app.systems.rigidbody.raycastAll(this.frontSensors.getPosition(), this.sensorLeftFront.getPosition()).forEach(function (result) {
if (result.entity.tags.has("Obstacle")) {
sensorLeftFrontHitObstacle = true;
}
});
var sensorLeftFrontBottomHitAnything = false;
this.app.systems.rigidbody.raycastAll(this.sensorLeftFront.getPosition(), this.sensorLeftFrontBottom.getPosition()).forEach(function (result) {
sensorLeftFrontBottomHitAnything = true;
});
// Detections
if (sensorLeftFrontHitObstacle || !sensorLeftFrontBottomHitAnything) {
this.detectionLeftFront = true;
}
else {
this.detectionLeftFront = false;
}
If it’s not right, you should be able to tweak this to get what you need.
A little more code than I hoped, but if that’s the best way, I’ll work it out that way.
Thanks for the effort @yaustar !