Repository: godot
Issue: SpringArm Node Bug: Spring Arm ignores collision when 'spring_length' is being updated
Labels: bug,topic:physics,topic:3d

### SpringArm Node Bug: Spring Arm ignores collision when _spring_length_ is being updated


**Godot version**:
Godot Engine v3.3.stable.offical

**OS/device including version**:
W10 64bit // i7-4770k @ 3.50GHz // 8gig DDR3 ram // RTX 3060ti

**Godot Files**:
[Springarm Issue.zip](https://github.com/godotengine/godot/files/6536470/Springarm.Issue.zip)

**Issue wright up**:

  I am having an issue with the _Spring Arm Node_ when trying to use it as a 3D camera arm.
My camera is set up to be able to lerp between two, technically three, positions during gameplay; 
Distant free view and Over the shoulder view. I'm taking inspiration form MGSV if that can give you an idea. The problem is when I update the arm length, it ignores the collision of any object it collides with.

**Node order**:
![image](https://user-images.githubusercontent.com/7089869/119253161-c7508a00-bb64-11eb-8b6c-bd955b73f6f9.png)

**Footage**:  Please excuse the jittery video, the source doesn't have this problem but viewing it on WEB is weird

https://user-images.githubusercontent.com/7089869/119253361-c53afb00-bb65-11eb-95e8-4e62471dcca4.mp4

When you see the spring arm working, i.e. not going through the floor, it's because _spring_length_ is _not being updated_
but when it is going through the floor, the arm _is interpolating between positions_ 

Here's the Code: 


```
extends Camera

export(NodePath) onready var arm = get_node( arm )
export(NodePath) onready var piv = get_node( piv )

                                                   # Points to where the camera is interpolating between
export(Vector3) var camera_zoom_offset : Vector3 = Vector3( 0.7,  0.5,  3.0)
export(Vector3) var camera_free_offset : Vector3 = Vector3( 0.0,  0.0,  7.0)

export( float ) var sensitivity        : float   = 5.0
export(Vector2) var vertical_clamp     : Vector2 = Vector2(deg2rad(-50), deg2rad(30))

var cam_pos : Vector3 = Vector3()

#-------------------------------------------------------------------------------

func _process(delta: float) -> void:
	_aim_camera(delta)

func _input(event: InputEvent) -> void:
	_cam_in(event)

#-------------------------------------------------------------------------------

func _aim_camera(delta):
	var to_vec : Vector3 # stores the target vector; where the camera is going

	if Input.is_action_pressed("aim"):                    # Triggers the camera to move over the players shoulder 
		if Input.is_action_just_pressed("aim_switch"):
			camera_zoom_offset.x *= -1                    # Switches which shoulder the camera is looking over

		cam_pos = lerp(cam_pos, camera_zoom_offset, delta * 7) # Interpolates between current position and to a target pos
		to_vec = camera_zoom_offset   # used to stop the arm distance from changing, you'll see
		
	else:                                                          # If we are not aiming; not in shoulder view
		cam_pos = lerp(cam_pos, camera_free_offset, delta * 5) # Interpolates between pos to pos
		to_vec = camera_free_offset                            # Again, set up to be used later

		if ((cam_pos - camera_free_offset).length() < 0.02):# rounds up the lerp to make stopping updating the arm length...
			cam_pos = camera_free_offset                # ... just a bit easier and faster
	
	if ((cam_pos - to_vec).length() != 0):     # If the camera / arm length is still changing, don't stop updating
		                                       # Else don't update the arm length if it's not changing
		transform.origin  = cam_pos            # This is where in the video you see it working until it starts in
		arm.spring_length = transform.origin.z # ... interpolating between positions
 


func _cam_in(event):                             # This is where I control the camera
	if event is InputEventMouseMotion:           # I'm not going to go into detail hear
		var mouse : Vector2 = -GlobalInput.Mouse(sensitivity, event)   # made a global script to make the syntax less bulky 
		piv.rotate_y( deg2rad( mouse.x ) )    
		arm.rotate_x( deg2rad( mouse.y ) ) 
		arm.rotation.x = clamp(arm.rotation.x, vertical_clamp.x, vertical_clamp.y)`


#------------------------------------------------------------------------------------------------------------------------------------------

# This is from my global input script and apply to the _cam_in function ^^^

func Mouse(sensitivity:float=1,event=InputEventMouseMotion) -> Vector2:
	var mouseDir = Vector2(event.relative.x, event.relative.y) # Note: always Add 'event' When calling from another script
	mouseDir * sensitivity * get_process_delta_time()
	return mouseDirextends Camera

```

Edits made for better formatting.