Catégories
Jeu vidéo ROBLOX ROBLOX-NIVEAU02

Déplacer une Part avec vitesse réelle et arrêt précis

Voir le tutoriel : Déplacer une Part avec la Physique Roblox

Apprendre une version avancée de la fonction mouvement qui :

  1. Calcule le déplacement restant frame par frame (comme Pythagore en 3D).
  2. S’arrête exactement sur la cible (sans la dépasser).
  3. Donne à la Part une vélocité physique réelle pendant le mouvement.
  4. Utilise CustomPhysicalProperties pour contrôler la physique de la Part.

Introduction : Qu’est-ce qui change par rapport au tutoriel précédent ?

Dans le tutoriel précédent, la fonction mouvement fonctionnait ainsi :

  • On calculait un déplacement fixe : direction * speed * deltaTime.
  • On s’arrêtait quand la distance parcourue dépassait ou atteignait la cible.
  • Problème : à la dernière frame, la Part pouvait dépasser légèrement la cible (elle ne s’arrêtait pas pile au bon endroit).

Dans ce nouveau script, on corrige ce problème et on ajoute des améliorations :

AspectTutoriel précédentCe tutoriel
CibleOn mesure la distance depuis le départ.On mesure la distance restante jusqu’à la cible.
Dernière frameLa Part peut dépasser la cible.math.min permet de s’arrêter exactement sur la cible.
PositionModifiée avec part.Position.Modifiée avec part.CFrame = CFrame.new(newPosition).
PhysiqueAucune vélocité.On donne une vélocité réelle (AssemblyLinearVelocity) à la Part.
DirectionNormalisée dès le départ avec direction.Unit.Calculée à chaque frame avec toTarget.Unit.
ArrêtVitesse « coupée » brutalement.Vélocité remise à zéro proprement à l’arrêt.

Préparation dans Roblox Studio

  1. Dans Workspace, crée un dossier Folder.
  2. Ajoute une Part nommée Part dans ce dossier.
  3. Crée un Script dans ServerScriptService et copie-y le code.
  4. Lance le jeu :
    • Après 5 secondes, la Part monte (axe Y) à 30 studs/seconde.
    • Elle s’arrête exactement après 100 unités, sans dépasser.

Script Commenté :

-- Récupérer le service RunService pour utiliser Heartbeat
local RunService = game:GetService("RunService")

-- Récupérer le dossier "Folder" et la Part à déplacer
local folder = workspace:WaitForChild("Folder")
local part = folder:WaitForChild("Part")

-- Configurer les propriétés physiques personnalisées de la Part
part.CustomPhysicalProperties = PhysicalProperties.new(
    1,   -- Density (densité) : masse par unité de volume
    0.3, -- Friction (frottement) : glisse un peu sur les surfaces
    0,   -- Elasticity (rebond) : ne rebondit pas du tout
    1,   -- FrictionWeight : importance du frottement
    1    -- ElasticityWeight : importance du rebond
)

-- Fonction pour déplacer une Part jusqu'à une cible, à vitesse contrôlée
-- Paramètres :
--   part : la Part à déplacer
--   targetDistance : distance totale à parcourir
--   direction : direction du mouvement (Vector3)
--   speed : vitesse en studs par seconde
local function mouvement(part, targetDistance, direction, speed)
    -- Ancrer la Part pour la contrôler manuellement (pas de gravité pendant le mouvement)
    part.Anchored = true

    -- Stocker la position de départ
    local startPosition = part.Position

    -- Calculer la position de la cible (point d'arrivée)
    local target = startPosition + (direction * targetDistance)

    -- Variable pour stocker la connexion à Heartbeat
    local connection
    connection = RunService.Heartbeat:Connect(function(deltaTime)
        -- Position actuelle de la Part
        local currentPosition = part.Position

        -- Vecteur restant jusqu'à la cible
        local toTarget = target - currentPosition

        -- Distance restante : longueur du vecteur toTarget
        -- C'est le théorème de Pythagore en 3D :
        -- distance = racine(x^2 + y^2 + z^2)
        local remainingDistance = toTarget.Magnitude

        -- Distance qu'on peut réellement parcourir cette frame :
        -- on prend la PLUS PETITE valeur entre (speed * deltaTime) et (remainingDistance)
        -- --> évite de dépasser la cible à la dernière frame !
        local step = math.min(speed * deltaTime, remainingDistance)

        -- Direction unitaire (longueur 1) vers la cible
        local moveDirection = toTarget.Unit

        -- Nouvelle position : position actuelle + direction * step
        local newPosition = currentPosition + moveDirection * step

        -- Appliquer la nouvelle position via CFrame
        part.CFrame = CFrame.new(newPosition)

        -- Donner à la Part une vélocité réelle correspondant au déplacement effectué
        -- velocity = déplacement / temps
        -- Cela rend le mouvement "visible" pour la physique de Roblox
        part.AssemblyLinearVelocity = (newPosition - currentPosition) / deltaTime

        -- Si la distance restante est plus petite que le pas, on est arrivé !
        if remainingDistance <= step then
            -- Remettre la vélocité à zéro (arrêt propre)
            part.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
            -- Déconnecter Heartbeat pour arrêter le mouvement
            connection:Disconnect()
        end
    end)
end

-- Attendre 5 secondes avant de commencer
task.wait(5)

-- Paramètres du mouvement
local speed1 = 30                     -- 30 studs par seconde
local direction1 = Vector3.new(0, 1, 0) -- Direction : vers le haut (axe Y)
local targetDistance1 = 100           -- 100 unités à parcourir

-- Lancer le mouvement
mouvement(part, targetDistance1, direction1, speed1)

Explications Détaillées

1. Les propriétés physiques personnalisées

part.CustomPhysicalProperties = PhysicalProperties.new(1, 0.3, 0, 1, 1)
  • PhysicalProperties.new permet de contrôler exactement le comportement physique de la Part :
ParamètreValeurSignification
Density (densité)1Poids de la Part par unité de volume.
Friction (frottement)0.3Elle glisse un peu sur les surfaces (0 = glisse parfaitement, 1 = accroche).
Elasticity (rebond)0Elle ne rebondit pas du tout (0 = pas de rebond).
FrictionWeight1Importance de notre frottement face aux autres surfaces.
ElasticityWeight1Importance de notre rebond face aux autres surfaces.
  • Pourquoi c’est utile ici ?
    • Comme on donne une vélocité à la Part, on veut contrôler comment elle réagirait en cas de collision (pas de rebond, frottement connu).

2. Calculer la distance restante (Pythagore en 3D)

local toTarget = target - currentPosition
local remainingDistance = toTarget.Magnitude
  • target - currentPosition :
    • Vecteur qui pointe de la position actuelle vers la cible.
  • .Magnitude :
    • Longueur de ce vecteur = distance restante.
    • C’est le théorème de Pythagore en 3D :
      distance = √(x² + y² + z²)
  • Différence avec le tutoriel précédent :
    • Avant : on mesurait la distance depuis le départ (distance parcourue).
    • Maintenant : on mesure la distance restant jusqu’à la cible.
    • C’est plus précis : même si la Part était déplacée par autre chose, le calcul resterait juste !

3. math.min : le secret de l’arrêt exact

local step = math.min(speed * deltaTime, remainingDistance)
  • math.min(a, b) retourne la plus petite des deux valeurs.
  • Deux cas possibles :
CasComparaisonRésultat
Milieu du mouvementspeed * deltaTime < remainingDistanceOn avance normalement de speed * deltaTime.
Dernière framespeed * deltaTime > remainingDistanceOn avance exactement de remainingDistance → on tombe pile sur la cible !
  • Exemple concret :
    • Il reste 0.4 studs à parcourir, mais speed * deltaTime = 0.5.
    • Ancienne méthode : on avancerait de 0.5 → la Part dépasse la cible de 0.1 !
    • Nouvelle méthode : math.min(0.5, 0.4) = 0.4 → la Part s’arrête exactement sur la cible.

4. Déplacer avec CFrame

part.CFrame = CFrame.new(newPosition)
  • CFrame.new(position) crée un CFrame (position + rotation) à la position donnée.
  • Différence avec part.Position = newPosition :
    • Position ne déplace que la position géométrique de la Part.
    • CFrame déplace toute la Part de manière complète (utile pour les Model et les assemblies).
  • Les deux fonctionnent ici, mais CFrame est la méthode recommandée pour déplacer des objets dans Roblox.

5. La vélocité réelle

part.AssemblyLinearVelocity = (newPosition - currentPosition) / deltaTime
  • Pourquoi faire ça alors que la Part est ancrée ?
    • La formule de la vitesse : vitesse = distance / temps.
    • Ici : déplacement de la frame ÷ durée de la frame = vélocité exacte en studs/seconde.
    • Cela informe le moteur physique de Roblox sur le mouvement réel de la Part.
    • Avantage : si un joueur touche la Part pendant son déplacement, les collisions et les effets seront cohérents avec le mouvement réel.

6. L’arrêt propre

if remainingDistance <= step then
    part.AssemblyLinearVelocity = Vector3.new(0, 0, 0)
    connection:Disconnect()
end
  • Condition : si la distance restante est plus petite que (ou égale à) le pas, c’est qu’on est arrivé.
  • On remet la vélocité à zéro (Vector3.new(0, 0, 0)) pour un arrêt propre, puis on déconnecte Heartbeat.

QCM : Teste ta compréhension !

Sur les différences avec le tutoriel précédent :

  1. Quelle est la principale amélioration de ce script par rapport au précédent ?
    • a) La Part s’arrête exactement sur la cible grâce à math.min.
    • b) La Part va plus vite.
    • c) La Part change de couleur.
  1. Dans le tutoriel précédent, quel problème pouvait survenir à la dernière frame ?
    • a) La Part pouvait dépasser légèrement la cible.
    • b) La Part ne bougeait pas.
    • c) La Part disparaissait.
  1. Comment mesure-t-on la distance dans ce script ?
    • a) La distance restante jusqu’à la cible (toTarget.Magnitude).
    • b) La distance parcourue depuis le départ.
    • c) On ne mesure pas la distance.

Sur math.min :

  1. Que fait math.min(0.5, 0.4) ?
    • a) Retourne 0.4 (la plus petite valeur).
    • b) Retourne 0.5 (la plus grande valeur).
    • c) Retourne 0.9 (la somme).
  1. Pourquoi math.min est-il essentiel ici ?
    • a) Pour éviter que la Part dépasse la cible à la dernière frame.
    • b) Pour accélérer la Part.
    • c) Pour changer la couleur de la Part.

Sur la physique :

  1. Que fait part.CustomPhysicalProperties = PhysicalProperties.new(1, 0.3, 0, 1, 1) ?
    • a) Définit la densité, le frottement et le rebond de la Part.
    • b) Définit la couleur de la Part.
    • c) Déplace la Part.
  1. Que signifie Elasticity = 0 dans les propriétés physiques ?
    • a) La Part ne rebondit pas du tout.
    • b) La Part rebondit parfaitement.
    • c) La Part est invisible.
  1. Pourquoi calcule-t-on AssemblyLinearVelocity = (newPosition - currentPosition) / deltaTime ?
    • a) Pour donner à la Part une vitesse physique réelle (distance / temps).
    • b) Pour téléporter la Part.
    • c) Pour changer la couleur de la Part.
  1. Pourquoi remet-on AssemblyLinearVelocity à Vector3.new(0, 0, 0) à l’arrêt ?
    • a) Pour un arrêt propre de la Part.
    • b) Pour redémarrer le mouvement.
    • c) Pour supprimer la Part.
  1. Quel est l’avantage de mesurer la distance restante plutôt que la distance parcourue ?
    • a) Le calcul reste correct même si la Part est déplacée par autre chose en cours de route.
    • b) Le script est plus court.
    • c) La Part va plus vite