ブラスターの動作を実装する

*このコンテンツは、ベータ版のAI(人工知能)を使用して翻訳されており、エラーが含まれている可能性があります。このページを英語で表示するには、 こちら をクリックしてください。

ブラスターの動作を実装することは、ファーストパーソンシューティングゲームにおけるブラスターメカニクスをプログラミングするプロセスです。プレイヤーはボタンを1回クリックまたは押すことでブラスターを発射できますが、満足のいく正確なブラスターの動作を作成することは、プレイヤーのゲームプレイ全体の楽しみを高めるために重要です。

サンプルレーザータグゲームを参考にして、このチュートリアルのセクションでは、2種類のブラスターのブラスター動作を実装するためのスクリプトについて学びます。以下の内容が含まれます:

  • プレイヤーがブラスターのボタンを押したときの検出。
  • プレイヤーが最近ブラスターのボタンを押した場合に、ブラスターを使用できるかどうかの確認。
  • サーバーに誰がブラスターを発射したか、どこから発射されたか、各レーザービームの最終的な目的地が何であったかを伝えるブラスターデータの生成。
  • ブラスターデータをサーバーに通知し、ブラスターが他のプレイヤーに衝突した場合に適切なアクションを実行できるようにする。
  • 各ブラスターの発射の間にブラスターをリセットし、再度発射できるまでに十分な冷却時間を与える。

このセクションを完了すると、ブラスターがその発射が他のプレイヤーに衝突したときに検出し、各ブラスタータイプに応じて対応する健康を減少させるためのスクリプトについて学びます。

プレイヤー入力の検出

ブラスターの動作を実装する最初のステップは、プレイヤーがブラスターのボタンを押したときにリスニングすることです。プレイヤーがブラスターのボタンを押すために使用する入力タイプは、ゲームにアクセスするために使用しているデバイスによって異なります。たとえば、サンプルレーザータグゲームは、マウスとキーボードのコントロール、ゲームパッド、タッチコントロールをサポートしています。これらの入力タイプはすべてReplicatedStorageUserInputHandlerにあります。

このクライアントスクリプトは、ContextActionServiceを使用して、MouseButton1ButtonR2を発射アクションにバインドします。これは、プレイヤーが左マウスボタンまたはゲームパッドのR2ボタンを押すたびに、ブラスターからレーザービームが発射されることを意味します。モバイルデバイス用の発射ボタンがHUDGuiに含まれており、スクリプトの後半で接続されることに注意してください。

UserInputHandler
ContextActionService:BindAction("_", onBlasterActivated, false,
Enum.UserInputType.MouseButton1,
Enum.KeyCode.ButtonR2
)

もう1つの重要な注意点は、onBlasterActivated()の定義でEnum.UserInputState.Beginを使用していることです。この例のようにブラスターを選択するなど、多くのユーザーインターフェースの操作は、マウスボタンが上がった後(Enum.UserInputState.End)に発生し、ユーザーに最後の瞬間の回避のチャンスを与えます。しかし、発射メカニクスは、ボタンが押された瞬間に発生しない限り、応答性が感じられません。

デモとして、Enum.UserInputState.BeginEnum.UserInputState.Endに変更し、プレイテストを行って、発射の応答性がゲームプレイにどのように影響するかを確認できます。たとえば、プレイヤーがボタンを押し続けても発射がトリガーされない場合、他のプレイヤーをタグ付けする際の体験はどのように変わるでしょうか?

UserInputHandler
local function onBlasterActivated(_actionName: string,
inputState: Enum.UserInputState, _inputObject: InputObject)
if inputState == Enum.UserInputState.End then -- 更新された行、必ず元に戻してください
attemptBlastClient()
end
end

プレイヤーが発射できるかどうかの確認

UserInputHandlerがボタンの押下または画面タップを検出した後、ReplicatedStorageBlasterattemptBlastClientを呼び出して、プレイヤーが発射できるかどうかを確認します。サンプルレーザータグゲームのほとんどのチェックと同様に、これはクライアントで最初に、次にサーバーで行われます。attemptBlastClientは次に、ReplicatedStorageBlastercanLocalPlayerBlastを呼び出して、blasterStateClientプレイヤー属性の簡単なチェックを行います:

canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return localPlayer:GetAttribute(PlayerAttribute.blasterStateClient) == BlasterState.Ready
end

ReplicatedStorageBlasterBlasterStateを調べると、ゲームには3つのブラスター状態があることがわかります:ReadyBlastingDisabled。これらの状態のそれぞれの効果を確認するには、ゲームをプレイテストし、Playersサービスの下でプレイヤーを選択し、PropertiesウィンドウでblasterStateClient属性を観察します。ブラスターを選択している間はDisabledが表示され、ほとんどの時間はReadyが表示され、ボタンを押した後はBlastingが1秒未満表示されることに注意してください。

このわずかな遅延により、クリックできる速度で発射することができなくなります。たとえば、関数を常にtrueを返すように変更すると、遅延なしでブラスターを急速に発射できるようになり、レーザータグのゲームプレイには非現実的です。

canLocalPlayerBlast
local function canLocalPlayerBlast(): boolean
return true -- 更新された行、必ず元に戻してください
end

ブラスターデータの生成

プレイヤーのブラスターがReady状態であることを確認した後、attemptBlastClientReplicatedStorageattemptBlastClientblastClientを呼び出します。blastClientが最初に行うステップは、blasterStateClientプレイヤー属性をBlastingに設定することで、以前の急速発射のケースを回避します。

次のステップは、ブラスターデータを生成することです。ReplicatedStorageBlasterBlastDataを確認すると、各発射は3つの情報から構成されていることがわかります:

  • 発射を開始したプレイヤー。
  • 発射の起点を表すDataType.CFrame
  • 各レーザービームの最終目的地と、他のプレイヤーにヒットした場合のヒットプレイヤーを含むRayResultテーブル。

このデータを生成するために、blastClientReplicatedStorageattemptBlastClientblastClientgenerateBlastDataを呼び出します。以下にその内容を示します。

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

この関数は、getBlasterConfigを使用してプレイヤーのブラスタータイプを取得することから始まります。サンプルでは、広い水平スプレッドで複数のビームを生成するブラスターと、単一のビームを生成するブラスターの2種類が提供されています。これらの設定はReplicatedStorageInstancesLaserBlastersFolderにあります。

次に、関数はcurrentCamera.CFrameを発射の起点として使用し、getDirectionsForBlastに渡します。この時点で、コードはもはやブラスターに関するものではなく、レーザービームに関するものです。レーザービームについては、チュートリアルのヒットの検出セクションでさらに学びます。最後に、rayResultsテーブルを作成した後、generateBlastDataはブラスターデータをblastClientに返すために必要なすべての情報を持っています。

サーバーへの通知

blastClientが発射の完全なデータを持つと、2つのイベントを発火します:

blastClient
local laserBlastedBindableEvent = ReplicatedStorage.Instances.LaserBlastedBindableEvent
local laserBlastedEvent = ReplicatedStorage.Instances.LaserBlastedEvent
laserBlastedBindableEvent:Fire(blastData)
laserBlastedEvent:FireServer(blastData)

BindableEventは、他のクライアントスクリプトに発射を通知します。たとえば、ReplicatedStorageFirstPersonBlasterVisualsは、このイベントを使用して発射アニメーションやクールダウンバーなどの視覚効果を表示するタイミングを知ります。同様に、RemoteEventはサーバースクリプトに発射を通知し、ServerScriptServiceLaserBlastHandlerで発射の処理を開始します。

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

チートを防ぐために、サーバーは各クライアントが送信するすべてのデータを検証する必要があります。これらのチェックには以下が含まれます:

  1. BlastDataはテーブルですか?Class.CFramerayResultsという名前の別のテーブルを含んでいますか?
  2. プレイヤーはブラスターを装備していますか?
  3. プレイヤーはキャラクターを持ち、世界内に位置していますか?
  4. 発射データを送信した後、プレイヤーはレーザービームを発射した場所から過度に移動しましたか?

この最後のチェックは判断を要し、サーバーのレイテンシやプレイヤーの移動速度に応じて、あなた自身のゲームにとって過度な値が何であるかを決定することができます。この判断を示すために、getValidatedBlastDataにprint文を追加し、ゲームをプレイテストして、位置の変化の典型的な大きさを把握できます。

getValidatedBlastData
local distanceFromCharacterToOrigin = blastData.originCFrame.Position - rootPartCFrame.Position
print(distanceFromCharacterToOrigin.Magnitude) -- 更新された行、必ず削除してください
if distanceFromCharacterToOrigin.Magnitude > ToleranceValues.DISTANCE_SANITY_CHECK_TOLERANCE_STUDS then
warn(`Player {player.Name} failed an origin sanity check while blasting`)
return
end

移動して発射すると、出力を確認してください。出力は次のようになるかもしれません:

1.9019629955291748
3.1549558639526367
2.5742883682250977
4.8044586181640625
2.6434271335601807

ReplicatedStoragePlayerStateHandlertogglePlayerMovementでプレイヤーの移動速度を増加させると、再度プレイテストを行うと、発射間の過度な移動による多くの失敗したチェックに遭遇する可能性が高いです。

togglePlayerMovement
local ENABLED_WALK_SPEED = 60 -- 更新された行、必ず元に戻してください

サーバーは次のことを行います:

  • rayResultsを検証します。
  • プレイヤーが発射できるかどうかを確認します。
  • ブラスターの状態をリセットします。
  • タグ付けされたプレイヤーの健康を減少させます。
  • 他のすべてのプレイヤーに発射を複製し、彼らが三人称の視覚を見られるようにします。

これらのサーバー操作の詳細については、チュートリアルのヒットの検出セクションを参照してください。

ブラスターのリセット

サンプルレーザータグゲームでは、ブラスターは熱メカニクスを使用します。一定の発射数の後にリロードするのではなく、各発射の間に「冷却」する時間が必要です。この同じクールダウンの遅延は、クライアント(blastClient)とサーバー(blastServer)の両方で発生し、サーバーが真実の源として機能します。

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)

secondsBetweenBlasts属性は、ReplicatedStorageInstancesLaserBlastersFolderのブラスター設定の一部です。secondsBetweenBlastsの遅延が経過すると、プレイヤーは再度発射でき、全プロセスが繰り返されます。プレイヤーが再度発射できるタイミングを理解できるように、ゲームにはクールダウンバーが含まれています。

この時点で、プレイヤーはスポーンおよびリスポーンし、狙いを定めて発射できますが、ゲームは各発射の結果を決定する必要があります。次のチュートリアルのセクションでは、ブラスターが発射が他のプレイヤーにヒットしたときに検出し、ブラスター設定に応じて適切な量のプレイヤーの健康を減少させる機能をプログラムする方法を学びます。

©2026 Roblox Corporation。Roblox(ロブロックス)、RobloxロゴおよびPowering Imaginationは、米国並びにその他の国における登録商標および非登録商標です。