Moving an Area3D using velocity and 2 rotation axis

Godot Version

4.3

Question

I have an Area3D that I do not want to use any physics behavior on it, and I just want to move on my own in func _process

I have the variable velocity, rotation_x_axis and rotation_y_axis. With these variables, I would like to calculate and set the new position of the Area3D in the process function.

But I am not sure about the calculation in 3D part. What would be the best way to tackle this problem?

Can you try this? It will work in 3 rotation axis:

var input_dir = Input.get_vector("left", "right", "backward", "forward")
velocity = transform.basis.z * speed
position += velocity * delta

Hi @KingGD ,

Isn’t that Input.get_vector code is for controlling the Player? Also, the input_dir is not used in other 2 lines.

Unless, I am missing something, can you explain how will this work?

I will be moving the Area3D using my own velocity and the values of 2 rotation axis.

1 Like

Can you show your codes?

@KingGD

So far, this is what I got:


var velocity_vector : Vector3 = Vector3(0,0,0)

func set_speed_and_dir(speed: float, rot_x : float, rot_y : float) -> void:
	velocity = speed
	rotation = Vector3(0.0, 0.0, 0.0)
	rotate_x( rot_x )
	rotate_y( rot_y )

	# there gotta be something else here. 
	# I have already rotate the x axis and y axis, 
	# but I am not sure how to translate the above
	# to velocity_vector to be used in _process below...

func _process(delta: float) -> void:
	global_position += velocity_vector*delta

1 Like

Can you try this?

velocity_vector = transform.basis.z * speed

Just put the above codes in that first function.

Do you looked for this? Or there are many ways… I can say.

1 Like

@KingGD

I just tried your one line, and wow, it worked.

One question though, is global_position += velocity_vector * delta the fastest way to move a 3D object in every frame?

I was surprised. I guess I will have to understand more about transform and basis more. I tried the document, but I still do not understand the Mathematics behind them.

2 Likes

You could stick the Area inside a Kinematic body, and move it that way. Putting the kinematic collider on a layer by itself.

It may be marginally better to update position instead of global_position. That line within _process is surely the fastest way for a GDScript to update position every frame.

1 Like

For physics objects such as an Area, it’s better to use _physics_process.
Your question is not very clear. What are you trying to achieve exactly? Do you want the node to travel with velocity along it’s own global axes so that it can move relative to it’s rotation?

1 Like

@wabbit I would like to have a full control over my Bullet Scene, and the thing is I’ve tried RigidBody3D but then I see that its physics simulation is not what I am after.

For the Bullet scene, I would like full controls like in Bullet Hell games and I control their patterns around. They will not be following any realistic physics simulation.

So I decided to go with Area3D instead. And that’s why I need to control the movement in 3D myself.

Okay, I see. So you do want the bullet to move along it’s rotation and not along the global axes?
I did just recently run into this issue, and after a good bit of research I decided to use ShapeCast. It provides all the necessary info you need for a bullet, like multiple collisions unlike Raycast which only returns one collision.

@wabbit No, actually, I only wanted to be able to set velocity and angles of the any instantiated Bullet scene and have it travel on the set velocity and angles.

In 2D game, as there is only 1 axis of rotation, I simply just apply simple trigonometry and everything works as expected. But in 3D, things are more complicated, and I decided to only use axis x and y to set the 3D angle of the Bullet.

With the given code from @KingGD , I could for example create a spherical “firework” of Bullets expanding outward.

1 Like

I don’t see how your original piece of code had any issues in that case. It just moves the area along the velocity. Anyways, another reason I wouldn’t use Area2D for bullets is because it can pass through objects at high speeds and not register the hit. It’ll also provide incorrect or no data about the hit’s direction.

@wabbit

Yes, I am seeing that too in a very low framerate simulation.

In that case, you’ve mentioned ShapeCast3D. This is probably the way to go for fast moving projectiles, yes?

But then:

It’ll also provide incorrect or no data about the hit’s direction.

If I have my own variable velocity_vector , then I would know its speed in x,y,z - basically the direction, right? Ex. I can apply add the values of this Vector3D to another object to bump it away to the direction the Bullet is travelling. Or do you have some other requirements here?

I just saw your post about low framerate and was about to reply there.

ShapeCast is the way to go for bullets imo.

You are correct, it is possible to use the velocity vector to get the direction of the hit.

1 Like

@gertkeno I did some testing, changing global_position to just position in the code.

I spawned 4000 bullets and have them expand outward like a firework. (Happy New Year in advance!) The framerate I got is about 50 fps for both global_position and position.

If I removed _process function completely, not defining it in the class, I got the highest framerate possible on my monitor screen which is 144 fps. From here, if I disable vsync and allow unlimited framerate, I got more than 400 fps or so, and if I look away from all the bullets, I got more than 1000 fps. But of course, then no bullets are moving :smiley:

But this does imply something though. If I have a huge scene like a very big city that has thousand of nodes and if they have no _process function, the engine will just take a bit of time to load all these nodes and resources up and should run smoothly afterward.

I also tried adding an empty _process in:

func _process(delta: float):
	pass

But having _process defined with pass seems to be slower than having no _process at all. I got 100 fps here instead.

But again, this is just a little test just for fun. Having no _process or _process with pass will never be the real bottleneck, but I will remove _process from now on if I don’t need it. :stuck_out_tongue:

But @KingGD , just in case:

global_position += velocity_vector * delta

From this one line of code. Is it possible to optimize this a bit further?

Assuming I could use C++, will it be faster? If so, how much % improvement are we talking?

For mass optimizations you will need to look at other sub system tricks.

Your no-process city example would be better suited to big repeating buildings as MultiMeshInstances. Godot supposedly does this automatically, thus you get 1000 fps. You are correct about loading takes longer with more nodes, editing the scene tree is one of the most expensive operations.

For many bullets you need to trim down the physics server’s load, along with updating position/transform it is updating overlapped areas. If your bullets are set to mask eachother then that is 4,000^2 overlap checks every frame. There is an old video on optimizing bullets this without delving into a compiled GDExtension.

2 Likes

Try making Area3D a child of the node that moves and is programmed

@borys9999 I’ve tried your suggestion, but I do not see any performance difference. Do you have evidences to support your claims?