この記事では、ROBLOXでプレイヤーの位置を視覚的に表示する「ESP(Extra Sensory Perception)」スクリプトの作成方法を解説します。このチュートリアルはLua言語の基本的な知識を前提としています。

ESP機能とは?

ESPとは「Extra Sensory Perception(超感覚的知覚)」の略で、ゲーム内で通常見ることができない情報(他プレイヤーの位置など)を視覚的に表示する機能です。ROBLOXでは、他プレイヤーの周りにボックスを描画したり、距離を表示したりすることができます。

基本的なESPスクリプトの構造

以下は、基本的なESPスクリプトのコードです。各部分について詳しく説明していきます。

-- 基本的なESPスクリプト
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera

-- ESPの設定
local ESP = {
    Enabled = true,
    BoxColor = Color3.fromRGB(255, 0, 0),  -- 赤色
    TextColor = Color3.fromRGB(255, 255, 255),  -- 白色
    TextSize = 14,
    BoxThickness = 1,
    TeamCheck = true  -- チームメイトには表示しない
}

-- ESPを切り替えるキー
local ToggleKey = Enum.KeyCode.F

-- ESPの表示要素を作成する関数
local function CreateESPParts()
    local ESPFolder = Instance.new("Folder")
    ESPFolder.Name = "ESPFolder"
    ESPFolder.Parent = game.CoreGui
    
    return ESPFolder
end

-- ESPを描画する関数
local function UpdateESP()
    -- 既存のESPフォルダを削除
    if game.CoreGui:FindFirstChild("ESPFolder") then
        game.CoreGui.ESPFolder:Destroy()
    end
    
    -- ESPが無効なら何もしない
    if not ESP.Enabled then
        return
    end
    
    -- 新しいESPフォルダを作成
    local ESPFolder = CreateESPParts()
    
    -- 各プレイヤーに対して処理
    for _, player in pairs(Players:GetPlayers()) do
        -- 自分自身はスキップ
        if player == LocalPlayer then
            continue
        end
        
        -- チームチェック
        if ESP.TeamCheck and player.Team == LocalPlayer.Team then
            continue
        end
        
        -- プレイヤーのキャラクターを取得
        local character = player.Character
        if not character then
            continue
        end
        
        -- HumanoidRootPartを取得
        local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
        if not humanoidRootPart then
            continue
        end
        
        -- プレイヤーの位置を3Dから2Dに変換
        local vector, onScreen = Camera:WorldToViewportPoint(humanoidRootPart.Position)
        
        -- 画面内にいる場合のみ描画
        if onScreen then
            -- プレイヤーとの距離を計算
            local distance = (Camera.CFrame.Position - humanoidRootPart.Position).Magnitude
            distance = math.floor(distance)
            
            -- ESP表示用の要素を作成
            local ESPFrame = Instance.new("Frame")
            ESPFrame.Size = UDim2.new(0, 200, 0, 50)
            ESPFrame.BackgroundTransparency = 1
            ESPFrame.Position = UDim2.new(0, vector.X, 0, vector.Y)
            ESPFrame.Parent = ESPFolder
            
            -- プレイヤー名と距離を表示するテキスト
            local NameLabel = Instance.new("TextLabel")
            NameLabel.Size = UDim2.new(1, 0, 0, 20)
            NameLabel.BackgroundTransparency = 1
            NameLabel.Text = player.Name .. " [" .. distance .. "m]"
            NameLabel.TextColor3 = ESP.TextColor
            NameLabel.TextSize = ESP.TextSize
            NameLabel.Font = Enum.Font.SourceSansBold
            NameLabel.TextStrokeTransparency = 0.4
            NameLabel.TextStrokeColor3 = Color3.new(0, 0, 0)
            NameLabel.Parent = ESPFrame
            
            -- ボックスを描画
            local Box = Instance.new("Frame")
            Box.Size = UDim2.new(0, 40, 0, 60)
            Box.BackgroundTransparency = 0.8
            Box.BorderSizePixel = ESP.BoxThickness
            Box.BorderColor3 = ESP.BoxColor
            Box.BackgroundColor3 = ESP.BoxColor
            Box.Position = UDim2.new(0.5, -20, 0.5, -30)
            Box.Parent = ESPFrame
        end
    end
end

-- ESPの切り替え処理
UserInputService.InputBegan:Connect(function(input)
    if input.KeyCode == ToggleKey then
        ESP.Enabled = not ESP.Enabled
    end
end)

-- 毎フレームESPを更新
RunService.RenderStepped:Connect(UpdateESP)

コードの詳細解説

1. 必要なサービスとオブジェクトの取得

local Players = game:GetService("Players")
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local LocalPlayer = Players.LocalPlayer
local Camera = workspace.CurrentCamera

この部分では、ESPスクリプトに必要な以下のROBLOXサービスを取得しています:

  • Players: ゲーム内のプレイヤー情報にアクセスするためのサービス
  • RunService: ゲームループ内で定期的に関数を実行するためのサービス
  • UserInputService: キーボードやマウスの入力を検出するためのサービス
  • LocalPlayer: スクリプトを実行しているプレイヤー
  • Camera: 現在のゲームカメラ(3D座標を2D画面座標に変換するために使用)

2. ESP設定の定義

-- ESPの設定
local ESP = {
    Enabled = true,
    BoxColor = Color3.fromRGB(255, 0, 0),  -- 赤色
    TextColor = Color3.fromRGB(255, 255, 255),  -- 白色
    TextSize = 14,
    BoxThickness = 1,
    TeamCheck = true  -- チームメイトには表示しない
}

-- ESPを切り替えるキー
local ToggleKey = Enum.KeyCode.F

ここでは、ESP機能の基本設定を定義しています:

  • Enabled: ESPが有効かどうか(初期値: 有効)
  • BoxColor: プレイヤーを囲むボックスの色
  • TextColor: プレイヤー名と距離表示の色
  • TextSize: テキストのサイズ
  • BoxThickness: ボックスの線の太さ
  • TeamCheck: 自分のチームメイトには表示しないかどうか
  • ToggleKey: ESPの表示/非表示を切り替えるキー(Fキー)

3. ESPの表示要素を作成する関数

-- ESPの表示要素を作成する関数
local function CreateESPParts()
    local ESPFolder = Instance.new("Folder")
    ESPFolder.Name = "ESPFolder"
    ESPFolder.Parent = game.CoreGui
    
    return ESPFolder
end

CreateESPParts関数では、ESPの表示要素を格納するためのフォルダを作成しています。game.CoreGuiは、ゲームのGUIを管理する特別なオブジェクトで、ESPの表示要素を追加するのに適した場所です。

4. ESPを描画する関数

-- ESPを描画する関数
local function UpdateESP()
    -- 既存のESPフォルダを削除
    if game.CoreGui:FindFirstChild("ESPFolder") then
        game.CoreGui.ESPFolder:Destroy()
    end
    
    -- ESPが無効なら何もしない
    if not ESP.Enabled then
        return
    end
    
    -- 新しいESPフォルダを作成
    local ESPFolder = CreateESPParts()
    
    -- 各プレイヤーに対して処理
    for _, player in pairs(Players:GetPlayers()) do
        -- 自分自身はスキップ
        if player == LocalPlayer then
            continue
        end
        
        -- チームチェック
        if ESP.TeamCheck and player.Team == LocalPlayer.Team then
            continue
        end
        
        -- プレイヤーのキャラクターを取得
        local character = player.Character
        if not character then
            continue
        end
        
        -- HumanoidRootPartを取得
        local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
        if not humanoidRootPart then
            continue
        end
        
        -- プレイヤーの位置を3Dから2Dに変換
        local vector, onScreen = Camera:WorldToViewportPoint(humanoidRootPart.Position)
        
        -- 画面内にいる場合のみ描画
        if onScreen then
            -- プレイヤーとの距離を計算
            local distance = (Camera.CFrame.Position - humanoidRootPart.Position).Magnitude
            distance = math.floor(distance)
            
            -- ESP表示用の要素を作成
            local ESPFrame = Instance.new("Frame")
            ESPFrame.Size = UDim2.new(0, 200, 0, 50)
            ESPFrame.BackgroundTransparency = 1
            ESPFrame.Position = UDim2.new(0, vector.X, 0, vector.Y)
            ESPFrame.Parent = ESPFolder
            
            -- プレイヤー名と距離を表示するテキスト
            local NameLabel = Instance.new("TextLabel")
            NameLabel.Size = UDim2.new(1, 0, 0, 20)
            NameLabel.BackgroundTransparency = 1
            NameLabel.Text = player.Name .. " [" .. distance .. "m]"
            NameLabel.TextColor3 = ESP.TextColor
            NameLabel.TextSize = ESP.TextSize
            NameLabel.Font = Enum.Font.SourceSansBold
            NameLabel.TextStrokeTransparency = 0.4
            NameLabel.TextStrokeColor3 = Color3.new(0, 0, 0)
            NameLabel.Parent = ESPFrame
            
            -- ボックスを描画
            local Box = Instance.new("Frame")
            Box.Size = UDim2.new(0, 40, 0, 60)
            Box.BackgroundTransparency = 0.8
            Box.BorderSizePixel = ESP.BoxThickness
            Box.BorderColor3 = ESP.BoxColor
            Box.BackgroundColor3 = ESP.BoxColor
            Box.Position = UDim2.new(0.5, -20, 0.5, -30)
            Box.Parent = ESPFrame
        end
    end
end

UpdateESP関数は、ESPの中核となる部分で以下の処理を行います:

  1. 既存のESP表示を削除し、ESP機能が無効の場合は処理を中断します。
  2. ゲーム内の全プレイヤーをループし、各プレイヤーに対して:
    • 自分自身はスキップ
    • チームチェックが有効な場合、味方はスキップ
    • プレイヤーのキャラクターとHumanoidRootPartが存在するか確認
  3. プレイヤーの3D位置を2D画面座標に変換(WorldToViewportPoint
  4. プレイヤーが画面内にいる場合のみ、ESP要素を作成:
    • プレイヤーとの距離を計算
    • ESP表示用のフレームを作成
    • プレイヤー名と距離を表示するテキストラベルを作成
    • プレイヤーを囲むボックスを作成

5. ESPの切り替え処理

-- ESPの切り替え処理
UserInputService.InputBegan:Connect(function(input)
    if input.KeyCode == ToggleKey then
        ESP.Enabled = not ESP.Enabled
    end
end)

この部分では、UserInputServiceを使用してキー入力を検出し、指定されたキー(Fキー)が押されたときにESP機能のオン/オフを切り替えます。

6. 毎フレームESPを更新

-- 毎フレームESPを更新
RunService.RenderStepped:Connect(UpdateESP)

最後に、RunService.RenderSteppedイベントにUpdateESP関数を接続して、毎フレームESP表示を更新します。これにより、プレイヤーの動きに合わせてESP表示がリアルタイムで更新されます。

応用:より高度なESP機能の実装

基本的なESPスクリプトを理解したら、以下のような機能を追加して、より高度なESPを実装することができます:

1. 体力バーの表示

-- HealthBarの作成部分(UpdateESP関数内に追加)
local humanoid = character:FindFirstChildOfClass("Humanoid")
if humanoid then
    local health = humanoid.Health
    local maxHealth = humanoid.MaxHealth
    local healthPercent = health / maxHealth
    
    -- 体力バーの背景
    local HealthBarBG = Instance.new("Frame")
    HealthBarBG.Size = UDim2.new(0, 50, 0, 5)
    HealthBarBG.BackgroundColor3 = Color3.new(0, 0, 0)
    HealthBarBG.BorderSizePixel = 0
    HealthBarBG.Position = UDim2.new(0.5, -25, 0, -15)
    HealthBarBG.Parent = ESPFrame
    
    -- 体力バー
    local HealthBar = Instance.new("Frame")
    HealthBar.Size = UDim2.new(healthPercent, 0, 1, 0)
    HealthBar.BackgroundColor3 = Color3.fromRGB(255 * (1 - healthPercent), 255 * healthPercent, 0)
    HealthBar.BorderSizePixel = 0
    HealthBar.Parent = HealthBarBG
end

2. 骨格表示(Skeleton ESP)

-- 骨格を描画する関数(新しく追加)
local function DrawSkeleton(character, espFolder)
    -- 骨格の接続情報(例:頭と胴体、胴体と右腕など)
    local connections = {
        {"Head", "UpperTorso"},
        {"UpperTorso", "LowerTorso"},
        {"UpperTorso", "RightUpperArm"},
        {"RightUpperArm", "RightLowerArm"},
        {"RightLowerArm", "RightHand"},
        {"UpperTorso", "LeftUpperArm"},
        {"LeftUpperArm", "LeftLowerArm"},
        {"LeftLowerArm", "LeftHand"},
        {"LowerTorso", "RightUpperLeg"},
        {"RightUpperLeg", "RightLowerLeg"},
        {"RightLowerLeg", "RightFoot"},
        {"LowerTorso", "LeftUpperLeg"},
        {"LeftUpperLeg", "LeftLowerLeg"},
        {"LeftLowerLeg", "LeftFoot"}
    }
    
    -- 各接続に対して線を描画
    for _, connection in pairs(connections) do
        local part1 = character:FindFirstChild(connection[1])
        local part2 = character:FindFirstChild(connection[2])
        
        if part1 and part2 then
            local pos1, onScreen1 = Camera:WorldToViewportPoint(part1.Position)
            local pos2, onScreen2 = Camera:WorldToViewportPoint(part2.Position)
            
            if onScreen1 and onScreen2 then
                -- 2点間に線を描画
                local line = Instance.new("Frame")
                line.BackgroundColor3 = ESP.BoxColor
                line.BorderSizePixel = 0
                line.Parent = espFolder
                
                -- 線の位置と大きさを計算
                local distance = (Vector2.new(pos1.X, pos1.Y) - Vector2.new(pos2.X, pos2.Y)).Magnitude
                local position = UDim2.new(0, (pos1.X + pos2.X) / 2, 0, (pos1.Y + pos2.Y) / 2)
                local size = UDim2.new(0, distance, 0, 1)
                
                -- 線の回転角度を計算
                local angle = math.atan2(pos2.Y - pos1.Y, pos2.X - pos1.X)
                
                line.Position = position
                line.Size = size
                line.Rotation = math.deg(angle)
            end
        end
    end
end

-- UpdateESP関数内で呼び出す
DrawSkeleton(character, ESPFolder)

3. トレーサー(プレイヤーから自分への線)

-- トレーサーを描画(UpdateESP関数内に追加)
-- 画面の下部中央から対象プレイヤーへの線
local screenCenter = Vector2.new(Camera.ViewportSize.X / 2, Camera.ViewportSize.Y)
local playerPos = Vector2.new(vector.X, vector.Y)

-- トレーサー(線)を作成
local tracer = Instance.new("Frame")
tracer.BackgroundColor3 = ESP.BoxColor
tracer.BorderSizePixel = 0
tracer.Parent = ESPFolder

-- 線の位置と大きさを計算
local distance = (screenCenter - playerPos).Magnitude
local position = UDim2.new(0, (screenCenter.X + playerPos.X) / 2, 0, (screenCenter.Y + playerPos.Y) / 2)
local size = UDim2.new(0, distance, 0, 1)

-- 線の回転角度を計算
local angle = math.atan2(playerPos.Y - screenCenter.Y, playerPos.X - screenCenter.X)

tracer.Position = position
tracer.Size = size
tracer.Rotation = math.deg(angle)

注意点

ESPスクリプトの使用に関する注意点:

  • ESPスクリプトは、ROBLOXの利用規約に違反する可能性があります。教育目的で理解することは問題ありませんが、実際のゲームで使用すると、アカウントのBANなどの処罰を受ける可能性があります。
  • 多くのゲームでは、不正なスクリプトの使用を検出するアンチチートシステムが導入されています。
  • このチュートリアルは、教育目的で提供されており、実際のゲームで不正な優位性を得るために使用することは推奨していません。

まとめ

このチュートリアルでは、ROBLOXでプレイヤーの位置を視覚的に表示するESPスクリプトの基本的な実装方法について解説しました。基本的なESP機能から、体力バー、骨格表示、トレーサーなどの応用機能まで、様々なESP機能を実装する方法を学びました。

ESPスクリプトの作成は、以下の重要な概念を理解するのに役立ちます:

  • 3D世界座標から2D画面座標への変換(WorldToViewportPoint
  • ROBLOXのGUI要素の作成と操作
  • ゲームループ内での処理(RunService.RenderStepped
  • プレイヤーと他のオブジェクトの情報へのアクセス