Creating beam weapon in 3D game

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Ertain

I need help with figuring out how to get a mesh to scale non-uniformly.

I’m trying to implement an beam-based weapon in a 3D game. It’ll act like Zarya’s particle cannon from Overwatch. Specifically, a beam will extend from the player’s weapon towards whatever the player is pointing at. While I can use something like a MeshInstance to extend to a far distance, I would like the beam to extend to some point until it hits a collision. What would be a good approach to implementing this?

I have looked into using a Raycast in order to detect the collisions, yet I still need to shorten the mesh. I’m fine with scaling it. However, scaling operations seem to be uniform; scaling the mesh on the Z-axis scales it from the origin. I need the mesh to be scaled in the direction of where the beam weapon is being pointed.

:bust_in_silhouette: Reply From: estebanmolca

If it is scaled uniformly, it is because the origin is in the center, I don’t know how the center is modified in a mesh in godot, but what you can do is create a Position3D or some other node that serves as the parent of the mesh. And then move the mesh so that one of its ends is in position 0.0 of Position3D. To make it work, you have to scale the Position3D, not the mesh, in the opposite direction of the end where the Position3D is. To detect the collision you can put an area with a collision as brother of the mesh and move one of its ends (The same as we did with the mesh). Scaling the Position3D will scale all your children in the same proportion. I don’t test if the collision works, I just tried the scaling but I think there shouldn’t be any problems.

The Position3D needs to be scaled to the end of the Position3D? I don’t understand what you’re saying.

Ertain | 2020-01-30 16:52

Sorry my english, I use google to translate, ends = one extreme, one side. Try this test: Add Position3D node, add a MeshInstance node as a child, add a cylinder mesh to the MeshInstance mesh property, go to Transform property and put 1 on the y axis of translation. go to position3d and scale on the y axis

estebanmolca | 2020-01-30 22:21

Another way is using shaders, add a meshInstance, add a MeshInstance with a CilinderMesh. And add a ShaderMaterial to the material with this code:
shader_type spatial;
uniform float dist = 10;
void vertex () {
if (VERTEX.y> 0.1) {VERTEX.y = dist; }
}
That scales the mesh according to the value of the dist variable (The scale is in local coordinates), you can access that variable from gdscript, using set_shader_param (), eg:
material.set_shader_param (“dist”, 15.0).
Vertex displacement with shaders — Godot Engine (3.0) documentation in English

estebanmolca | 2020-01-30 22:54

Ah, so use the shader code:

uniform float distance = 10;
void vertex() {
      if (VERTEX.y > 0.1) {
           VERTEX.y = distance;
      }
}

Then reference it in GDscript with the code:

laser_beam.get_surface_material( 0 ).set_shader_param( "distance", some_length )

I got it.

Ertain | 2020-01-31 22:49

:bust_in_silhouette: Reply From: Merlin1846

If your going with the scaling plan then try changing the anchor point for the node from center to left or right. Maybe using a control node?

Didn’t know nodes had anchor points. Or are those just unique to Controls? If that’s the case, then it’s not a viable solution; Control nodes aren’t really useful in 3D.

Ertain | 2020-01-30 19:40

Didn’t know you were in 3d. So try a CSG shape.

Merlin1846 | 2020-01-30 20:13