>
Guide 2026-05-13

Système de trains et transports publics pour FiveM

OntelMonke

OntelMonke

Développeur et créateur de contenu chez Agency Scripts

Les transports publics comme infrastructure de serveurs

Un système de train et de transports publics transforme ton serveur FiveM d'une ville centrée sur l'automobile en une zone métropolitaine vivante dotée de transports en commun fonctionnels. Les trains circulant selon les horaires du réseau ferroviaire existant de la région du Grand Toronto, les bus suivant les itinéraires à travers les rues de la ville et les stations de métro permettant des déplacements rapides entre les quartiers contribuent tous à un monde véritablement vivant. Les transports publics profitent à tous les joueurs du serveur, quels que soient leur richesse ou leur emploi. Les nouveaux joueurs qui n’ont pas les moyens d’acheter une voiture peuvent prendre le bus pour se rendre sur les lieux de travail. Les joueurs expérimentés utilisent le métro pendant les heures de pointe pour éviter les routes encombrées. Les joueurs criminels utilisent les transports en commun pour se déplacer dans la ville sans véhicule personnel traçable. Le système de transport crée également des opportunités d'emploi uniques pour les chauffeurs de bus, les conducteurs de train et le personnel des autorités de transport qui maintiennent les horaires, collectent les tarifs et gèrent les incidents sur le réseau. D'un point de vue technique, les trains et les bus qui circulent sur des itinéraires cohérents peuplent le monde d'entités en mouvement qui donnent l'impression que la ville est occupée sans nécessiter de nombre de joueurs supplémentaire.

Configuration des itinéraires et des horaires des trains

GTA V dispose d'un réseau ferroviaire intégré qui entoure la carte, et ton système ferroviaire doit exploiter ces voies existantes pour une compatibilité maximale. Définissez les itinéraires des trains comme des séquences d'arrêts en gare le long de la voie avec des heures d'arrivée et de départ calculées à partir de la vitesse moyenne du train entre les gares. Chaque station a besoin d'une zone de quai où les joueurs montent et sortent, d'un point d'interaction avec un distributeur de billets et de panneaux d'affichage indiquant les arrivées à venir. Configurez plusieurs services ferroviaires qui fonctionnent simultanément sur différents segments du réseau, avec des horaires qui se répètent selon un cycle configurable correspondant à la progression jour-nuit de ton serveur :

Config.TrainSystem = {
    ticketPrice = 50,
    speedMultiplier = 1.0,
    despawnDistance = 500.0,
    announceArrival = true,
    announceDeparture = true,
}

Config.TrainRoutes = {
    ['metro_line_1'] = {
        label = 'Metro Line 1 - City Loop',
        model = 'metrotrain',
        carriages = 3,
        frequency = 300,  -- seconds between departures
        stations = {
            {
                name = 'Los Santos Central',
                coords = vector3(268.09, -1204.28, 38.90),
                platform = vector3(264.55, -1200.12, 38.90),
                stopDuration = 20,
                announceText = 'Now arriving at Los Santos Central Station',
            },
            {
                name = 'Strawberry',
                coords = vector3(36.81, -1393.78, 29.36),
                platform = vector3(40.22, -1389.45, 29.36),
                stopDuration = 15,
                announceText = 'Now arriving at Strawberry Station',
            },
            {
                name = 'Del Perro',
                coords = vector3(-1359.88, -474.17, 15.02),
                platform = vector3(-1355.44, -470.89, 15.02),
                stopDuration = 15,
                announceText = 'Now arriving at Del Perro Station',
            },
            {
                name = 'Rockford Hills',
                coords = vector3(-512.47, -680.33, 33.42),
                platform = vector3(-508.12, -676.88, 33.42),
                stopDuration = 15,
                announceText = 'Now arriving at Rockford Hills Station',
            },
            {
                name = 'Burton',
                coords = vector3(-283.66, -324.78, 10.07),
                platform = vector3(-279.33, -321.44, 10.07),
                stopDuration = 15,
                announceText = 'Now arriving at Burton Station',
            },
        },
    },
}

Config.BusRoutes = {
    ['route_1'] = {
        label = 'Route 1 - Downtown Express',
        model = 'bus',
        frequency = 180,
        stops = {
            { name = 'Legion Square', coords = vector3(208.24, -935.88, 30.69),
              stopDuration = 12 },
            { name = 'Pillbox Hospital', coords = vector3(311.44, -592.33, 43.29),
              stopDuration = 12 },
            { name = 'Alta Street', coords = vector3(-226.87, -381.44, 30.05),
              stopDuration = 12 },
            { name = 'Vinewood Blvd', coords = vector3(302.33, 193.67, 104.38),
              stopDuration = 12 },
        },
    },
}

Le frequency La valeur détermine la fréquence à laquelle un nouveau train part de la première gare de l'itinéraire. Plusieurs trains peuvent circuler simultanément sur le même itinéraire, espacés de l’intervalle de fréquence. Le stopDuration à chaque gare donne aux joueurs suffisamment de temps pour embarquer ou sortir, avec une annonce audio diffusée à l'arrivée du train et un carillon d'avertissement de départ quelques secondes avant son départ.

Former l'apparition et le mouvement des entités

La génération et le contrôle des trains dans FiveM nécessitent des fonctions natives spécifiques qui diffèrent de la gestion habituelle des véhicules. Utiliser CreateMissionTrain pour faire apparaître des trains sur le réseau ferroviaire, ce qui les place automatiquement sur la voie la plus proche et gère le suivi physique des rails. Contrôlez la vitesse des trains avec SetTrainSpeed et SetTrainCruiseSpeed, et arrêter les trains dans les gares en réduisant progressivement la vitesse à mesure qu'ils s'approchent des coordonnées du quai. Le train doit s'arrêter précisément à la position du quai afin que les portes soient alignées avec les zones d'embarquement, ce qui nécessite des calculs minutieux de réduction de vitesse en fonction de la distance jusqu'à la gare suivante :

local activeTrains = {}

function SpawnTrain(routeId)
    local route = Config.TrainRoutes[routeId]
    if not route then return end

    local firstStation = route.stations[1]
    local variation = 24  -- metro train variation

    -- Create the mission train
    local train = CreateMissionTrain(variation, firstStation.coords.x,
        firstStation.coords.y, firstStation.coords.z, true)

    if not DoesEntityExist(train) then
        print('[Transit] Failed to spawn train for route: ' .. routeId)
        return
    end

    SetTrainSpeed(train, 0.0)
    SetTrainCruiseSpeed(train, 0.0)
    SetEntityAsMissionEntity(train, true, true)

    -- Store train state
    activeTrains[routeId] = {
        entity = train,
        route = route,
        currentStation = 1,
        state = 'stopped',  -- stopped, departing, moving, arriving
        stateTimer = GetGameTimer(),
        passengers = {},
    }

    return train
end

-- Train movement controller
CreateThread(function()
    while true do
        for routeId, trainData in pairs(activeTrains) do
            local train = trainData.entity
            if not DoesEntityExist(train) then
                activeTrains[routeId] = nil
                goto continue
            end

            local station = trainData.route.stations[trainData.currentStation]
            local elapsed = GetGameTimer() - trainData.stateTimer

            if trainData.state == 'stopped' then
                if elapsed >= (station.stopDuration * 1000) then
                    -- Depart from station
                    trainData.state = 'departing'
                    trainData.stateTimer = GetGameTimer()
                    AnnounceToPassengers(trainData, 'Doors closing. Next stop: '
                        .. GetNextStationName(trainData))
                end

            elseif trainData.state == 'departing' then
                local speed = math.min(15.0, elapsed * 0.005)
                SetTrainCruiseSpeed(train, speed)
                SetTrainSpeed(train, speed)
                if speed >= 15.0 then
                    trainData.state = 'moving'
                end

            elseif trainData.state == 'moving' then
                local nextIdx = trainData.currentStation + 1
                if nextIdx > #trainData.route.stations then
                    nextIdx = 1
                end
                local nextStation = trainData.route.stations[nextIdx]
                local trainCoords = GetEntityCoords(train)
                local dist = #(trainCoords - nextStation.coords)

                if dist < 200.0 then
                    trainData.state = 'arriving'
                    trainData.stateTimer = GetGameTimer()
                    AnnounceToPassengers(trainData, nextStation.announceText)
                end

            elseif trainData.state == 'arriving' then
                local nextIdx = trainData.currentStation + 1
                if nextIdx > #trainData.route.stations then
                    nextIdx = 1
                end
                local nextStation = trainData.route.stations[nextIdx]
                local trainCoords = GetEntityCoords(train)
                local dist = #(trainCoords - nextStation.coords)

                -- Gradually slow down
                local speed = math.max(0.0, dist * 0.08)
                SetTrainCruiseSpeed(train, speed)
                SetTrainSpeed(train, speed)

                if dist < 3.0 then
                    SetTrainSpeed(train, 0.0)
                    SetTrainCruiseSpeed(train, 0.0)
                    trainData.currentStation = nextIdx
                    trainData.state = 'stopped'
                    trainData.stateTimer = GetGameTimer()
                end
            end

            ::continue::
        end
        Wait(100)
    end
end)

Embarquement et billetterie des passagers

Lorsqu'un train s'arrête à une gare, affichez des invites d'interaction aux joueurs à proximité leur permettant de monter à bord. Vérifiez que le joueur dispose d'un billet ou d'un titre de transport valide avant de lui permettre d'entrer. Les billets peuvent être achetés auprès des distributeurs de billets de chaque gare à l'aide d'une interface simple NUI qui affiche les itinéraires disponibles et les prix. Une fois à bord, téléportez le joueur à l'intérieur du wagon et définissez sa position par rapport à l'entité du train afin qu'il se déplace avec elle. Les intérieurs de train intégrés de GTA fonctionnent pour les implémentations de base, mais les intérieurs personnalisés utilisant des objets ou des instances attachés offrent une meilleure expérience avec des sièges, des zones debout et des fenêtres qui montrent le paysage qui passe. Suivez la gare dans laquelle chaque passager est monté à bord afin que le système puisse calculer les différences tarifaires pour une tarification basée sur la distance. Affichez le nom de la prochaine gare et l'heure d'arrivée estimée à l'intérieur du wagon via un élément de texte 3D ou un écran NUI joint qui se met à jour à mesure que le train progresse le long de son itinéraire.

Système de bus et pilotes PNJ

Les bus complètent le réseau ferroviaire en couvrant les zones inaccessibles par le rail. Générez des bus pilotés par des PNJ qui suivent des itinéraires prédéfinis à travers les rues de la ville, en s'arrêtant aux arrêts de bus marqués pour prendre et déposer les joueurs. Le pilote NPC utilise le système de tâches de GTA pour naviguer entre les arrêts en utilisant TaskVehicleDriveToCoordLongrange avec des drapeaux de conduite appropriés pour respecter le code de la route et s'arrêter aux endroits désignés. À chaque arrêt, le bus attend pendant une durée configurée pendant que les joueurs montent ou sortent, puis le chauffeur PNJ continue jusqu'à l'arrêt suivant. Affichez les informations sur l'itinéraire sur les accessoires de l'arrêt de bus, indiquant le numéro de l'itinéraire, la destination et le temps d'attente estimé jusqu'à l'arrivée du prochain bus. Pour une variante exploitée par les joueurs, permettez aux joueurs occupant le poste d'autorité de transport de conduire des bus manuellement, gagnant ainsi un salaire par passager transporté et une prime pour le respect des horaires.

Carte des transports en commun et interface utilisateur de la gare

Créez une carte des transports en commun à laquelle les joueurs peuvent accéder depuis leur téléphone, les kiosques des gares ou les écrans des arrêts de bus. La carte doit montrer tous les itinéraires actifs codés par couleur par ligne, les emplacements des gares avec des indicateurs d'échange où plusieurs lignes se connectent et les positions des trains en temps réel mises à jour toutes les quelques secondes. L'interface utilisateur de la station dans les kiosques doit afficher l'heure actuelle, les prochaines arrivées pour chaque ligne desservant cette station, toute interruption ou retard de service, ainsi qu'une interface d'achat de billets. Implémentez la carte des transports en commun sous la forme d'une superposition NUI qui restitue le réseau ferroviaire de manière schématique plutôt que géographique, à l'instar des cartes de métro du monde réel qui privilégient la clarté plutôt que la précision géographique. Ajoutez des indicateurs en temps réel indiquant la position actuelle de chaque train sous la forme d'un point mobile le long de son itinéraire, donnant aux joueurs un retour immédiat sur le temps dont ils ont besoin pour attendre le prochain service.

Système tarifaire et laissez-passer de transport en commun

Mettez en œuvre un système tarifaire à plusieurs niveaux avec des billets aller simple, des pass journaliers et des abonnements mensuels. Les billets simples coûtent le tarif de base et expirent après un voyage. Les pass journaliers permettent des trajets illimités pendant vingt-quatre heures de jeu à un prix fixe qui devient économique après trois ou quatre voyages. Les laissez-passer mensuels offrent le meilleur rapport qualité-prix par trajet pour les navetteurs réguliers et sont stockés en tant qu'élément dans l'inventaire du joueur avec un horodatage d'expiration. Validez les tarifs aux portes d'entrée des gares à l'aide d'interactions cibles sur les supports de tourniquet et dans les bus grâce à l'interaction du conducteur lors de l'embarquement. Pour une tarification basée sur la distance, calculez le tarif à la sortie du passager en fonction du nombre de gares parcourues. Les joueurs sans billet valide qui sont arrêtés lors d'inspections aléatoires par le personnel de la société de transport reçoivent des amendes, ce qui ajoute un gameplay d'application du travail de la société de transport.

Performances et synchronisation

Les trains et les bus sont de grandes entités qui doivent être synchronisées entre tous les clients, ce qui en fait des fonctionnalités sensibles aux performances qui nécessitent une optimisation minutieuse. Utilisez la gestion de l'état côté serveur pour contrôler les positions des trains et diffuser des mises à jour aux clients, permettant à chaque client de restituer l'entité du train localement en fonction des coordonnées reçues. Supprimez les entités de train pour les joueurs éloignés de toute gare ou voie ferrée afin de réduire les frais de rendu, et ne les faites apparaître que lorsqu'un joueur entre à proximité du réseau ferroviaire. Les conducteurs de bus PNJ ne devraient être activement chargés que lorsque les joueurs sont à proximité, les bus distants utilisant une interpolation de position simplifiée plutôt qu'une recherche de chemin complète par l'IA. Limitez le nombre total d’entités de train et de bus simultanées sur le serveur pour éviter toute dégradation des performances pendant les heures de pointe. Échelonnez les heures de départ sur différents itinéraires afin que plusieurs véhicules n'apparaissent pas simultanément. Nettoyez toutes les entités de transport en commun au redémarrage de la ressource et implémentez une logique de récupération qui recalcule les positions des trains en fonction de l'horaire au démarrage de la ressource, afin que les trains apparaissent immédiatement aux emplacements corrects plutôt que de partir de la première gare à chaque fois.

Partager cet article

Prêt à améliorer votre serveur ?

Découvrez nos scripts FiveM premium dans la boutique Agency Scripts ou rejoignez notre communauté Discord pour le support et les mises à jour.