Actually, you could just apply ‘gravity’ to the bullet every frame that it is going forward (world down * magic number * deltaTime). That would do enough to look like a bullet falling over a distance.
If I be used gravity from the physics engine, and adjust the mass parameter, will it work?
If the bullet has a rigid body and collision, then yes but I don’t recommend that bullets should use the physics engine due to their size and speed.
For large things like geneades, perhaps.
Thanks for the detailed explanation. Now in my project, shooting works well, but sometimes the bullet flies through the object. How can this problem be solved?
Assuming it isn’t using a rigidbody with collision:
Have the bullet keep track of it’s position in the world and do a raycast between it’s current and last frame position.
I tried this method, but it did not work. Could you help me?
Try this version: https://playcanvas.com/project/596138/overview
A coupe of issues that I fixed:
- The last position was updated after the entity had moved which meant that both the last position and the current position was the same.
- The position of the entity wasn’t copied to last position, it was just storing a reference to the position vector.
Great job. Now I understand my mistakes and how to do it right.
Better not to use
setTimeout(), but to use the deltaTime variable for all counters?
In your case, it looked like you were setting a setTimeout every frame the bullet was ‘hitting’ anything and because the code destroys the entity on ‘hit’, you can be left with dangling setTimeout calls which leads to exception errors.
The way I’ve done it means that there’s only one place that the entity is destroyed for the bullet.
Is my project correctly implemented the algorithm for calculating the target point for the bullet or can it be simplified?
From playing it, it looks a bit off. It’s almost as though it doing a raycast from the camera and not the players weapon. I haven’t looked at the code to be sure.
I simplified the script for the bullet, and I have new questions.
Can I somehow make a check on another entity, that Ray Cast from this script was successfully applied to it, and after that play, for example, a sound?
If I have a trigger in my scene, but it doesn’t have a Rigid Body component, can I do the same check, that Ray Cast was applied, but ignore this so, that the
.applyImpulse()method doesn’t throw an error?
When I start the game, the bullet entity is disabled. When I take a shot, it’s copied. Euler angles always have the same value, regardless of where the weapon is directed. I have to set the Euler angles for each new bullet entity based on the Euler angles of the point that is at the end of the weapon. Can this be avoided?
I want to make the all scripts standalone so that they fit the design pattern ECS.
Not sure what you mean by this? If you are talking about telling the entity that it has been hit so it can do something in response, you can fire an event on the hit entity that scripts on that entity is listening for.
Check if the hit entity has a rigidbody before applying impulse. (
if (hitEntity.rigidbody != null)or something similar.
Not really. You could put the bullet as a child of the weapon and place it at end of the barrel. When you clone, it should place it in the correct position to start from? This may cause problems if you reparent the bullet though. I would just stick to cloning it and positioning the clone in the correct place.
- That is, I can configure the connection between the two scripts by this instruction?
- Here I understand.
- That is, I should always set Euler angles for the bullet entity, that I should be getting from another entity?
Sorry for a lot of questions.
Edit: I figured out with point 3.
- Yes. Entities have and components all can fire and listen to events which is incredibly useful
You wouldn’t happen to know, there is rules for writing scripts based on architectural pattern Entity Component System?
PlayCanvas script systems is more of a EC rather than ECS.
Quite frankly, I use the SOLID principles where possible.
I made this a while back (not sure if it still works with latest engine changes) which encompasses my approach in keeping code modular.
I, as a beginner, it is very interesting.
I still have one more shooting question. How to set correctly the crosshair on the screen? I use the
.worldToScreen method to set the crosshair, but it is installed incorrectly. I have to adjust it by pixels, which is not correct.
As the crosshairs are on a 2D UI screen, you actually want world to UI space rather than world to screen (screen being your computer screen and working in pixels).
Unfortunately, there isn’t a built in function in PlayCanvas to do that but a few forum users have managed to work out how to do this: [SOLVED] Include devicePixelRatio for screenspace to worldspace conversion
Thanks. I found this formula and applied it in my project. The crosshair should be at the bottom left of the screen.
var screenPos = new pc.Vec3(); var screenEntity = this.entity.element.screen; var scale = screenEntity.screen.scale; var device = this.app.graphicsDevice; this.cameraCrosshairEntity.camera.worldToScreen(worldPoint, screenPos); this.entity.setLocalPosition((screenPos.x / scale) - (this.entity.element.width / 2), ((device.height - screenPos.y) / scale) - (this.entity.element.height / 2), 0);