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

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

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

サンプルレーザータグ体験を参考にして、このチュートリアルのセクションでは、ブラスターの動作を実装するためのスクリプトについて学び、次のことを含む2種類のブラスターのガイダンスを提供します:

  • プレイヤーがブラストボタンを押したときを検出する。
  • プレイヤーが最近ブラストボタンを押した場合、そのプレイヤーがブラスターを使用できるかどうかを確認する。
  • ブラストデータを生成し、サーバーにブラストを開始したプレイヤー、それがどこから来たか、そして各レーザービームの最終目的地について伝える。
  • ブラストデータをサーバーに通知し、ブラストが他のプレイヤーと衝突した場合に適切なアクションを実行できるようにする。
  • 各ブラストの間にブラスターをリセットし、次のブラストが可能になるまでに十分なクールダウン時間を与える。

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

プレイヤー入力を検出する

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

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

UserInputHandler

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

もう一つ重要なポイントは、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.CFrameと別のテーブルrayResultsを含んでいますか?
  2. プレイヤーはブラスターを装備していますか?
  3. プレイヤーは世界内にキャラクターと位置を持っていますか?
  4. ブラストデータを送信した後、プレイヤーはレーザー ビームをブラストした場所から過度に離れた位置に移動していませんか?

最後のチェックは判断を必要とし、サーバーのレイテンシやプレイヤーの移動速度に応じて、体験によって異なる値が許容されるかもしれません。この判断を行う方法を示すために、getValidatedBlastDataにプラントステートメントを追加し、体験をプレイテストして、位置の変化の一般的な大きさを確認することができます。

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は、米国並びにその他の国における登録商標および非登録商標です。