Voeg grenzen toe met Mathf.Clamp en maak beweging vloeiender met interpolation
Overzicht
Je ruimteschip beweegt nu, maar het kan buiten het speelveld vliegen! In dit hoofdstuk voeg je grenzen toe, maak je de beweging vloeiender, en zorg je dat het schip binnen het zichtbare gebied blijft.
Hoogtegrenzen toevoegen (clamping)
Het ruimteschip kan nu te hoog vliegen of door de grond crashen! Voeg verticale grenzen toe.
Voeg height clamping toe na MoveAndSlide() aan het einde van _PhysicsProcess():
// ... bestaande movement code ...Velocity=movement;MoveAndSlide(); // Beperk hoogte (niet te hoog, niet door de grond)floatclampedY=Mathf.Clamp(Position.Y,0.5f,_maxHeight);Position=newVector3(Position.X,clampedY,Position.Z);}
Bereken een "geclamped" Y-positie die tussen 0.5 (grondniveau) en _maxHeight ligt. Pas daarna de Position aan met deze nieuwe Y-waarde.
Test met F6. Probeer te hoog of te laag te vliegen - het schip stopt bij de grenzen!
Banking effect toevoegen
Laat het schip visueel laten kantelen (banken) wanneer het draait. Dit maakt de beweging veel realistischer - net zoals een vliegtuig kantelt tijdens een bocht!
Nieuwe Godot-specifieke elementen:
Rotation.Z - De roll rotatie (kantelen links/rechts) in radialen
Mathf.DegToRad(degrees) - Converteert graden naar radialen (Godot gebruikt radialen voor rotatie)
Voeg een bank angle variabele toe:
Voeg een turnInput variabele toe bovenaan _PhysicsProcess():
Dit houdt bij in welke richting je draait (-1, 0, of 1).
Pas de turning code aan om turnInput bij te houden. Verander de if statements naar if/else if:
Oude code (verwijder dit):
Nieuwe code (voeg dit toe):
Voeg het banking effect toe na de turning code, maar voor de vertical movement:
Bereken de gewenste bankhoek (in graden), converteer naar radialen, en pas Rotation.Z aan.
Test met F6. Draai naar links en rechts - het schip bankt nu als een vliegtuig!
Waarom turnInput? Sla de turn richting op (-1, 0, of 1) om het schip in die richting te laten kantelen. Als je naar links draait (turnInput = 1), kantelt het schip naar links (positieve bank angle). Experimenteer met Bank Angle in de Inspector!
Smooth banking met interpolatie
Het banking effect is nu instant - het schip springt direct naar de volle bank angle. Maak dit vloeiender met interpolatie (lerping)!
a = startwaarde, b = doelwaarde, weight = hoe ver tussen de twee (0 tot 1)
Bij weight = 0 krijg je a, bij weight = 1 krijg je b, bij 0.5 krijg je het midden
Door weight als bankSpeed * delta te gebruiken krijg je een vloeiende, frame-rate onafhankelijke transitie
De transitie speed is afhankelijk van bankSpeed (instelbaar in de Inspector!)
Converteren in radians - Rotation.Z werkt altijd met radialen, dus we moeten bankAngle (in graden) converteren met Mathf.DegToRad(). Houd bankAngle in de Inspector in graden omdat dat intuïtiever is (30 vs ~0.52)
Voeg een bankSpeed variabele toe:
Vervang de banking code door een versie met smooth interpolatie:
Oude code (verwijder dit):
Nieuwe code (voeg dit toe):
Nu converteren we _bankAngle meteen naar radialen en gebruiken Mathf.Lerp() om geleidelijk van de huidige hoek naar de doelhoek te bewegen.
Test met F6. Draai en laat los - het schip bankt nu vloeiend in en uit!
Smooth boost met interpolatie
In het vorige hoofdstuk heb je een boost functie toegevoegd, maar de snelheidsverandering was abrupt en voelde niet vloeiend aan. Verbeter dit met interpolatie - net zoals je bij de banking deed!
Nieuwe Godot-specifieke elementen:
Smooth speed transitie met Lerp - We interpoleren van de huidige speed naar de target speed
Boost transitie speed
Voeg twee nieuwe variabelen toe:
De _boostTransitionSpeed bepaalt hoe snel de boost in- en uitfade. De _currentSpeed houdt bij wat de huidige snelheid is (start automatisch op 0).
Vervang de instant boost door een smooth interpolatie:
Oude code (verwijder dit):
Nieuwe code (voeg dit toe):
Bereken eerst de gewenste snelheid (targetSpeed), interpoleer dan geleidelijk naar die snelheid, en gebruik de geïnterpoleerde snelheid voor movement.
Test met F6. Hou de spatiebalk ingedrukt en laat los - het schip versnelt en vertraagt nu op een vloeiende manier! Probeer verschillende waarden voor boostTransitionSpeed in de Inspector!
Complete Script
Klik hier voor het volledige PlayerController.cs script
// Auto-forward movement met optionele boost
float currentSpeed = _forwardSpeed;
if (Input.IsActionPressed("boost"))
currentSpeed *= _boostMultiplier;
movement += Transform.Basis.Z * -currentSpeed;
// Bepaal target snelheid: boost of normaal
float targetSpeed = _forwardSpeed;
if (Input.IsActionPressed("boost"))
targetSpeed *= _boostMultiplier;
// Smooth transitie naar target speed
_currentSpeed = Mathf.Lerp(_currentSpeed, targetSpeed, _boostTransitionSpeed * (float)delta);
// Auto-forward movement met smooth boost
movement += Transform.Basis.Z * -_currentSpeed;
using Godot;
public partial class PlayerController : CharacterBody3D
{
[Export] private float _forwardSpeed = 10f;
[Export] private float _turnSpeed = 2f;
[Export] private float _verticalSpeed = 5f;
[Export] private float _boostMultiplier = 1.2f;
[Export] private float _maxHeight = 4f;
[Export] private float _bankAngle = 30f;
[Export] private float _bankSpeed = 5f;
[Export] private float _boostTransitionSpeed = 3f;
private float _currentSpeed;
public override void _PhysicsProcess(double delta)
{
Vector3 movement = Vector3.Zero;
float turnInput = 0f;
// Bepaal target snelheid: boost of normaal
float targetSpeed = _forwardSpeed;
if (Input.IsActionPressed("boost"))
targetSpeed *= _boostMultiplier;
// Smooth transitie naar target speed
_currentSpeed = Mathf.Lerp(_currentSpeed, targetSpeed, _boostTransitionSpeed * (float)delta);
// Auto-forward movement met smooth boost
movement += Transform.Basis.Z * -_currentSpeed;
// Links/Rechts - draai het schip EN kantel het
if (Input.IsActionPressed("move_left"))
{
Rotation = new Vector3(Rotation.X, Rotation.Y + _turnSpeed * (float)delta, Rotation.Z);
turnInput = 1f;
}
else if (Input.IsActionPressed("move_right"))
{
Rotation = new Vector3(Rotation.X, Rotation.Y - _turnSpeed * (float)delta, Rotation.Z);
turnInput = -1f;
}
// Smooth banking: interpoleer tussen huidige en target angle
float targetBankAngle = turnInput * Mathf.DegToRad(_bankAngle);
float newBankAngle = Mathf.Lerp(Rotation.Z, targetBankAngle, _bankSpeed * (float)delta);
Rotation = new Vector3(
Rotation.X,
Rotation.Y,
newBankAngle
);
// Omhoog/Omlaag (Y-as)
if (Input.IsActionPressed("move_up"))
movement.Y += _verticalSpeed;
if (Input.IsActionPressed("move_down"))
movement.Y -= _verticalSpeed;
// Pas de Velocity aan en beweeg met physics
Velocity = movement;
MoveAndSlide();
// Beperk hoogte (niet te hoog, niet door de grond)
float clampedY = Mathf.Clamp(Position.Y, 0.5f, _maxHeight);
Position = new Vector3(Position.X, clampedY, Position.Z);
}
}