Thank you very much.
Experience so far
I completed the tutorials for first 2D and 3D games a few weeks ago. I also tried reading much of the documentation but many of the pages were short and didn’t help much so I stopped reading them. Many of the tutorials on YouTube are for outdated versions and made years ago. I tried some demos in the asset library and was able to get 3D camera movement and mouse control working in another project.
Despite this much exposure to Godot I still feel like a novice in the deep end.
Project setup
I considered using RigidBody3D for particles because of the built-in physics behaviours, but in my other attempts to use RigidBody3D I always struggled to set its properties. RigidBody3D would get stuck or not do something simple such as changing its position or scale.
From what I read online in various places, RigidBody3D needs forces applied to it instead of directly setting its properties, because the collision system handles those. So I’m reluctant to use it.
I also tried CharacterBody3D but it doesn’t have the physics behaviour of a RigidBody3D, so both node types have disadvantages, which is why I chose Area3D.
World setup
For a bounding sphere in the world scene I used an Area3D parenting a CollisionShape3D.
world.tscn:
Node3D ('world') (script: world.gd):
Area3D ('boundingSphere'):
CollisionShape3D ('collider')
DirectionalLight3D
WorldEnvironment
Camera3D
world.gd:
extends Node3D
const proton = preload("res://proton.tscn")
func _ready() -> void:
for i in range(50):
var newProton = proton.instantiate()
var minVel = -0.01
var maxVel = 0.01
var velocity:Vector3
velocity = Vector3(randf_range(minVel, maxVel), randf_range(minVel, maxVel), randf_range(minVel, maxVel))
newProton.initialize(velocity)
newProton.scale = Vector3(0.5, 0.5, 0.5)
add_child(newProton)
func _process(delta: float) -> void:
pass
func _on_bounding_sphere_area_exited(area: Area3D) -> void:
if area.is_in_group("particleCore"):
area.get_parent().velocity *= -1
This bounces the protons back as intended but seems inefficient because every process loop needs to check which group the Area3D is in.
What is a more efficient way to simulate a bounding sphere? I guess I could somehow store the IDs of all particles and loop through that array to check if their positions are in the bounding sphere. Such a loop could be more efficient because the program knows everything in that list is a particle, as opposed to checking all Area3Ds intersecting the bounding sphere and checking if those Area3Ds are in the particle group.
I just realised in theory I could optimize collision layers so the only Area3Ds which do collide with the bounding sphere are particles.
Particle setup
For the particles so far I have a Proton scene and a particle script.
proton.tscn:
Node3D ('proton') (script: particle.gd):
Area3D ('forceArea') (group: protonForceArea):
CollisionShape3D ('forceCollider')
Area3D ('core') (group: particleCore):
CollisionShape3D ('coreCollider')
MeshInstance3D ('mesh')
particle.gd:
extends Node3D
var velocity: Vector3 = Vector3(0, 0, 0)
func _ready() -> void:
var minVel = -0.01
var maxVel = 0.01
velocity = Vector3(randf_range(minVel, maxVel), randf_range(minVel, maxVel), randf_range(minVel, maxVel))
pass # Replace with function body.
func initialize(newVelocity: Vector3):
velocity = newVelocity
pass
func _process(delta: float) -> void:
position += velocity
pass
The core is the proton’s ‘solid’ surface and can be used to prevent other particles occupying its exclusive position in space. I guess I could replace the core with a CSGSphere.
Force area setup?
The force area is the radius in which the proton’s force is applied to anything inside the force area’s Area3D.
I’m not sure if this is the best node setup for a particle applying a force over an area.
Ideally the force would be applied to all other particles wherever they are, even if they’re not in a force area. Like how gravity is applied to all objects regardless of distance, with closer objects experiencing stronger force.
I realised there is no signal for something simply being inside the force area; the signals are for entering or exiting the area. So I can’t do something like
if otherParticle is inside this particle's force area
then calculate force
But I want distance to nearby particles to factor into the force strength; closer particles experience stronger force.
I guess I will need to somehow loop through an array of all particles to apply such forces. How would I do that? I think such code would need to be in the world’s script instead of in the particle’s script.
Thank you again. I recall deleting this topic yesterday because I gave up and didn’t want to waste anyone’s time, but later I tried again and this morning noticed your response.