Implémenter le comportement du blaster est le processus de programmation d'un mécanisme d'explosion dans des expériences de tir à la première personne. Bien que les joueurs puissent tirer avec un simple clic ou une pression sur un bouton, créer un comportement d'explosion satisfaisant et précis est important car cela améliore le plaisir des joueurs dans le gameplay global.
En utilisant l'expérience de laser tag d'exemple comme référence, cette section du tutoriel vous apprend les scripts derrière l'implémentation du comportement du blaster pour deux types différents de blasters, y compris des conseils sur :
- Détecter quand les joueurs pressent le bouton d'explosion.
- Vérifier si le joueur peut utiliser son blaster s'il a récemment pressé le bouton d'explosion.
- Générer des données d'explosion qui disent au serveur qui a initié l'explosion, d'où elle vient et quelle était la destination finale de chaque faisceau laser.
- Notifier le serveur des données d'explosion afin qu'il puisse effectuer les actions appropriées si l'explosion entre en collision avec un autre joueur.
- Réinitialiser le blaster entre chaque explosion pour donner au blaster suffisamment de temps pour refroidir avant qu'il puisse exploser à nouveau.
Après avoir terminé cette section, vous apprendrez à connaître les scripts qui permettent au blaster de détecter quand ses explosions entrent en collision avec d'autres joueurs, puis à déduire le montant correspondant de santé selon chaque type de blaster.
Détecter l'entrée du joueur
La première étape pour implémenter le comportement du blaster est d'écouter lorsque qu'un joueur presse le bouton d'explosion. Le type d'entrée que les joueurs utilisent pour presser le bouton d'explosion dépend de l'appareil qu'ils utilisent pour accéder à l'expérience. Par exemple, l'expérience de laser tag d'exemple prend en charge les contrôles de souris et de clavier, les manettes et les contrôles tactiles. Vous pouvez voir chacun de ces types d'entrée dans ReplicatedStorage ⟩ UserInputHandler.
Ce script client utilise ContextActionService pour lier MouseButton1 et ButtonR2 à l'action d'explosion. Cela signifie qu'à chaque fois qu'un joueur presse le bouton gauche de la souris ou le bouton R2 d'une manette, cela déclenche un faisceau laser qui jaillit du blaster. Notez que le HUDGui contient un bouton pour exploser sur les appareils mobiles, auquel il se connecte plus tard dans le script.
UserInputHandlerContextActionService:BindAction("_", onBlasterActivated, false,Enum.UserInputType.MouseButton1,Enum.KeyCode.ButtonR2)
Une autre note importante est l'utilisation de Enum.UserInputState.Begin dans la définition de onBlasterActivated(). De nombreuses interactions de l'interface utilisateur, telles que le choix d'un blaster dans cet exemple, ne se produisent qu'après que le bouton de la souris se relève (Enum.UserInputState.End), ce qui donne aux utilisateurs une dernière chance d'éviter l'interaction. Cependant, un mécanisme d'explosion ne semble pas réactif à moins qu'il ne se produise l'instant où le bouton est enfoncé.
Pour démontrer, vous pouvez changer Enum.UserInputState.Begin en Enum.UserInputState.End, puis tester pour voir comment la réactivité de l'explosion impacte le gameplay de l'expérience. Par exemple, si les joueurs peuvent maintenir le bouton enfoncé sans déclencher l'explosion, comment cela pourrait-il changer leur expérience tout en marquant d'autres joueurs ?
UserInputHandler
local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- ligne mise à jour, assurez-vous de changer en retour
attemptBlastClient()
end
end
Vérifier si le joueur peut exploser
Après que UserInputHandler détecte une pression sur un bouton ou un tapotement d'écran, il appelle ReplicatedStorage ⟩ Blaster ⟩ attemptBlastClient pour vérifier si le joueur peut exploser ou non. Comme la plupart des vérifications dans l'expérience de laser tag d'exemple, cela se produit deux fois : d'abord sur le client, puis plus tard sur le serveur. attemptBlastClient appelle ensuite ReplicatedStorage ⟩ Blaster ⟩ canLocalPlayerBlast pour effectuer une vérification simple de l'attribut du joueur blasterStateClient :
canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
end
Si vous examinez ReplicatedStorage ⟩ Blaster ⟩ BlasterState, vous pouvez voir que l'expérience a trois états de blaster : Ready, Blasting, et Disabled. Pour voir l'effet de chacun de ces états, vous pouvez tester l'expérience, sélectionner votre joueur sous le service Players, puis observer l'attribut blasterStateClient dans la fenêtre Properties. Remarquez comment il affiche Disabled pendant que vous choisissez votre blaster, Ready la plupart du temps, et Blasting pendant moins d'une seconde après avoir pressé le bouton.
Cette légère pause vous empêche de pouvoir exploser aussi rapidement que vous pouvez cliquer. Par exemple, si vous changez la fonction pour toujours retourner vrai, vous pourrez rapidement faire exploser votre blaster sans aucun délai, ce qui n'est pas réaliste pour le gameplay de laser tag.
canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return true -- ligne mise à jour, assurez-vous de changer en retour
end
Générer des données d'explosion
Après avoir vérifié que le blaster du joueur est dans l'état Ready, attemptBlastClient appelle ReplicatedStorage ⟩ attemptBlastClient ⟩ blastClient. La première étape que blastClient effectue est de définir l'attribut du joueur blasterStateClient sur Blasting, ce qui évite le même cas de tir rapide d'avant.
L'étape suivante consiste à générer les données d'explosion. Si vous examinez ReplicatedStorage ⟩ Blaster ⟩ BlastData, vous pouvez voir que chaque explosion consiste en trois informations :
- Le joueur qui initie l'explosion.
- Un DataType.CFrame qui représente le point d'origine de l'explosion.
- Un tableau RayResult qui contient la destination finale de chaque faisceau laser et le joueur touché, s'il a touché un autre joueur.
Pour générer ces données, blastClient appelle ReplicatedStorage ⟩ attemptBlastClient ⟩ blastClient ⟩ generateBlastData, que vous pouvez examiner ci-dessous.
generateBlastData
local function generateBlastData(): BlastData.Type
local blasterConfig = getBlasterConfig()
local rayDirections = getDirectionsForBlast(
currentCamera.CFrame, blasterConfig)
local rayResults = castLaserRay(
localPlayer, currentCamera.CFrame.Position, rayDirections)
local blastData: BlastData.Type = {
player = localPlayer,
originCFrame = currentCamera.CFrame,
rayResults = rayResults,
}
return blastData
end
Cette fonction commence par utiliser getBlasterConfig pour récupérer le type de blaster du joueur. L'exemple fournit deux types de blasters : un qui produit plusieurs faisceaux avec une large diffusion horizontale, et un autre qui produit un seul faisceau. Vous pouvez trouver leurs configurations dans ReplicatedStorage ⟩ Instances ⟩ LaserBlastersFolder.
La fonction utilise ensuite currentCamera.CFrame comme point d'origine pour l'explosion, le passant à getDirectionsForBlast. À ce stade, le code ne concerne plus le blaster, mais le faisceau laser, dont vous apprendrez davantage dans la section détecter les coups du tutoriel. Enfin, après avoir créé le tableau rayResults, generateBlastData dispose de toutes les informations nécessaires pour renvoyer les données d'explosion à blastClient.
Notifier le serveur
Une fois que blastClient a des données complètes pour l'explosion, il déclenche deux événements :
blastClientlocal laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEventlocal laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEventlaserBlastedBindableEvent:Fire(blastData)laserBlastedEvent:FireServer(blastData)
Le BindableEvent notifie d'autres scripts client de l'explosion. Par exemple, ReplicatedStorage ⟩ FirstPersonBlasterVisuals utilise cet événement pour savoir quand afficher des effets visuels, tels que l'animation d'explosion et la barre de refroidissement. De même, le RemoteEvent notifie les scripts serveur de l'explosion, ce qui commence à traiter l'explosion dans ServerScriptService ⟩ LaserBlastHandler.
LaserBlastHandler
local function onLaserBlastedEvent(playerBlasted: Player, blastData: BlastData.Type)
local validatedBlastData = getValidatedBlastData(playerBlasted, blastData)
if not validatedBlastData then
return
end
if not canPlayerBlast(playerBlasted) then
return
end
blastServer(playerBlasted)
processTaggedPlayers(playerBlasted, blastData)
for _, replicateToPlayer in Players:GetPlayers() do
if playerBlasted == replicateToPlayer then
continue
end
replicateBlastEvent:FireClient(replicateToPlayer, playerBlasted, blastData)
end
end
Pour aider à prévenir la tricherie, le serveur doit vérifier toutes les données que chaque client envoie. Ces vérifications incluent :
- Est-ce que BlastData est un tableau ? Contient-il un Class.CFrame et un autre tableau nommé rayResults ?
- Le joueur a-t-il un blaster équipé ?
- Le joueur a-t-il un personnage et une position dans le monde ?
- Après avoir envoyé les données d'explosion, le joueur s'est-il déplacé d'une distance excessive depuis l'endroit où il a tiré le faisceau laser ?
Cette dernière vérification implique un jugement, et selon la latence du serveur et la vitesse de mouvement des joueurs, vous pourriez décider que différentes valeurs sont excessives pour votre propre expérience. Pour démontrer comment faire ce jugement, vous pouvez avoir un sens de l'ampleur typique du changement de position en ajoutant une instruction de print dans getValidatedBlastData et en testant l'expérience.
getValidatedBlastDatalocal distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Positionprint(distanceFromCharacterToOrigin.Magnitude) -- ligne mise à jour, assurez-vous de retirerif distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS thenwarn(`Player {player.Name} failed an origin sanity check while blasting`)returnend
En vous déplaçant et en explosant, notez la sortie. Cela pourrait ressembler à ceci :
1.90196299552917483.15495586395263672.57428836822509774.80445861816406252.6434271335601807
Si vous augmentez la vitesse de mouvement des joueurs dans ReplicatedStorage ⟩ PlayerStateHandler ⟩ togglePlayerMovement, alors testez à nouveau, vous rencontrerez probablement de nombreux échecs de vérification en raison d'un mouvement excessif entre les explosions.
togglePlayerMovementlocal ENABLED_WALK_SPEED = 60 -- ligne mise à jour, assurez-vous de changer en retour
Le serveur effectue ensuite les opérations suivantes :
- Valide rayResults.
- Vérifie si le joueur peut exploser.
- Réinitialise l'état du blaster.
- Réduit la santé des joueurs marqués.
- Réplique l'explosion à tous les autres joueurs afin qu'ils puissent voir des visuels en tiers.
Pour plus d'informations sur ces opérations serveur, voir la section détecter les coups du tutoriel.
Réinitialiser le blaster
Dans l'expérience de laser tag d'exemple, les blasters utilisent un mécanisme de surchauffe. Plutôt que de recharger après un nombre défini d'explosions, ils ont besoin de temps pour "refroidir" entre chaque explosion. Ce même délai de refroidissement se produit à la fois sur le client (blastClient) et le serveur (blastServer), le serveur agissant comme la source de vérité.
blastServer
local blasterConfig = getBlasterConfig(player)
local secondsBetweenBlasts = blasterConfig:GetAttribute("secondsBetweenBlasts")
task.delay(secondsBetweenBlasts, function()
local currentState = player:GetAttribute(PlayerAttribute.blasterStateServer)
if currentState == BlasterState.Blasting then
player:SetAttribute(PlayerAttribute.blasterStateServer, BlasterState.Ready)
end
end)
L'attribut secondsBetweenBlasts fait partie de la configuration du blaster dans ReplicatedStorage ⟩ Instances ⟩ LaserBlastersFolder. Après que le délai secondsBetweenBlasts passe, le joueur peut à nouveau exploser, et l'ensemble du processus se répète. Pour aider le joueur à comprendre quand il peut exploser à nouveau, l'expérience inclut une barre de refroidissement.
À ce stade, les joueurs peuvent apparaître et réapparaître, viser et exploser, mais l'expérience doit encore déterminer les résultats de chaque explosion. Dans la prochaine section du tutoriel, vous apprendrez à programmer la capacité pour le blaster de détecter quand l'explosion touche un autre joueur, puis à réduire le montant approprié de santé des joueurs selon les paramètres du blaster.