Thursday, October 19, 2023

Player and Rigidbody


 Hello there!

After many many many headaches, I found a way to work with the collision between Player and Puck.
Eventually I found this demo https://godotengine.org/asset-library/asset/1291 which uses
Rigidbody to control the player, and has box collisions. Besides, I've swapped the player's shape
with Godot's robot 3d animation from: https://godotengine.org/asset-library/asset/344 and
edited it to my needs. Now I have player movement, puck's collision and a mini rink to test.

Below you can see the current scene (tscn) and code for the player:


Edit: The robot character takes too much resources to load in the PS VITA and the game freezes after pressing the new game button. This means, for now, the robot is discarded and the generic capsule (MeshInstance) is used. [On the PC when I debug the project the resources problem doesn't happen, at all]
 

```
# Player
extends RigidBody


onready var raycast = $RayCast
onready var camera = $Target/Camera
onready var start_position = translation


func _physics_process(_delta):
    var dir = Vector3()
    dir.x = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
    dir.z = Input.get_action_strength("move_back") - Input.get_action_strength("move_forward")

    # Get the camera's transform basis, but remove the X rotation such
    # that the Y axis is up and Z is horizontal.
    var cam_basis = camera.global_transform.basis
    var basis = cam_basis.rotated(cam_basis.x, -cam_basis.get_euler().x)


    apply_central_impulse(dir.normalized() /5)

    # Jumping code.
    if on_ground() and Input.is_action_pressed("jump"):
        apply_central_impulse(Vector3.UP)


# Test if there is a body below the player.
func on_ground():
    if raycast.is_colliding():
        return true
```


And now the player's camera (the one from the player scene, not for the main scene)

```
extends Camera


export var min_distance = 0.5
export var max_distance = 3.0
export var angle_v_adjust = 0.0
var collision_exception = []
var max_height = 2.0
var min_height = 0
onready var target_node: Spatial = get_parent()


func _ready():
    collision_exception.append(target_node.get_parent().get_rid())
    # Detaches the camera transform from the parent spatial node
    set_as_toplevel(true)


func _physics_process(_delta):
    var target_pos: Vector3 = target_node.global_transform.origin
    var camera_pos: Vector3 = global_transform.origin

    var delta_pos: Vector3 = camera_pos - target_pos

    # Regular delta follow

    # Check ranges
    if delta_pos.length() < min_distance:
        delta_pos = delta_pos.normalized() * min_distance
    elif delta_pos.length() > max_distance:
        delta_pos = delta_pos.normalized() * max_distance

    # Check upper and lower height
    delta_pos.y = clamp(delta_pos.y, min_height, max_height)
    camera_pos = target_pos + delta_pos

    look_at_from_position(camera_pos, target_pos, Vector3.UP)

    # Turn a little up or down
    var t = transform
    t.basis = Basis(t.basis[0], deg2rad(angle_v_adjust)) * t.basis
    transform = t
```


If you try that, your character will fall to the ground due to the physics, and you'll see a capsule rotating around the floor. To fix that, you have to go to the inspector (in your rigidbody) and lock the angular Axis. Example in the image below:






No comments:

Post a Comment