August 27, 2024

Делаем систему крови или возможность персонажа "красиво" умирать

в прошлом уроке мы сделали ловушки и также улучшили немного нашу систему это последней урок в нашей серии , в следущей серии мы сделаем с вами игру Doors

теперь перейдем к главному как сделать чтобы при стрельбе в игрока из оружия у него появлялась кровь?

на этот раз я тоже буду использовать модельку из тулбокса про создание моделей и билдинг я сделаю отдельный урок вы если хотите может использовать свой автомат

но сначала мы с вами сделаем кнопку + меню выбора оружия

в папке StarterGui мы добавляем screengui

Screengui -

В Roblox Studio ScreenGui (сокращение от "Screen Graphical User Interface") — это элемент интерфейса, который отображает графические элементы на экране игрока. ScreenGui используется для создания различных интерфейсов, таких как кнопки, текстовые поля, шкалы здоровья, карты и другие визуальные элементы, которые игроки видят во время игры.

Основные характеристики ScreenGui

  1. Расположение на экране: ScreenGui всегда отображается поверх игры и фиксируется к экрану игрока. Это означает, что элементы внутри ScreenGui не будут изменять своё положение относительно экрана, даже если камера или игрок будут двигаться.
  2. Родительский объект для GUI-элементов: Внутри ScreenGui можно добавлять различные элементы интерфейса, такие как:Все эти элементы должны быть вложены в ScreenGui для того, чтобы быть видимыми на экране.
    • TextLabel: Текстовые метки.
    • TextButton: Кнопки с текстом.
    • ImageLabel: Изображения.
    • Frame: Прямоугольные области, используемые для группировки других элементов.
    • И другие GUI-объекты.
  3. Область отображения: ScreenGui всегда отображается в пределах области экрана игрока. Это означает, что он "привязан" к экрану и не будет изменяться в зависимости от игрового мира. Например, элементы интерфейса, такие как панели управления, инвентари, карты и другие элементы HUD (Head-Up Display), всегда остаются на экране, независимо от позиции игрока в игровом мире.

Выбираем TextButton

Дизайн кнопки вы можете выбрать сами в Properties для тех кто не знает как я покажу как сделать такую же кнопку или как настроить ее внешний вид

для тех у кого также как у меня нету Properties

Мы заходим во View и выбираем properties

делаю черный цвет нашего бэкграунда

дальше меняю цвет текста

и увеличиваем размер текста в пункте TextScale

Также еще в нашу папку Screengui добавляем обьект с именем Frame

(я также если что поменял имя нашего Textbutton на MenuButton для удобства)

Также добавляем внутрь нашего ScreenGui cкрипт

Только поправку не Script а Localscript щас обьясню почему

В Roblox Studio существуют два основных типа скриптов для работы с Lua-кодом: Script и LocalScript. Они отличаются главным образом тем, где и как они выполняются, а также какие функции и данные им доступны. Вот основные различия:

1. Script (Скрипт)

  • Место выполнения: Скрипты выполняются на стороне сервера. Это означает, что код внутри Script запускается и работает на сервере Roblox.
  • Область видимости: Скрипты имеют доступ к серверным функциям и объектам. Они могут изменять состояние игры, доступное для всех игроков.
  • Примеры использования:
    • Управление серверной логикой игры (например, изменение состояния игры, управление спавном объектов).
    • Взаимодействие с DataStore для хранения и загрузки данных игроков.
    • Создание и управление общедоступными объектами (например, расположение деталей, управление монстрами).

2. LocalScript (Локальный скрипт)

  • Место выполнения: Локальные скрипты выполняются на стороне клиента, то есть непосредственно на устройстве игрока.
  • Область видимости: Локальные скрипты имеют доступ к объектам и функциям, которые доступны только клиенту, например, графический интерфейс пользователя (GUI) или управление камерой.
  • Примеры использования:
    • Управление интерфейсом пользователя (например, отображение HUD или диалогов).
    • Управление камерой, анимацией или другими визуальными эффектами, которые специфичны для каждого игрока.
    • Обработка ввода пользователя (например, нажатия клавиш, движения мыши).

3. Особенности взаимодействия

  • LocalScript не может напрямую изменять объекты на сервере, для этого ему нужно использовать RemoteEvent или RemoteFunction для отправки запроса на сервер, чтобы серверный Script мог выполнить необходимую работу.
  • Script не может напрямую взаимодействовать с клиентскими объектами, такими как интерфейс пользователя, и тоже должен использовать удаленные вызовы для взаимодействия с клиентом.

4. Где они могут быть размещены:

  • Script можно размещать в ServerScriptService, Workspace и других местах, которые доступны серверу.
  • LocalScript должен быть размещен в объектах, которые доступны клиенту, таких как StarterPlayerScripts, StarterCharacterScripts, StarterGui и некоторых других.

Таким образом, основное различие между Script и LocalScript в Roblox Studio заключается в том, где они выполняются (на сервере или на клиенте) и какие функции они могут использовать.

также LocalScript гораздо легче взломать поэтому все важные манипуляции и данные размещяем в script чтобы читеры не могли получить существенное превосходство

так а теперь к главному

в нашей переменной мы обращаемся к родителю нашего скрипта (родитель это папка а ребенок материал который расположен в папке в нашем же случае Frame является ребенком StarterGui

menuButton:

  • Это переменная, которая ссылается на объект типа TextButton (кнопку), которую мы создали в ScreenGui. Эта кнопка отображается на экране игрока и может быть нажата игроком.
  • у нас есть кнопка с именем MenuButton, переменная menuButton содержит ссылку на этот объект.

MouseButton1Click:

  • Это событие, которое срабатывает, когда пользователь нажимает на кнопку с левой кнопкой мыши.
  • В Roblox все GUI-элементы могут иметь события, которые запускаются при определённых действиях, таких как нажатие кнопки или перемещение мыши. В данном случае событие MouseButton1Click связано с левым щелчком мыши по кнопке.

Connect(OnOff):

  • Метод Connect используется для подключения функции к событию. Когда событие происходит (в данном случае, когда пользователь нажимает на кнопку), вызывается подключенная функция.
  • OnOff — это имя нашей функции, котораячс будет выполнена, когда событие MouseButton1Click сработает. Например, функция OnOff может управлять видимостью меню, показывая или скрывая его.

я немного поменял наш Frame

теперь я добавил 3 ImageButton это кнопка с картинкой я на каждой кнопке размещу картинку оружия которую получит персонаж при нажатии а также переименую каждую кнопку в названия оружия

name button

**Example**

AK-47 BUTTON

Теперь после того как я пронумеровал их, мы в Properties поставим саму картинку

теперья на скорую руку подробал изображения вы можете поставить свои так как эти далеко не самые лучшие

про дизайн gui будет отдельная статья + в конце статьи будет ссылка на полезный плагин

теперь нужно найти модельки наших оружий причем которые работают и могут стрелять

после того как нашли наши модельки переносим их в ServerStorage (это наше хранилище где можно хранить предметы карты и прочее)

добавляем еще один скрипт

и теперь добавляем в ReplicatedStorage Remove event

Remote Event в Roblox Studio — это один из ключевых механизмов, позволяющих взаимодействовать между клиентом и сервером в игре. Давайте разберёмся, что это такое, зачем он нужен и как его использовать.

Что такое Remote Event?

Remote Event — это объект, который используется для передачи сообщений между клиентом (игроком) и сервером (серверной частью игры). В Roblox, игры работают по принципу клиент-серверной архитектуры, где клиент и сервер — это два разных "мира":

  • Клиент — это устройство игрока (например, его компьютер или телефон), которое отображает игру, позволяет управлять персонажем и так далее.
  • Сервер — это основная часть игры, которая управляет всей логикой, например, где находятся объекты, как они взаимодействуют, и так далее.

Из-за этой разделённости клиент и сервер не могут напрямую "видеть" или управлять друг другом, поэтому нужен способ передавать данные между ними. И вот тут на сцену выходит Remote Event.

Зачем нужен Remote Event?

  1. Безопасность: Сервер управляет важной логикой игры, такой как проверка правил, обработка игровых данных, и так далее. Если бы клиент мог сам всё это контролировать, то игроки могли бы читерить, меняя данные у себя на устройстве. Поэтому клиент не может напрямую изменять важные данные на сервере — ему нужно отправлять запросы с помощью Remote Event, а сервер уже решает, что с этими данными делать.
  2. Синхронизация: В игре могут быть действия, которые нужно синхронизировать между разными игроками. Например, если один игрок нажал кнопку, то у всех остальных игроков должно что-то произойти. Для этого клиент отправляет событие на сервер, а сервер уже рассылает это событие всем клиентам.

Как работает Remote Event?

Работа с Remote Event основана на двух основных методах:

  1. FireServer — используется клиентом для отправки сообщения на сервер.
  2. FireClient — используется сервером для отправки сообщения на конкретный клиент.
  3. FireAllClients — используется сервером для отправки сообщения всем клиентам.

Пример использования Remote Event

Представим, что у вас в игре есть кнопка, которую игрок нажимает, и это должно привести к каким-то изменениям на сервере, например, выдаче очков.

  1. На стороне клиента:
    • Игрок нажимает кнопку.
    • Скрипт на клиенте (местный скрипт) вызывает RemoteEvent:FireServer(), передавая какие-то данные на сервер, например, количество очков.
  2. На стороне сервера:
    • Сервер получает сообщение от клиента с помощью RemoteEvent.OnServerEvent:Connect(function(player, data) ... end).
    • Обрабатывает это сообщение, например, добавляет очки игроку.
    • Если нужно, сервер может отправить обратно информацию клиенту с помощью RemoteEvent:FireClient().

и сегодня мы как раз таки будем выдывать предмет нашему игру с помощью данной конструкции

так а теперь переходим к скрипту

напомню что надо localsript так как мы будем использовать клиент → серверную архитектуру мы будем обращаться из клиента (компьютера игрока) на серверную функцию мы с вами уже делали такой трюк в этой статье

https://teletype.in/@antichrist_squid/x4AvHZLlEeQ

Переменные

luaCopy codelocal ak47 = script.Parent:WaitForChild("AK-47 BUTTON")
local m12button = script.Parent:WaitForChild("m12 button")
local awpbutton = script.Parent:WaitForChild("AWP Button")
  • ak47, m12button, awpbutton: Здесь создаются три переменные, которые будут ссылаться на кнопки которые мы с вами создали. Они используются для того, чтобы привязать к ним функционал. Каждая переменная ссылается на кнопку с соответствующим названием ("AK-47 BUTTON", "m12 button", "AWP Button"). Эти кнопки находятся в родительском объекте script.Parent, который указывает на родительский элемент скрипта (обычно это GUI объект).

Функция для выдачи оружия

luaCopy codelocal givingweapon = game.ReplicatedStorage.RemoteEvent
  • givingweapon: Создаётся переменная givingweapon, которая ссылается на событие типа RemoteEvent, находящееся в ReplicatedStorage. Это событие будет использовано для отправки сигнала с клиента на сервер (что-то вроде межсессионного сообщения между клиентом и сервером).

Подключение кнопки к функции

luaCopy codeak47.MouseButton1Click:Connect(function(plr)
	givingweapon:FireServer(plr)
end)
  • ak47.MouseButton1Click:Connect(function(plr) ... end): Эта строка кода говорит, что когда игрок нажимает на кнопку ak47, выполняется функция, переданная в Connect.
  • givingweapon:FireServer(plr): Внутри функции вызывается метод FireServer, который отправляет сигнал на сервер с параметром plr (в данном случае, это, вероятно, ссылка на объект игрока).

Что это всё значит?

  • Переменные ak47, m12button, и awpbutton: Эти переменные позволяют вам работать с конкретными кнопками на пользовательском интерфейсе (UI).
  • Событие RemoteEvent (givingweapon): Оно используется для того, чтобы сигнализировать серверу о необходимости выдать игроку оружие. Это нужно, поскольку в Roblox действия, связанные с изменением данных игры, часто должны быть выполнены на сервере.
  • Обработка нажатия кнопки: Когда игрок кликает по кнопке ak47, клиент отправляет запрос на сервер через givingweapon:FireServer(plr). Сервер, получив этот сигнал, может выполнить выдачу оружия.

грубо говоря при нажатии наш скрипт говорит серверу "Эй, босс, этому игроку нужен АК-47!" И сервер мгновенно достаёт оружие и вручает его

хорошо а теперь пришло время к реализации серверного скрипта

добавляем на сервер скрипт

Что такое ServerScriptService?

Когда вы создаёте игру в Roblox, существует два основных типа скриптов: серверные и клиентские. Серверные скрипты работают на сервере и обычно используются для выполнения задач, которые должны быть одинаковыми для всех игроков в игре, например:

  • Управление игровыми объектами и их состояниями (например, позиция или видимость объектов).
  • Обработка действий, связанных с несколькими игроками (например, синхронизация состояния игры).
  • Управление экономикой игры (например, выдача внутриигровой валюты или предметов).

Почему важно использовать ServerScriptService?

  1. Безопасность: Скрипты, размещенные в ServerScriptService, не видны и недоступны для игроков. Это важно, потому что игроки не могут их изменить или взломать. Например, если вы хотите сохранить логику выдачи наград или обработку покупок, лучше разместить этот код в ServerScriptService.
  2. Организация: ServerScriptService помогает структурировать ваш проект. Вы можете хранить все серверные скрипты в одном месте, что упрощает их управление и редактирование.
  3. Серверная логика: В ServerScriptService можно размещать скрипты, которые управляют тем, что происходит на сервере. Например, когда игрок собирает предмет, серверный скрипт может обрабатывать этот процесс, обеспечивая правильное взаимодействие между всеми игроками.

1. Подключение к удалённому событию (RemoteEvent)

local givingweapon = game.ReplicatedStorage.RemoteEvent
  • Эта строка находит и сохраняет ссылку на объект RemoteEvent, который находится в ReplicatedStorage.
  • RemoteEvent — это специальный объект в Roblox, который позволяет клиенту (игроку) и серверу обмениваться сообщениями. В данном случае, это объект, который сервер будет слушать, чтобы понять, когда игрок запросил оружие.

2. Обработка события на сервере

degivingweapon.OnServeшщEvent:Connect(function(plr)
  • Этот код прослушивает событие OnServerEvent, которое срабатывает, когда клиент отправляет сигнал на сервер, используя RemoteEvent.
  • Когда происходит это событие, вызывается функция, которая получает параметр plr (это игрок, который отправил запрос).

3. Клонирование и выдача оружия

game.ServerStorage["ak47"]:Clone().Parent = plr:WaitForChild("Backpack")
game.ServerStorage["ak47"]:Clone().Parent = plr:WaitForChild("StarterGear")
  • game.ServerStorage["ak47"] — этот код обращается к объекту ak47, который хранится в ServerStorage.
    • ServerStorage — это хранилище, в котором хранятся объекты, доступные только серверу. Игроки не могут получить к ним доступ напрямую.
  • Clone() — эта команда создаёт копию объекта ak47.
  • Parent = plr:WaitForChild("Backpack") — эта часть кода перемещает клонированный объект в рюкзак игрока (Backpack). Таким образом, оружие появляется у игрока и он может его использовать.
  • Parent = plr:WaitForChild("StarterGear") — эта строка по вашему желанию она отвечает за то что даже после смерти нашего персонажа во время респпуана у него всероно останется

также в качестве практики реализуете красную кнопку при нажатии на которую у нас пропадает наша меню

теперь к основе

добавляете в это место скрипт и копируете туда наш код от капкана

теперь добавим несколько изменений

нашу основую функцию не меняем единственное что мы поменяем это условие ее вызова

тут нужно немного поменять:

для начала в функции stopBleeding убираем редактирование кирпича

теперь просто удаляем функцию onTouch она нам не нужна:

теперь пишем новую функцию onHealthChanged

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

local function onHealthChanged(health)
	-- Если здоровье уменьшилось и персонаж не кровоточит, запускаем кровотечение
	if health < humanoid.MaxHealth and not isBleeding then
		startBleeding(humanoid.Parent)
	end
end
  1. Определение функции:
    • local function onHealthChanged(health) — Эта строка объявляет локальную функцию с именем onHealthChanged. Функция принимает один параметр — health, который представляет текущее значение здоровья персонажа.
  2. Проверка состояния:
    • if health < humanoid.MaxHealth and not isBleeding then — Эта строка проверяет два условия:
      • health < humanoid.MaxHealth — Проверяет, уменьшилось ли текущее здоровье (health) по сравнению с максимальным здоровьем (humanoid.MaxHealth). Это значит, что персонаж получил урон.
      • not isBleeding — Проверяет, не кровоточит ли уже персонаж (isBleeding должно быть переменной, которая указывает, кровоточит ли персонаж в данный момент).
  3. Запуск эффекта кровотечения:
    • startBleeding(humanoid.Parent) — Если оба условия истинны (здоровье уменьшилось и персонаж не кровоточит), вызывается функция startBleeding, передавая ей родительский объект персонажа (humanoid.Parent). Эта функция отвечает за запуск эффекта кровотечения для персонажа.

Что делает этот код: Этот код следит за изменением здоровья персонажа. Когда здоровье персонажа уменьшается (то есть, когда он получает урон) и при этом он не кровоточит, код запускает функцию, которая инициирует эффект кровотечения.

теперь пишем следующую функцию которая будет отслеживать нашего игрока

  1. Функция onCharacterAdded:
    • Эта функция вызывается каждый раз, когда к игроку добавляется новый персонаж в игру (например, когда игрок респавнится).
    • Функция получает параметр character, который представляет собой объект персонажа игрока.
    • Внутри функции она пытается найти объект Humanoid в персонаже. Humanoid — это компонент, который управляет здоровьем, анимациями и другими аспектами персонажа.
    • Если Humanoid найден (то есть, если он существует), функция подключает две обработки событий:
      • HealthChanged: Событие, которое срабатывает каждый раз, когда изменяется здоровье персонажа. Для этого события подключается функция onHealthChanged, которая будет вызвана при изменении здоровья.
      • Died: Событие, которое срабатывает, когда персонаж умирает. Для этого события подключается функция stopBleeding, которая остановит кровотечение (или выполнит другую соответствующую логику).
  2. Подключение к событию CharacterAdded:
    • player.CharacterAdded:Connect(onCharacterAdded) — эта строка подключает функцию onCharacterAdded к событию, которое срабатывает каждый раз, когда у игрока добавляется новый персонаж.
    • Это означает, что каждый раз, когда персонаж игрока появляется или респавнится, функция onCharacterAdded будет вызвана, чтобы установить необходимые обработчики событий.
  3. Проверка существующего персонажа:
    • if player.Character then onCharacterAdded(player.Character) — это условие проверяет, существует ли персонаж игрока в момент выполнения скрипта. Если персонаж уже существует, функция onCharacterAdded вызывается сразу, чтобы установить обработчики событий, не дожидаясь следующего появления персонажа.

Общий смысл: Этот код обеспечивает автоматическое подключение функций для обработки изменений здоровья и смерти персонажа игрока. Он делает это как при создании нового персонажа, так и при наличии персонажа в момент выполнения скрипта.

теперь можете тестировать все должно работать

я думаю уже после серии про Doors я выдвину пару улучшений который мы сможем добавить

(то куда летит пуля то место и отлетает) тоесть если мы целимя в руку то урон приходится в эту часть тела игрока и эта часть отлетает мы уже сделали с капканом похожее ну а теперь к практике

1 Реализуете кнопку закрывания меню выбора оружия(Легко)

2.Попробуйте сделать то что я написал выше(сложно)