Roblox LocalScript запускает код несколько раз

Я написал LocalScript (MessageController) для сюжетной игры Roblox под названием Police Raid. Этот сценарий управляет ходом истории, изменяя сообщения пользовательского интерфейса и запуская события.

-- This script controls the progress of the messages! (It's the GOAT)
local message = script.Parent.Message

-- Wait for character to load
local player = game:GetService("Players").LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

-- Change message
task.wait(7)
message.Text = "Back there is the panic room. If there's any trouble, click the big red button and get inside. We're just going to hole up in here until someone comes to help us."

-- Change message
task.wait(7)
message.Text = "[static] This is the Robloxian Police Department, Barricaded Supsects Division. We have a warrant for your arrest on counts of [static]..."
message.TextColor3 = BrickColor.Red().Color
script["Heli Sound"]:Play()

-- Change message
task.wait(5)
message.Text = "Uh oh..."
message.TextColor3 = BrickColor.Black().Color

-- Change message
task.wait(2)
message.Text = "If you don't come out and surrender now, we will raid the premises!"
message.TextColor3 = BrickColor.Red().Color

-- Change message
task.wait(3)
message.Text = "Get to the panic room! NOW!!!"
-- Enable panic room
game:GetService("Workspace").Button.Part.ClickDetector.MaxActivationDistance = 32
message.TextColor3 = BrickColor.Black().Color

game:GetService("Workspace").TouchDetector.Touched:Connect(function(otherPart: BasePart)
    -- In the panic room
    task.wait(1)
    script["Explosion"]:Play()
    
    -- Change message
    task.wait(3)
    message.Text = "They're raiding the house... we should be safe in here."
    script["Loud Explosion"]:Play()
    
    -- Change message
    task.wait(2)
    message.Text = "They're in the panic room!"
    message.TextColor3 = BrickColor.Red().Color
    script["Extra Loud Explosion"]:Play()
    
    -- Change message
    task.wait(2)
    message.Text = "I don't think we're as safe as I thought. Grab that rifle from the floor and get to the basement, QUICK!"
    message.TextColor3 = BrickColor.Black().Color
    game:GetService("Workspace")["Panic Door"].Fire.Enabled = true
    game:GetService("Workspace")["Panic Panel"].CanCollide = false
    -- Change message
    game:GetService("Workspace")["Basement Detector"].Touched:Connect(function(otherPart: BasePart)
        task.wait(2)
        message.Text = "Okay... this basement was designed to survive a raid, so we should be okay."

        -- Change message
        task.wait(7)
        script["Extra Loud Explosion"]:Play()
        game:GetService("Workspace")["Basement Wall"].Transparency = 1
        message.Text = "Put your hands up!"
        message.TextColor3 = BrickColor.Red().Color

        -- Change message
        task.wait(2)
        message.Text = "Get down, part of the wall is still up!"
        message.TextColor3 = BrickColor.Black().Color
        local counter = 10
        task.wait(1)

        for i = counter, 0, -1 do
            task.wait(1)
            script.Gunfire:Play()
            -- Damage player

            -- Check if they are in a safe area
            local safezone = game:GetService("Workspace")["Wall Parts"].Safezone
            safezone.Touched:Connect(function() end) -- TouchInterest

            local function CheckIfPlayerIsInArea(Part,Character)
                local touching = Part:GetTouchingParts()
                for i=1,#touching do
                    if touching[i] == Character.HumanoidRootPart then
                        return true
                    end
                end
                return false
            end
            if not CheckIfPlayerIsInArea(safezone, game:GetService("Players").LocalPlayer.Character) then
                --game:GetService("ReplicatedStorage").DamagePlayer:FireServer(10)
                game:GetService("Players").LocalPlayer.Character.Humanoid.Health -= 1
            end
        end

        -- Change message
        message.Text = "The Robloxian Freedom Fighters are here! Get into their helicopter and escape to headquarters!"
        game:GetService("Workspace")["Basement Wall"].CanCollide = false
        local fighters = game:GetService("Workspace")["Freedom Fighters"]
        fighters["RFF-Beta-31"]:MoveTo(Vector3.new(-100.242, 3.003, 39.393))
        fighters["RFF-Alpha-0"]:MoveTo(Vector3.new(-103.259, 3.003, 31.674))
        fighters["RFF-Epsilon-97"]:PivotTo(CFrame.new(-90.501, 9.305, 40.968))
        fighters["RFF-Sigma-69"]:MoveTo(Vector3.new(-98.693, 3.003, 24.884))
        fighters["RFF-Gamma-3"]:MoveTo(Vector3.new(-122.102, 3.003, 25.833))
        fighters["RFF-Foxtrot-11"]:MoveTo(Vector3.new(-96.868, 3.003, 48.219))
        fighters["RFF-Delta-4"]:MoveTo(Vector3.new(-113.647, 3.003, 32.763))
        game:GetService("Workspace")["RFF Heli"]:PivotTo(CFrame.new(-105.629, 3.5, 49.35))
        local ChatService = game:GetService("Chat")
        local talkpart = game:GetService("Workspace")["BSD Commander Parker"].Handle
        do
            ChatService:Chat(talkpart, "It's an ambush!")
        end
        print("Triggered")
        task.wait(1)
        script["Machine Gun Fire"]:Play()
    end)
end)

Проблема в том, что «Triggered», кажется, выводится на консоль 528 раз, а звук «Gunfire» воспроизводится поверх самого себя очень быстро. NPC Паркер говорит: «Это засада!» снова и снова в пузырях чата над его головой. Борцы за свободу и RFF Heli перемещаются настолько сильно, что в конечном итоге исчезают, а игра тормозит из-за слишком быстрого выполнения кода. Я понятия не имею, почему код выполняет так много. Часть проблемы выглядит следующим образом:

local counter = 10
        task.wait(1)

        for i = counter, 0, -1 do
            task.wait(1)
            script.Gunfire:Play()
            -- Damage player

            -- Check if they are in a safe area
            local safezone = game:GetService("Workspace")["Wall Parts"].Safezone
            safezone.Touched:Connect(function() end) -- TouchInterest

            local function CheckIfPlayerIsInArea(Part,Character)
                local touching = Part:GetTouchingParts()
                for i=1,#touching do
                    if touching[i] == Character.HumanoidRootPart then
                        return true
                    end
                end
                return false
            end
            if not CheckIfPlayerIsInArea(safezone, game:GetService("Players").LocalPlayer.Character) then
                --game:GetService("ReplicatedStorage").DamagePlayer:FireServer(10)
                game:GetService("Players").LocalPlayer.Character.Humanoid.Health -= 1
            end
        end

        -- Change message
        message.Text = "The Robloxian Freedom Fighters are here! Get into their helicopter and escape to headquarters!"
        game:GetService("Workspace")["Basement Wall"].CanCollide = false
        local fighters = game:GetService("Workspace")["Freedom Fighters"]
        fighters["RFF-Beta-31"]:MoveTo(Vector3.new(-100.242, 3.003, 39.393))
        fighters["RFF-Alpha-0"]:MoveTo(Vector3.new(-103.259, 3.003, 31.674))
        fighters["RFF-Epsilon-97"]:PivotTo(CFrame.new(-90.501, 9.305, 40.968))
        fighters["RFF-Sigma-69"]:MoveTo(Vector3.new(-98.693, 3.003, 24.884))
        fighters["RFF-Gamma-3"]:MoveTo(Vector3.new(-122.102, 3.003, 25.833))
        fighters["RFF-Foxtrot-11"]:MoveTo(Vector3.new(-96.868, 3.003, 48.219))
        fighters["RFF-Delta-4"]:MoveTo(Vector3.new(-113.647, 3.003, 32.763))
        game:GetService("Workspace")["RFF Heli"]:PivotTo(CFrame.new(-105.629, 3.5, 49.35))
        local ChatService = game:GetService("Chat")
        local talkpart = game:GetService("Workspace")["BSD Commander Parker"].Handle
        do
            ChatService:Chat(talkpart, "It's an ambush!")
        end
        print("Triggered")
        task.wait(1)
        script["Machine Gun Fire"]:Play()

Извините, если кода много или он плохо отформатирован.

Я попытался отладить код, напечатав текст «Триггерировано», и просмотрел сценарий на предмет всего, что может вызывать бесконечный цикл. Я также попробовал добавить task.wait(math.huge) в конец скрипта, чтобы предотвратить его многократное выполнение (над операторами end), но это не повлияло на циклическое выполнение. Интересно, что Machine Gun Fire (зацикленный звук) звучит не более одного раза. Если это полезно, LocalScript является родительским элементом ScreenGui, который является родительским для StarterGui.

Я не могу опубликовать этот вопрос на форуме разработчиков Roblox из-за отсутствия репутации, поскольку я просматриваю сайт без входа в систему в течение длительного времени.

Я не знаком со сценариями Roblox, но если game:GetService("Workspace").TouchDetector.Touched активируется много раз, вы каждый раз подключаете новое событие к game:GetService("Workspace")["Basement Detector"].Touched. Таким образом, если к TouchDetector прикоснуться 10 раз, у вас будет 10 событий, которые одновременно сработают на BasementDetector. Может быть, вместо того, чтобы создавать событие внутри другого события, вам следует создать событие в начале и не делать ничего, пока не будет установлена ​​определенная условная переменная?

Kaia 23.04.2024 00:36

Возможно, над линией game:GetService("Workspace")["Basement Detector"].Touched:Connect(function(otherPart: BasePart) добавьте print("Enabled the BasementDetector") и посмотрите, будет ли она вызываться более одного раза (и столько же раз, сколько печатается «Triggered»).

Kaia 23.04.2024 00:38

@Кайя Спасибо за помощь! Детектор подвала срабатывает сотни раз, а это, скорее всего, является причиной проблемы. Как мне остановить этот эффект? Я считаю, что события касания запускаются для каждого кадра, когда персонаж соприкасается с рассматриваемой частью.

O5 Command Stands With Ukraine 23.04.2024 00:42

Как сохранить состояние в скрипте Roblox? Это так же просто, как объявить глобальную переменную? Если да, то вы можете сделать (верхняя часть скрипта) local hasTriggeredTouchDetector = false, а затем в событии TouchDetector (косая черта — это новая строка) if hasTriggeredTouchDetector then / return / else / hasTriggeredTouchDetector = true / end. Это должно пропустить все, кроме первого вызова.

Kaia 23.04.2024 01:09

Вы также можете увидеть, есть ли Disconnect аналог Connect, чтобы можно было отключить события после их запуска. Я не уверен, что предпочтительнее в Roblox — я мог бы проверить, как с этим справляются другие хорошо продуманные скрипты. Другие вещи, которые вы можете искать (и, к сожалению, я не нахожу здесь хороших ресурсов), — это «обнаружение краев» и «устранение дребезга». Обнаружение края — это термин, обозначающий обнаружение того, когда событие (например, контакт с триггером) начинает происходить и когда оно прекращается. Устранение дребезга — это удаление коротких краев, например, если персонаж сходит со спускового крючка и сразу же возвращается обратно.

Kaia 23.04.2024 01:17

(Это похоже на то, если бы вам нужно, чтобы персонаж произносил свой диалог с игроком каждый раз, когда он приближался, но не хотел, чтобы он повторял это снова и снова, если игрок входил и выходил из зоны действия. Это также такое часто случается на физическом оборудовании, потому что кнопки подпрыгивают при нажатии!) Это не очень хорошие ссылки, но это что-то: резисторкапаситор.wordpress.com/2018/04/29/… stackoverflow.com /questions/24004791/…

Kaia 23.04.2024 01:19

Ах, эй!! Это выглядит полезным: create.roblox.com/docs/scripting/debounce. А если вы не хотите, чтобы событие перезагружалось и запускалось только один раз, удалите task.wait() и строку ниже.

Kaia 23.04.2024 01:22
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
95
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема, с которой вы сталкиваетесь, заключается в том, что вы подключаете прослушиватели к событиям и никогда не отключаете их, а также не устраняете события, которые срабатывают несколько раз. Распространенная проблема, особенно с событием Touched, заключается в том, что оно может срабатывать, когда что-либо в рабочей области касается его, а также срабатывать несколько раз для одной и той же модели персонажа. Если ваша рука и нога коснутся Детали, событие сработает для обеих этих частей.

Помимо этого, большая часть вашей игровой логики должна происходить в сценарии, таким образом, когда воспроизводятся звуки или объекты перемещаются, скрываются или уничтожаются, они должны происходить для всех одновременно.

Единственное, что должно произойти в LocalScript, — это отображение сообщений. Итак, давайте настроим серверу простой способ отправки сообщений в пользовательский интерфейс.

Итак, выполните следующие действия:

  1. Создайте RemoteEvent в ReplicationStorage с именем DisplayMessage.
  2. В вашем LocalScript удалите все, кроме этого (не волнуйтесь, ваш код перемещается в скрипт):
-- import services
local ReplicatedStorage = game:GetService("ReplicatedStorage")

-- find the UI elements
local lblMessage = script.Parent.Message

-- find the RemoteEvent telling us that the server has a message for us
local DisplayMessage = ReplicatedStorage.DisplayMessage

-- display the messages when the server sends them to us
DisplayMessage.OnClientEvent:Connect(function(message : string, color : Color3)
    lblMessage.Text = message
    lblMessage.Color3 = color
end)
  1. Создайте ModuleScript в ReplicationStorage для обработки логики устранения дребезга, когда игрок касается детали. Назовите его debounceTouch. Мы будем использовать это, чтобы запретить пользователю многократно запускать событие Touch, когда его модель персонажа касается детали.
local Players = game:GetService("Players")

-- Debounce a function so that it only fires once per player touch event
local function debounceTouch(part : BasePart, onPlayerTouched : (Player)->(), onPlayerTouchEnded : (Player)->()?)
    -- keep track of which players are touching the part
    local playersTouching : { [Player] : number } = {}
    
    local touchedConnection = part.Touched:Connect(function(otherPart : BasePart)
        local player = Players:GetPlayerFromCharacter(otherPart.Parent)
        if not player then
            return
        end

        if not playersTouching[player] then
            -- a player has begun touching!
            onPlayerTouched(player)
            playersTouching[player] = 1
        else
            playersTouching[player] += 1
        end
    end)
    local touchEndedConnection = part.TouchEnded:Connect(function(otherPart : BasePart)
        local player = Players:GetPlayerFromCharacter(otherPart.Parent)
        if not player then
            return
        end
        -- when a player stops touching, decrement the counter so that we can clear the debounce flag
        if playersTouching[player] then
           playersTouching[player] -= 1
           if (playersTouching[player] <= 0) then
               playersTouching[player] = nil

               -- the player has stopped touching, fire the callback if provided
               if onPlayerTouchEnded then
                   onPlayerTouchEnded(player)
               end
           end
        end
    end)

    -- return an object that functions like an RbxScriptConnection token so that we can disconnect it when it is no longer relevant
    return {
        Connected = (touchedConnection.Connected or touchEndedConnection.Connected),
        Disconnect = function()
            touchedConnection:Disconnect()
            touchEndedConnection:Disconnect()
        end,
    }
end

return debounceTouch
  1. Создайте сценарий в ServerScriptService и поместите его в содержимое. Это будет обрабатывать вашу игровую логику и отправлять сообщения игрокам.
-- import services
local ChatService = game:GetService("Chat")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Workspace = game:GetService("Workspace")

-- import helper functions
local debounceTouch = require(ReplicatedStorage.debounceTouch)


-- create a helper function to send the messages to all players
local DisplayMessage = ReplicatedStorage.DisplayMessage
local function displayMessageWithDelay(delay : number, message : string, color : Color3?)
    task.wait(delay)
    DisplayMessage:FireAllClients(message, color)
end

-- Wait for any player to load into the game
if #Players.GetPlayers() == 0 then
    Players.PlayerAdded:Wait()
end

-- define some values
local SAFEZONE_DAMAGE_PER_SECOND = 10


-- write down all the messages at the top
local messages = {
    "Back there is the panic room. If there's any trouble, click the big red button and get inside. We're just going to hole up in here until someone comes to help us.",
    "[static] This is the Robloxian Police Department, Barricaded Suspects Division. We have a warrant for your arrest on counts of [static]...",
    "Uh oh...",
    "If you don't come out and surrender now, we will raid the premises!",
    "Get to the panic room! NOW!!!",
    "They're raiding the house... we should be safe in here.",
    "They're in the panic room!",
    "I don't think we're as safe as I thought. Grab that rifle from the floor and get to the basement, QUICK!",
    "Okay... this basement was designed to survive a raid, so we should be okay.",
    "Put your hands up!",
    "Get down, part of the wall is still up!",
    "The Robloxian Freedom Fighters are here! Get into their helicopter and escape to headquarters!",
}

local colors = {
    black = BrickColor.Black().Color,
    red = BrickColor.Red().Color,
}

-- load some workspace elements
local ButtonClickDetector = Workspace.Button.Part.ClickDetector
local TouchDetector = Workspace.TouchDetector
local PanicDoor = Workspace["Panic Door"]
local BasementDetector = Workspace["Basement Detector"]
local BasementWall = Workspace["Basement Wall"]
local safezone = Workspace["Wall Parts"].Safezone
local fighters = Workspace["Freedom Fighters"]
local helicopter = Workspace["RFF Heli"]
local talkPart = Workspace["BSD Commander Parker"].Handle




-- start playing the game
displayMessageWithDelay(7, messages[1])
displayMessageWithDelay(7, messages[2], colors.red)
script["Heli Sound"]:Play()
displayMessageWithDelay(5, messages[3], colors.black)
displayMessageWithDelay(2, messages[4], colors.red)
displayMessageWithDelay(3, messages[5])

-- Enable panic room
ClickDetector.MaxActivationDistance = 32

local touchedConnection
touchedConnection = TouchDetector.Touched:Connect(function(otherPart: BasePart)
    -- make sure that this only fires if a player touches it
    if not Players:GetPlayerFromCharacter(otherPart.Parent) then
        return
    end

    -- disconnect the connection so that it doesn't fire again
    touchedConnection:Disconnect()

    -- In the panic room
    task.wait(1)
    script["Explosion"]:Play()
    displayMessageWithDelay(3, messages[6], colors.black)
    script["Loud Explosion"]:Play()
    displayMessageWithDelay(2, messages[7], colors.red)
    script["Extra Loud Explosion"]:Play()
    displayMessageWithDelay(2, messages[8], colors.black)

    -- set the door on fire
    PanicDoor.Fire.Enabled = true
    PanicDoor.CanCollide = false

    
    local basementTouchedConnection
    basementTouchedConnection = BasementDetector.Touched:Connect(function(otherPart: BasePart)
        -- make sure that this only fires if a player touches it
        if not Players:GetPlayerFromCharacter(otherPart.Parent) then
            return
        end

        -- disconnect the connection so it only fires once
        basementTouchedConnection:Disconnect()
 
        -- start playing the next set of messages
        displayMessageWithDelay(2, messages[9])
        displayMessageWithDelay(7, messages[10], colors.red)

        -- explode the basement walls
        script["Extra Loud Explosion"]:Play()
        BasementWall.Transparency = 1
        displayMessageWithDelay(2, messages[11], colors.black)

        -- create a list of players currently touching the safezone
        local playersInSafezone = {}
        local playerList = Players:GetPlayers()
        for _, player in ipairs(playerList) do
            playersInSafezone[player] = false
        end
        local safezoneTouchConnection = debounceTouch(safezone, function(player)
            -- when they touch the safezone, mark them as safe
            playersInSafezone[player] = true
        end, function(player)
            -- when they stop touching the safezone, mark them as unsafe
            playersInSafezone[player] = false
        end)

        task.wait(1)
        for i = 10, 0, -1 do
            task.wait(1)
            script.Gunfire:Play()

            -- Check if they are in a safe area
            for player, isSafe in pairs(playersInSafezone) do
                if not isSafe then
                    -- Damage player
                    player.Character.Humanoid:TakeDamage(SAFEZONE_DAMAGE_PER_SECOND)
                    --ReplicatedStorage.DamagePlayer:FireServer(10)
                end
            end
        end

        -- clean up the safezone events
        safezoneTouchConnection:Disconnect()
        playersInSafezone = nil

        -- Change message
        displayMessageWithDelay(0, messages[12])
        BasementWall.CanCollide = false

        -- move the fighters into place
        fighters["RFF-Beta-31"]:MoveTo(Vector3.new(-100.242, 3.003, 39.393))
        fighters["RFF-Alpha-0"]:MoveTo(Vector3.new(-103.259, 3.003, 31.674))
        fighters["RFF-Epsilon-97"]:PivotTo(CFrame.new(-90.501, 9.305, 40.968))
        fighters["RFF-Sigma-69"]:MoveTo(Vector3.new(-98.693, 3.003, 24.884))
        fighters["RFF-Gamma-3"]:MoveTo(Vector3.new(-122.102, 3.003, 25.833))
        fighters["RFF-Foxtrot-11"]:MoveTo(Vector3.new(-96.868, 3.003, 48.219))
        fighters["RFF-Delta-4"]:MoveTo(Vector3.new(-113.647, 3.003, 32.763))
        helicopter:PivotTo(CFrame.new(-105.629, 3.5, 49.35))
        
        ChatService:Chat(talkPart, "It's an ambush!")
        print("Triggered")
        task.wait(1)
        script["Machine Gun Fire"]:Play()
    end)
end)
  1. Наконец, переместите все звуки, которые были дочерними элементами вашего LocalScript, в Script. Это обеспечит сохранение пути к звукам.

Вы заметите, что я изменил способ нанесения урона игроку и принцип работы безопасной зоны. Таким образом, мы можем каждый раз быстро проверять, кто касается безопасной зоны, без необходимости просить движок искать детали у игроков.

Единственное, что я действительно сделал, это переместил все игровые сообщения в список вверху, в этом не было особой необходимости, но я подумал, что так будет проще увидеть логику игры, а не читать сообщения внутри тела. сценария. Это мое предпочтение, и оно не является необходимым для функционирования вашего кода.

Надеюсь, это поможет.

Спасибо за полезный ответ! Однако причина, по которой моя логика была полностью реализована в LocalScript, заключалась в том, что я не хочу, чтобы история развивалась для одного игрока из-за того, что другой игрок что-то запускает: если игрок А коснется BasementDetector, не вызовет ли это следующее сообщение для игрока B как хорошо? Если у игроков есть собственный локальный сюжетный прогресс, они не смогут проходить через события игры, не оказавшись в нужной области. Кроме того, LocalScript, похоже, вызывает ошибку «Players.Player.PlayerGui.ScreenGui.LocalController:12: попытка индексировать строку с ошибкой «Текст».

O5 Command Stands With Ukraine 23.04.2024 22:34

Все, что вы сказали, в точку. Я перенес логику на сервер, чтобы история могла развиваться по мере того, как кто-то выполнял соответствующие действия для ее развития. Очень часто в StackOverflow люди не уделяют активного внимания этому аспекту, поэтому я по умолчанию обращаюсь к авторитету сервера за предложениями. Вы можете перенести логику обратно в свой LocalScript, если индивидуальный прогресс жизненно важен для вашей игры. Вся логика устранения дребезга основана на «любом» игроке, но вместо этого вы можете сравнить игрока, возвращенного из Players:GetPlayerFromCharacter, с Players.LocalPlayer в качестве ключа. Также извините за ошибку!

Kylaaa 23.04.2024 23:49

Другие вопросы по теме