Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose PhysicsServer's (and Physics2DServer's) space_step #1373

Open
ETdoFresh opened this issue Aug 15, 2020 · 10 comments
Open

Expose PhysicsServer's (and Physics2DServer's) space_step #1373

ETdoFresh opened this issue Aug 15, 2020 · 10 comments

Comments

@ETdoFresh
Copy link

ETdoFresh commented Aug 15, 2020

Describe the project you are working on:
I am currently working on a lower level client side prediction / server reconciliation clone of asteroids. I saw the demo project on youtube (https://www.youtube.com/watch?v=B02bil7G2S4) of Client side prediction and Server reconciliation in Godot 4.0. I asked the question how this was being done. @AndreaCatania responded back immediately and told me he was using kinematic bodies and space_step. He asked if space_step is not currently exposed, to put in an issue. (This is my first one, so apologies if I'm doing this wrong!)

Describe the problem or limitation you are having in your project:
Currently, I have no way to re-simulate physics via gdscript. I can run physics in realtime, but if I need to do server reconciliation, I do not have access to any step() function.

Describe the feature / enhancement and how it helps to overcome the problem or limitation:
Exposing a step() function will allow network programmers to re-simulate the world and make corrections as necessary.

Describe how your proposal will work, with code, pseudocode, mockups, and/or diagrams:

# Very psuedo! :p
func resimulate_step(delta):
    PhysicsServer.space_step(space_rid, delta)

func correct_and_resimulate(corrected_transforms, number_of_steps_to_resimulate):
    correct_all_physics_body_transforms(corrected_transforms)
    for i in range(number_of_steps_to_simulate):
        resimulate_step(fixed_rate)
    apply_correction_to_all_nodes()

If this enhancement will not be used often, can it be worked around with a few lines of script?:
I think resimulating physics seems like something that would take many man hours to reproduce if not exposed.

Is there a reason why this should be core and not an add-on in the asset library?:
I think everyone that has to do some kind of live networking game will need this in their coding toolkit.

PS - I'm currently working in 3.2. It's be great if this can be exposed here. But if not, I'll definitely make the switch to whichever version has it! :)

@neqs20
Copy link

neqs20 commented Aug 15, 2020

Client-side prediction and server reconciliation are on my to-do list. I am very far from implementing those, but that function will definitely help me with that.

@Calinou Calinou changed the title Expose PhysicsServer (and Physics2DServer) space_step Expose PhysicsServer's (and Physics2DServer's) space_step Aug 15, 2020
@jonbonazza
Copy link

To be entirely clear here, this is only needed when dealing with physical bodies like rigidbodies with replay algorithms. For kinematic bodies, you do not need this. You can implement typical server reconciliation and client-side prediction just fine with the current facilities. In fact, we already do this in our game.

@Xrayez
Copy link
Contributor

Xrayez commented Aug 16, 2020

I think this could help #740.

@ETdoFresh
Copy link
Author

@jonbonazza Yeah, exactly! I'm using Rigidbodies for my simple pseudo asteroids example, but I could definitely replace with kinematics bodies. And, honestly, maybe the way I have to go for this one.

TBH, I'm coming from a 5 year unity background, and I was spoiled with having co-existing PhysicsScene(s) where I could run PhysicsScene.Simulate(float step) on any individual scene. I was hoping to recapture this concept in Godot, in Godot style of course. I looked at Godot source code for the Physics2DServer, and there is a "step" function in there. But what I don't know, how many tentacles rely on this function, and what actually happens when using it. I exposed it using ClassDB:bind_method, and in a way, it kinda works (with editor warnings per step...), but I can only step the default world, and not another world/space.

@Xrayez Cool, yeah, I saw the post. Similar to my response to Jon... It's very possible, and perhaps even more optimized, to use Kinematic Bodies and use the Mathz... I am capable (err, maybe capable :p). I was just hoping I could use engine to simulate the world instead of me having to calculate every objects position/rotation/velocity/etc. But, alas, I may have no other choice.

@ETdoFresh
Copy link
Author

Apologies if I'm being too chatty. I just want to share my experiences in case it helps somebody. I had some time to play with the KinematicBody2D this evening, and yes, it's able to do everything I need it to do for my simple asteroids game and other simple games I have in mind. I found that I can use move_and_collide and collisions to bounce. So, for me personally, no worries! But for future game devs, I still think the physics.step() can be a useful tool if someone is running more in-depth physical simulations. Thanks for the comments everyone, thanks for helping me out, and thank you contributors and community. Everyone here is great! ❤️ - ET

@Xrayez
Copy link
Contributor

Xrayez commented Aug 18, 2020

TBH, I'm coming from a 5 year unity background, and I was spoiled with having co-existing PhysicsScene(s) where I could run PhysicsScene.Simulate(float step) on any individual scene. I was hoping to recapture this concept in Godot, in Godot style of course.

but I can only step the default world, and not another world/space.

There was a really cool PR for this on a conceptual level: godotengine/godot#28816. Perhaps @LeonardMeagher2 could elaborate on this topic in relation to this one (someone could write a different proposal for subspaces too, for discussion purposes).

By the way, in Godot 4.0 we have Viewport and Subviewport now (talking in relation to Viewport.find_world_2d/3d where those spaces could be potentially accessed).

I had some time to play with the KinematicBody2D this evening, and yes, it's able to do everything I need it to do for my simple asteroids game and other simple games I have in mind.

I've been using KinematicBody2D as well for a lot of stuff lately, mainly because I need more control over physics interactions... I even managed to use KinematicBody2D as a RigidBody2D in some cases just because KinematicBody2D doesn't suffer from OCD CCD issues: godotengine/godot#9071.

@LeonardMeagher2
Copy link

LeonardMeagher2 commented Aug 18, 2020

@Xrayez thanks for the mention
It's actually pretty easy to do sub spaces in 2d and 3d in gdscript. Here are two scripts I keep around for 2d, but I'm sure they could easily be made for 3D also.

extends Resource
class_name Space2D

export(bool) var active = true setget set_active
export(float) var gravity = 98.0 setget set_gravity
export(Vector2) var gravity_vector = Vector2(0,1) setget set_gravity_vector
export(float) var linear_damp = 0.1 setget set_linear_damp
export(float) var angular_damp = 1.0 setget set_angular_damp

var space : RID = RID()
var direct_space_state : Physics2DDirectSpaceState setget ,get_direct_space_state

func set_active(_active:bool):
	active = _active
	Physics2DServer.space_set_active(space,_active)
func set_gravity(_gravity:float):
	gravity = _gravity
	Physics2DServer.area_set_param(space, Physics2DServer.AREA_PARAM_GRAVITY, _gravity)
func set_gravity_vector(_gravity_vector:Vector2):
	gravity_vector = _gravity_vector
	Physics2DServer.area_set_param(space, Physics2DServer.AREA_PARAM_GRAVITY_VECTOR, _gravity_vector)
func set_linear_damp(_linear_damp:float):
	linear_damp = _linear_damp
	Physics2DServer.area_set_param(space, Physics2DServer.AREA_PARAM_LINEAR_DAMP, _linear_damp)
func set_angular_damp(_angular_damp:float):
	angular_damp = _angular_damp
	Physics2DServer.area_set_param(space, Physics2DServer.AREA_PARAM_ANGULAR_DAMP, _angular_damp)
	
func get_direct_space_state():
	return Physics2DServer.space_get_direct_state(space)
	
func _init():
	space = Physics2DServer.space_create()
	set_active(active)
	set_gravity(gravity)
	set_gravity_vector(gravity_vector)
	set_linear_damp(linear_damp)
	set_angular_damp(angular_damp)
extends Node2D
class_name SubSpace2D

export(Resource) var space2D setget, get_space2D

func get_space2D():
	return space2D as Space2D
	
func _update_space(node:Node):
	if node is CollisionObject2D:
		Physics2DServer.body_set_space(node.get_rid(),space2D.space)
	for child in node.get_children():
		_update_space(child)

func _ready():
	_update_space(self)

func _enter_tree():
	get_tree().connect("node_added",self,"_node_added")
func _exit_tree():
	get_tree().disconnect("node_added",self,"_node_added")

func _node_added(node:Node):
	if is_a_parent_of(node) and node is CollisionObject2D:
		Physics2DServer.body_set_space(node.get_rid(),space2D.space)

Edit: Looks like I reference these scripts in that PR too 🤷

@JakSparro98
Copy link

I strongly support this feature since I'm developing a Peggle-like game and the need for pixel perfect trajectories and bodies position predictions can't be solved with workarounds. After lots of research on the subject and hours spent watching AI-played games on Peggle I've come at the conclusion they cloned the game scene and simulated a ball launch on a parallel physics system keeping also in mind what kind of peg were hit and the position of the basket/any moving object.

I mean, this is not a simple ballistic formula, this is a baked trajectory that keeps track of every aspect of a rigid body:
BakedTrajectory

@AndreaCatania
Copy link

I agree that this feature is needed. Right now it's possible to create a new physics space, but it's always processed within the main process.
So, a way to process it following user code is definitely useful.

Another use case is when you want to fast forward the scene to know the final result, and so show the future to the player.

@addmix
Copy link

addmix commented Sep 22, 2022

This is a necessary feature for networked games in 4.0. With the change of KinematicBody to CharacterBody, there is no longer a way to control the delta time of KinematicBodys. I am currently in a development deadlock due to this constraint.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants