-
-
Notifications
You must be signed in to change notification settings - Fork 21.6k
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
Added spring arm node #18822
Added spring arm node #18822
Conversation
scene/3d/spring_arm.cpp
Outdated
@@ -0,0 +1,141 @@ | |||
/*************************************************************************/ | |||
/* spring_arm.h */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should be .cpp
corrected the license, also added a method to get the current spring length. |
build.bat
Outdated
@@ -0,0 +1,3 @@ | |||
@echo off | |||
call "C:\Program Files (x86)\Microsoft Visual Studio\2017\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64 | |||
scons p=windows |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was added by mistake.
@vnen, yeah, sorry. Fixed |
I think that is better if you initialize current_spring_length to 0 and mask to 1 ( that is the same value of all other physics body) |
3ea6202
to
292e489
Compare
Done :) |
This looks nice, but I'm not sure this should be core, it does not seem like something you will use very often and could be very well provided by a script in the asset library |
Most 3D games will probably use this, @reduz |
@reduz i think it would be nice to have, i felt the need for this and i think also the people in #16508 did :) |
I agree with @Zireael07 and @QbieShay, imho it'd be more convenient to have it core rather than having to import it every time. Moreover, for something as performance-intensive as a spring arm, to me C++ appears as a better choice than gdscript. |
@reduz is saying correctly, but I think that it will make life easier for all the people that want to avoid camera overlapping with environment. Is not a lot of code and i think worth it |
This is useful unless the game is in first person or camera movement is deterministic. I don't think I can make unobscured third person view without implementing something similar to this, and doing so takes a considerable amount of time and coding skill. I think it is justified according to this. |
Is anyone interested in adding enabling camera lag for location and rotation? There's camera lag speed, camera rotation lag speed variables and a max camera lag distance. Bonus points for adding arm debugging helpers. The reason is that the arm motion is abrupt. |
Hey @fire, achieving camera lag shouldn't bee to complicated: you place a dummy object under the spring arm node and you make your camera follow it with the lag you prefer. I believe you can also use an interpolated camera and have it out of the box |
It's working. I placed a dummy CameraTarget as a child of the spring arm node, then put the interpolated camera somewhere not as a child of the spring arm node. (its location should be close to the controlled mesh, this defines the minimum camera distance.) and set the interpolated camera's target to be CameraTarget. |
@QbieShay A lot of users really insisted about this feature, so in the latest PR meeting review we have decided to merge it, as such, I will review it for inclusion. |
set_process_internal(false); | ||
} | ||
break; | ||
case NOTIFICATION_INTERNAL_PROCESS: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be INTERNAL_PHYSICS_PROCESS, because then you make sure that physics world is available for raycasting (as in, may happen that thread physics is enabled and you will get an error). You also need to use set_physics_process_internal()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If physic process is used and the spring arm is used for a camera, the difference between physic process and regular process is visible to the user and annoying. See here you can try out a spring arm that uses physic process
scene/3d/spring_arm.h
Outdated
public: | ||
void set_spring_length(float p_length); | ||
float get_spring_length() const; | ||
void set_shape(Ref<Shape> p_shape); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is setting a shape worth it? I would honestly just use a raycast with a margin, this covers pretty much any case I can think of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked in the physics server but I don't see a way to set a margin for a raycast
scene/3d/spring_arm.h
Outdated
bool remove_excluded_object(RID p_rid); | ||
void clear_excluded_objects(); | ||
float get_current_spring_length(); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would also set a node via NodePath that you want to automatically make the SpringArm change position to on every frame (usually a camera). Could be a function like
set_target_node(const NodePath&)
NodePath get_target_node() const
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The movement of the spring arm node is intentionally left to the user. In order to achieve what you mention, it is enough to put the spring arm node as a child of a remote transform or the object itself. Leaving the movement to the user also allows for adding manual lag - damping - ecc.
@@ -390,6 +391,8 @@ void register_scene_types() { | |||
ClassDB::register_class<RigidBody>(); | |||
ClassDB::register_class<KinematicCollision>(); | |||
ClassDB::register_class<KinematicBody>(); | |||
ClassDB::register_class<SpringArm>(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you should probably add a gizmo to this, where you can edit the length (and optionally the margin if you use that)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you point me to an example of where this is done? I have no idea on how to implement that. Probably also @groud can help me?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
check the ray shape gizmo, I think that you can copy most part of code from there
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AndreaCatania I'm not sure the ray shape gizmo is that good, I opened an issue on that here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It can be improved, but the basic code is almost the same
scene/3d/spring_arm.h
Outdated
void add_excluded_object(RID p_rid); | ||
bool remove_excluded_object(RID p_rid); | ||
void clear_excluded_objects(); | ||
float get_current_spring_length(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would use a get_hit_length() function or similar, instead of get_current_sprint_length(), to make it less confusing
8d4ed3e
to
723f4df
Compare
Gizmos changed recently due to @JFonS , so this will need re-adapting to the new way gizmos are done. |
@QbieShay you can take the new RayCastSpatialGizmoPlugin as an example on how to convert your gizmo, and ask away if you have any doubts. |
This Node is lacking an icon. |
Thanks to @AndreaCatania, Godot now can have a Spring Arm node!
Closes #16508.
The spring arm node is a node that pushes all its children back on his local z considering collision with the environment. If there is a collision, the spring arm will reduce its length.
The spring arm only moves its immediate children, and only the location( rotation control it's left in the hands of the developer ). It supports collision masks and specific body exclusion. It has a shape as property which is the shape that will be cast to do collision avoidance. Multiple shapes are not supported.
This type of node comes in handy when making 3rd person cameras, but it's not bound to that.
Example usage:
A classic responsive 3rd person camera can be achieved by simply adding the spring node as a child of the character, regulating its orientation to match the desired angle, and adding a camera as a child of the spring arm node. This implementation can be modified in various ways, for example, moving the spring arm on the shoulder of the character will achieve a shoulder camera with minimal effort.
The spring arm itself does not move on his own, so it is possible to control its motion , for example, for a racing game it's useful to have damping on the camera movement, and this can be easily achieved by scripting the spring arm node.