<?xml version="1.0" encoding="utf-8" ?><rss version="2.0" xmlns:tt="http://teletype.in/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>Аллен Волкер</title><generator>teletype.in</generator><description><![CDATA[Аллен Волкер]]></description><image><url>https://img3.teletype.in/files/68/de/68de7cde-1092-4c81-b6af-cd7b6c73ea05.png</url><title>Аллен Волкер</title><link>https://teletype.in/@allenwalker</link></image><link>https://teletype.in/@allenwalker?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=allenwalker</link><atom:link rel="self" type="application/rss+xml" href="https://teletype.in/rss/allenwalker?offset=0"></atom:link><atom:link rel="next" type="application/rss+xml" href="https://teletype.in/rss/allenwalker?offset=10"></atom:link><atom:link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></atom:link><pubDate>Sun, 14 Jun 2026 03:51:29 GMT</pubDate><lastBuildDate>Sun, 14 Jun 2026 03:51:29 GMT</lastBuildDate><item><guid isPermaLink="true">https://teletype.in/@allenwalker/robloxstudio</guid><link>https://teletype.in/@allenwalker/robloxstudio?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=allenwalker</link><comments>https://teletype.in/@allenwalker/robloxstudio?utm_source=teletype&amp;utm_medium=feed_rss&amp;utm_campaign=allenwalker#comments</comments><dc:creator>allenwalker</dc:creator><title>📘 Программирование на Lua в Roblox. Полный курс от новичка до уверенного разработчика.</title><pubDate>Wed, 21 May 2025 14:18:11 GMT</pubDate><description><![CDATA[print(&quot;Привет, Roblox!&quot;)]]></description><content:encoded><![CDATA[
  <h2 id="Hhis">Оглавление:</h2>
  <p id="6FPT"></p>
  <h2 id="f8bt">🔹 Глава 1: Введение в Roblox и Lua.</h2>
  <h2 id="VCSv">🔹 Глава 2: Знакомство с интерфейсом Roblox Studio.</h2>
  <h2 id="bOlX">🔹 Глава 3: Основы программирования на Lua.</h2>
  <h2 id="N9yA">🔹 Глава 4: Работа с объектами и сервисами Roblox.</h2>
  <h2 id="rBlt">🔹 Глава 5: События и взаимодействие в Roblox.</h2>
  <h2 id="avyQ">🔹 Глава 6: GUI — Создание интерфейса.</h2>
  <h2 id="Mkn1">🔹 Глава 7: Работа с игроками и персонажами.</h2>
  <h2 id="Gxws">🔹 Глава 8: Анимация и физика персонажей.</h2>
  <h2 id="EUaQ">🔹 Глава 9: Сохранение данных с DataStore.</h2>
  <h2 id="EEr1">🔹 Глава 10: Клиент-серверное взаимодействие.</h2>
  <h2 id="55tM">🔹 Глава 11: Модульные скрипты и библиотеки.</h2>
  <h2 id="5zxf">🔹 Глава 12: Работа с файлами и внешними данными.</h2>
  <h2 id="vEu9">🔹 Глава 13: JSON и работа с форматами данных.</h2>
  <h2 id="x4mu">🔹 Глава 14: Работа с аудио и звуками.</h2>
  <h2 id="VwBx">🔹 Глава 15: Таймеры, корутины и многозадачность.</h2>
  <h2 id="pAvP">🔹 Глава 16: Обработка ошибок и отладка.</h2>
  <h2 id="lzfM">🔹 Глава 17: Плагины для Roblox Studio.</h2>
  <h2 id="wQ5t">🔹 Глава 18: Мультиплеер и работа с командами.</h2>
  <h2 id="OtHZ">🔹 Глава 19: Оптимизация и производительность.</h2>
  <p id="NGsl"></p>
  <h2 id="UcU7"></h2>
  <p id="WhVs"></p>
  <h2 id="x0jh">🔹 Глава 1: Введение в Roblox и Lua.</h2>
  <h3 id="cKBc">Содержание:</h3>
  <h4 id="BZIf">Что такое Roblox?</h4>
  <ul id="u6hf">
    <li id="druA">Обзор платформы.</li>
    <li id="Xc2r">Возможности: создание игр, монетизация, сообщество.</li>
    <li id="kkz0">История развития.</li>
  </ul>
  <h4 id="tiNW">Что такое Lua?</h4>
  <ul id="vH95">
    <li id="zOcq">Краткая история языка.</li>
    <li id="Ruaa">Почему именно Lua используется в Roblox.</li>
    <li id="413z">Особенности легковесности и скорости.</li>
  </ul>
  <h4 id="9xge">Зачем учить программирование через Roblox?</h4>
  <ul id="64Zz">
    <li id="MReS">Логическое мышление.</li>
    <li id="We6z">Основы алгоритмов.</li>
    <li id="AI4x">Работа с событиями, объектами, данными.</li>
    <li id="Qvrh">Возможность создания реальных проектов.</li>
  </ul>
  <h4 id="c3Bz">Как устроена эта книга?</h4>
  <ul id="bi3O">
    <li id="P2X7">Объяснение структуры.</li>
    <li id="zwzL">Советы по прохождению.</li>
    <li id="Wuja">Как использовать примеры.</li>
  </ul>
  <h4 id="fYGS">Первые шаги: установка и запуск Roblox Studio</h4>
  <ul id="Pzu4">
    <li id="MyOO">Пошаговая инструкция по регистрации.</li>
    <li id="M6s1">Скачивание и запуск Roblox Studio.</li>
    <li id="7V9j">Создание первого Place.</li>
    <li id="9rcK">Сохранение проекта.</li>
  </ul>
  <h4 id="FMpP">Термины и понятия</h4>
  <ul id="JLe8">
    <li id="huWX"><code>Place</code>, <code>Game</code>, <code>Server</code>, <code>Client</code>.</li>
    <li id="vJXa">Разница между клиентом и сервером.</li>
    <li id="VuqL">Что такое <code>Workspace</code>, <code>StarterGui</code>, <code>ReplicatedStorage</code>.</li>
  </ul>
  <h4 id="52sF">Упражнения:</h4>
  <ul id="70BM">
    <li id="KmeL">Установи Roblox Studio.</li>
    <li id="H8JS">Создай новый Place и сохрани его как &quot;MyFirstGame&quot;.</li>
    <li id="pvt5">Добавь в Workspace одну Part и перемести её на высоту 10.</li>
  </ul>
  <p id="ym6k"></p>
  <h2 id="Wdeh">🔹 Глава 2: Знакомство с интерфейсом Roblox Studio.</h2>
  <h3 id="AMCO">Содержание:</h3>
  <h4 id="iUDl">Интерфейс студии</h4>
  <ul id="CRfz">
    <li id="LouV">Toolbar: основные инструменты.</li>
    <li id="kWzk">Viewport: игровое окно.</li>
    <li id="u4g8">Explorer: дерево объектов.</li>
    <li id="NwKV">Properties: редактор свойств.</li>
    <li id="I9P4">Output: вывод скриптов и ошибок.</li>
  </ul>
  <h4 id="R89m">Основные папки и сервисы</h4>
  <ul id="Z9l8">
    <li id="KgOK"><code>Workspace</code> – где происходит действие.</li>
    <li id="FwDZ"><code>Players</code> – информация об игроках.</li>
    <li id="TsW4"><code>Lighting</code> – управление освещением.</li>
    <li id="TRQE"><code>StarterGui</code> – UI для новых игроков.</li>
    <li id="Degv"><code>ServerScriptService</code> – серверные скрипты.</li>
    <li id="48RA"><code>ReplicatedStorage</code> – данные для клиента и сервера.</li>
    <li id="updY"><code>Lighting</code> – управление светом и тенью.</li>
  </ul>
  <h4 id="Fug4">Работа с объектами</h4>
  <ul id="aZuW">
    <li id="dlLO">Создание, удаление, копирование.</li>
    <li id="64bT">Перемещение, поворот, масштабирование.</li>
    <li id="CUmi">Изменение цвета, текстуры, размера.</li>
  </ul>
  <h4 id="qg5o">Базовые понятия:</h4>
  <ul id="m73N">
    <li id="HUZs">Instance – объект в Roblox.</li>
    <li id="Tbkc">Parent/Child – иерархия объектов.</li>
    <li id="qgNI">Property – параметр объекта.</li>
  </ul>
  <h4 id="cM82">Практическое задание:</h4>
  <ul id="G6WX">
    <li id="1Ui7">Создай комнату из Part&#x27;ов.</li>
    <li id="qChV">Добавь в неё дверь и кнопку.</li>
    <li id="8FAQ">Настрой освещение.</li>
  </ul>
  <p id="FHcp"></p>
  <h2 id="iMtd">🔹 Глава 3: Основы программирования на Lua.</h2>
  <h3 id="DQ6c">Содержание:</h3>
  <h4 id="26X0">Что такое язык программирования?</h4>
  <ul id="IHJS">
    <li id="uVSX">Понятие синтаксиса.</li>
    <li id="gVbr">Компиляция vs интерпретация.</li>
    <li id="vBuH">Lua как скриптовый язык.</li>
  </ul>
  <h4 id="cX87">Первая программа</h4>
  <p id="drGC"></p>
  <p id="skqa"><code>print(&quot;Привет, Roblox!&quot;)</code></p>
  <p id="RdmF"></p>
  <p id="nlqB">Структура программы</p>
  <ul id="CKI0">
    <li id="NE1C">Комментарии: однострочные и многострочные.</li>
    <li id="7hRy">Инструкции и выражения.</li>
    <li id="Z1c7">Блоки кода.</li>
  </ul>
  <h4 id="OkwH">Переменные и типы данных</h4>
  <ul id="poIs">
    <li id="5YZN"><code>local</code> vs <code>global</code>.</li>
    <li id="mtIF">Числа, строки, булевы значения.</li>
    <li id="ULUn">nil и что это значит.</li>
    <li id="hyC0">Преобразование типов.</li>
  </ul>
  <h4 id="wyHF">Операторы</h4>
  <ul id="pDHN">
    <li id="c8QP">Арифметические: +, -, *, /, ^, %</li>
    <li id="yQaD">Сравнения: ==, ~=, &lt;, &gt;, &lt;=, &gt;=</li>
    <li id="f5nE">Логические: and, or, not</li>
    <li id="VvlL">Конкатенация строк: ..</li>
  </ul>
  <h4 id="oiT5">Условия</h4>
  <ul id="7q0k">
    <li id="8UBz">if...then...else</li>
    <li id="HP0s">elseif</li>
    <li id="A6F8">switch-like конструкции через if</li>
    <li id="uDLf">Таблицы как условие</li>
  </ul>
  <h4 id="SacP">Циклы</h4>
  <ul id="qILi">
    <li id="Cm4e">for i = a, b do ... end</li>
    <li id="nFCU">while condition do ... end</li>
    <li id="0jKt">repeat ... until condition</li>
    <li id="xBhW">break и continue</li>
  </ul>
  <h4 id="7bmN">Функции</h4>
  <ul id="7iGB">
    <li id="5WIW">Создание функций.</li>
    <li id="eIYV">Параметры и возврат значений.</li>
    <li id="2fbl">Локальные и глобальные функции.</li>
    <li id="cdBb">Анонимные функции.</li>
  </ul>
  <h4 id="some">Таблицы</h4>
  <ul id="Zk5T">
    <li id="kbbv">Создание таблиц.</li>
    <li id="LuZi">Индексация: числовая и строковая.</li>
    <li id="N2th">Методы работы: ipairs, pairs.</li>
    <li id="HCEi">Таблицы как структуры данных.</li>
  </ul>
  <h4 id="fGut">Упражнения:</h4>
  <ul id="v6lI">
    <li id="fRw0">Напиши функцию, которая считает площадь прямоугольника.</li>
    <li id="cQYE">Напиши цикл, который выводит числа от 1 до 20, но пропускает чётные.</li>
    <li id="hEiA">Создай таблицу с информацией о персонаже: имя, уровень, здоровье.</li>
  </ul>
  <p id="IzfO"></p>
  <h2 id="rZtL">🔹 Глава 4: Работа с объектами и сервисами Roblox.</h2>
  <hr />
  <h3 id="spoN">Введение</h3>
  <p id="7jEQ">В этой главе ты узнаешь:</p>
  <ul id="4wwd">
    <li id="3SF4">Как устроены объекты в Roblox.</li>
    <li id="Fy5G">Что такое <code>Instance</code> и как им управлять.</li>
    <li id="eTgM">Как работать с основными сервисами: <code>Workspace</code>, <code>Players</code>, <code>ReplicatedStorage</code>.</li>
    <li id="0iki">Как создавать, изменять и удалять объекты через код.</li>
    <li id="4qNQ">Как использовать дерево объектов (Explorer) для поиска нужных элементов.</li>
  </ul>
  <hr />
  <h3 id="5B5n">4.1 — Основы объектов в Roblox</h3>
  <h4 id="grYS">Что такое Instance?</h4>
  <p id="wzI7">Все объекты в Roblox — это <code>Instances</code>. Это базовый класс, из которого наследуются все остальные объекты: <code>Part</code>, <code>Model</code>, <code>Folder</code>, <code>Script</code>, <code>GuiObject</code> и т.д.</p>
  <p id="eqzi"></p>
  <p id="upoc"><code>local part = Instance.new(&quot;Part&quot;)</code></p>
  <p id="jp9h"><code>part.Name = &quot;МояЧасть&quot;</code></p>
  <p id="NDhi"><code>part.Parent = workspace</code></p>
  <h4 id="BfU4">Иерархия объектов</h4>
  <p id="kvuh">Каждый объект имеет родителя (<code>Parent</code>) и может содержать дочерние элементы (<code>Children</code>).</p>
  <p id="qcwl"></p>
  <p id="KjIN"><code>local folder = Instance.new(&quot;Folder&quot;)</code></p>
  <p id="7ww7"><code>folder.Name = &quot;Группа&quot;</code></p>
  <p id="aH3i"><code>folder.Parent = workspace</code></p>
  <p id="iVq9"><code>local part = Instance.new(&quot;Part&quot;)</code></p>
  <p id="yBc5"><code>part.Parent = folder</code></p>
  <p id="4q2L">Теперь <code>Part</code> находится внутри <code>Folder</code>.</p>
  <hr />
  <h3 id="pgAb">4.2 — Сервисы Roblox</h3>
  <p id="qXnx">Roblox предоставляет ряд встроенных сервисов, которые можно получить через <code>game:GetService()</code>.</p>
  <h4 id="9SPi">Workspace</h4>
  <p id="2wIH">Игровой мир, где находятся все части, модели и персонажи.</p>
  <p id="zwtZ"></p>
  <p id="IfDZ"><code>local workspace = game:GetService(&quot;Workspace&quot;)</code></p>
  <h4 id="gvaD">Players</h4>
  <p id="SCtm">Список всех игроков в игре.</p>
  <p id="vqzL"></p>
  <p id="vwPd"><code>local players = game:GetService(&quot;Players&quot;)</code></p>
  <h4 id="N4u5">ReplicatedStorage</h4>
  <p id="bLxt">Хранилище объектов, доступных как серверу, так и клиенту.</p>
  <p id="iTzf"></p>
  <p id="NGVq"><code>local replicatedStorage = game:GetService(&quot;ReplicatedStorage&quot;)</code></p>
  <h4 id="BcAk">ServerScriptService</h4>
  <p id="dCa1">Серверные скрипты. Сюда помещаются скрипты, работающие только на сервере.</p>
  <p id="Ju72"></p>
  <p id="Tjx2"><code>local serverScripts = game:GetService(&quot;ServerScriptService&quot;)</code></p>
  <h4 id="AXY3">StarterGui / PlayerGui</h4>
  <p id="EGw1">Интерфейс игрока. <code>StarterGui</code> — шаблон для новых игроков. <code>PlayerGui</code> — UI конкретного игрока.</p>
  <p id="NT0s"></p>
  <p id="Rk1X"><code>local player = players.LocalPlayer</code></p>
  <p id="wzkg"><code>local gui = player.PlayerGui</code></p>
  <hr />
  <h3 id="aY73">4.3 — Создание и управление объектами</h3>
  <h4 id="gP8l">Создание объекта</h4>
  <p id="1RTZ"></p>
  <p id="h5sh"><code>local cube = Instance.new(&quot;Part&quot;)</code></p>
  <p id="YUAd"><code>cube.Size = Vector3.new(2, 2, 2)</code></p>
  <p id="1suL"><code>cube.BrickColor = BrickColor.Red()</code></p>
  <p id="3Rbi"><code>cube.Anchored = true</code></p>
  <p id="GqWO"><code>cube.Position = Vector3.new(0, 5, 0)</code></p>
  <p id="nEOH"><code>cube.Parent = workspace</code></p>
  <h4 id="CfgT">Изменение свойств объекта</h4>
  <p id="cOHC"></p>
  <p id="zwuZ"><code>cube.Transparency = 0.5 -- делает часть полупрозрачной</code></p>
  <p id="pnQr"><code>cube.Shape = Enum.PartType.Ball -- делает часть шаром</code></p>
  <h4 id="gD2r">Удаление объекта</h4>
  <p id="t0wx"></p>
  <p id="fPrc"><code>cube:Destroy() -- удаляет объект</code></p>
  <h4 id="HXvi"></h4>
  <h4 id="Tt8D">Поиск объекта</h4>
  <p id="Z4jl"></p>
  <p id="ALCI"><code>local found = workspace:FindFirstChild(&quot;МояЧасть&quot;)</code></p>
  <p id="d1SR"><code>if found then</code></p>
  <p id="UwKx"><code>        print(&quot;Найден объект: &quot; .. found.Name)</code></p>
  <p id="AE9N"><code>else</code></p>
  <p id="rhKN"><code>        print(&quot;Объект не найден.&quot;)</code></p>
  <p id="XRjA"><code>end</code></p>
  <hr />
  <h3 id="q1Ud">4.4 — Работа с событиями объектов</h3>
  <p id="fBl0"></p>
  <p id="1Ka5">Каждый объект может иметь события. Например, <code>Part</code> имеет событие <code>Touched</code>.</p>
  <p id="F8Pb"></p>
  <p id="M6ga"><code>cube.Touched:Connect(function(hit)</code></p>
  <p id="RXuf"><code>local character = hit.Parent</code></p>
  <p id="b8rP"><code>if character:FindFirstChild(&quot;Humanoid&quot;) then</code></p>
  <p id="HEqO"><code>print(&quot;Персонаж коснулся куба!&quot;)</code></p>
  <p id="dtH0"><code>     end</code></p>
  <p id="OIon"><code>end)</code></p>
  <hr />
  <h3 id="80LU">4.5 — Работа с моделями и группировкой объектов</h3>
  <h4 id="B3Q4">Создание модели</h4>
  <p id="Ok5r"></p>
  <p id="ObNz"><code>local model = Instance.new(&quot;Model&quot;)</code></p>
  <p id="10oI"><code>model.Name = &quot;Герой&quot;</code></p>
  <p id="CaED"><code>model.Parent = workspace</code></p>
  <p id="c72H"><code>local head = Instance.new(&quot;Part&quot;)</code></p>
  <p id="qQJX"><code>head.Name = &quot;Head&quot;</code></p>
  <p id="Fjkl"><code>head.Parent = model</code></p>
  <p id="nECe"><code>local torso = Instance.new(&quot;Part&quot;)</code></p>
  <p id="0J08"><code>torso.Name = &quot;Torso&quot;</code></p>
  <p id="V9fG"><code>torso.Parent = model</code></p>
  <p id="A5Py">Теперь <code>Model</code> содержит две <code>Part</code>: Head и Torso.</p>
  <hr />
  <h3 id="c8zQ">4.6 — Практическое задание</h3>
  <p id="3Dlj"><strong>Задача:</strong><br />Создай дом с крышей, стенами и дверью. Добавь освещение. При нажатии на дверь — она должна открываться.</p>
  <p id="oPV0"><strong>Шаги:</strong></p>
  <ol id="WIbI">
    <li id="IuCo">Создай несколько Part для стен, крыши и двери.</li>
    <li id="Hh5S">Сгруппируй их в одну модель.</li>
    <li id="bIF9">Добавь двери <code>ClickDetector</code>.</li>
    <li id="38kk">При нажатии поворачивай дверь на 90 градусов с помощью <code>CFrame</code>.</li>
  </ol>
  <p id="T1d2"><strong>Пример кода для двери:</strong></p>
  <p id="RJm1"></p>
  <p id="Vswa"><code>local door = workspace.Door</code></p>
  <p id="DOyA"><code>door.ClickDetector.MouseClick:Connect(function(player)</code></p>
  <p id="9CCN"><code>door.CFrame = door.CFrame * CFrame.Angles(0, math.rad(90), 0)</code></p>
  <p id="emGm"><code>end)</code></p>
  <hr />
  <h3 id="MMgz">4.7 — Советы и рекомендации</h3>
  <ul id="G85h">
    <li id="JuZL">Используй <code>print()</code> для проверки, создан ли объект.</li>
    <li id="lxfU">Не забывай указывать <code>Parent</code>, иначе объект останется невидимым.</li>
    <li id="TSsE">Используй <code>Folder</code> для группировки объектов.</li>
    <li id="r3VH">Тестируй взаимодействие с объектами через <code>Touched</code>, <code>MouseClick</code> и другие события.</li>
  </ul>
  <hr />
  <h3 id="XRH3">4.8 — Ключевые термины</h3>
  <p id="Ik7s"></p>
  <p id="jlXu">Термин - Описание</p>
  <p id="Kkt7">Instance - Базовый объект в Roblox</p>
  <p id="0Uyx">Parent - Родительский объект</p>
  <p id="HHvH">Child - Дочерний объект</p>
  <p id="Yy7Q">Workspace - Основное игровое пространство</p>
  <p id="5SUP">Model - Группировка объектов</p>
  <p id="UOr2">ClickDetector - Компонент для обнаружения кликов</p>
  <p id="zvOQ">Touched - Событие прикосновения объекта</p>
  <p id="kVjl"></p>
  <h1 id="PAK4">🔹 Глава 5: События и взаимодействие в Roblox.</h1>
  <hr />
  <h2 id="spnx">Введение</h2>
  <p id="6qFD">В этой главе ты узнаешь:</p>
  <ul id="NkTq">
    <li id="50LE">Что такое события (Events) в Roblox.</li>
    <li id="dYHx">Как использовать <code>.Connect()</code> для обработки событий.</li>
    <li id="GssD">Как работать с часто используемыми событиями: <code>Touched</code>, <code>MouseClick</code>, <code>Changed</code>, <code>ChildAdded</code>.</li>
    <li id="ZvcK">Как создавать собственные события через <code>BindableEvent</code> и <code>RemoteEvent</code>.</li>
    <li id="MVib">Как организовывать клиент-серверное взаимодействие.</li>
  </ul>
  <hr />
  <h2 id="U6Cg">5.1 — Что такое события?</h2>
  <p id="btDp">События — это реакции на действия, происходящие в игре. Например:</p>
  <ul id="ssmM">
    <li id="lgEV">Игрок нажал на кнопку → событие <code>MouseClick</code></li>
    <li id="XEq8">Персонаж прыгнул → событие <code>Jumped</code></li>
    <li id="DlBM">Объект изменил своё свойство → событие <code>Changed</code></li>
  </ul>
  <h3 id="ZcCn">Пример:</h3>
  <p id="F3AR"></p>
  <p id="UUiZ"><code>local button = workspace.Button</code></p>
  <p id="XKs2"><code>button.ClickDetector.MouseClick:Connect(function(player)</code></p>
  <p id="pyVt"><code>            print(player.Name .. &quot; нажал на кнопку!&quot;)</code></p>
  <p id="q17j"><code>end)</code></p>
  <hr />
  <h2 id="WpZa">5.2 — Основные типы событий</h2>
  <p id="6BMC">Тип события - Где используется - Описание</p>
  <p id="lS3m">MouseClick - ClickDetector - Клик мышью по объекту</p>
  <p id="x7mT">Touched - BasePart - Прикосновение к объекту</p>
  <p id="q4Yy">Changed - Instance - Изменение любого свойства</p>
  <p id="yA5e">ChildAdded/Removed - Instance - Добавление или удаление дочернего элемента</p>
  <p id="9TtM">Humanoid.Jumped - Humanoid - Прыжок персонажа</p>
  <p id="frJU">PlayerAdded - Players - Игрок зашёл в игру</p>
  <p id="vTA5">PlayerRemoving - Players - Игрок вышел из игры</p>
  <hr />
  <h2 id="Z4SU">5.3 — Подписка на события: <code>.Connect()</code></h2>
  <p id="MT3G">Чтобы отреагировать на событие, нужно подписаться на него с помощью метода <code>.Connect()</code>.</p>
  <p id="VuRd"></p>
  <p id="PAgw"><code>workspace.Door.Touched:Connect(function(hit)</code></p>
  <p id="0EkZ"><code>          local character = hit.Parent</code></p>
  <p id="gkig"><code>          if character:FindFirstChild(&quot;Humanoid&quot;) then</code></p>
  <p id="XZJv"><code>                    print(&quot;Кто-то коснулся двери!&quot;)</code></p>
  <p id="AFOR"><code>          end</code></p>
  <p id="xBO9"><code>end)</code></p>
  <hr />
  <h2 id="ky3i">5.4 — Использование Changed</h2>
  <p id="re66">Это событие вызывается при изменении любого свойства объекта.</p>
  <p id="Dvb8"></p>
  <p id="ErcN"><code>local part = workspace.Part</code></p>
  <p id="Giqt"><code>part.Changed:Connect(function(property)</code></p>
  <p id="vnyL"><code>              print(&quot;Изменилось свойство: &quot; .. property)</code></p>
  <p id="XZqj"><code>end)</code></p>
  <p id="rONf">Можно отслеживать конкретное свойство:</p>
  <p id="w37r"></p>
  <p id="z01g"><code>if property == &quot;Transparency&quot; then</code></p>
  <p id="6hK8"><code>             print(&quot;Прозрачность изменилась&quot;)</code></p>
  <p id="guWf"><code>end</code></p>
  <hr />
  <h2 id="rRAC">5.5 — ChildAdded и ChildRemoved</h2>
  <p id="wRFY">Эти события позволяют отслеживать добавление или удаление дочерних объектов.</p>
  <p id="peAH"></p>
  <p id="OefR"><code>workspace.ChildAdded:Connect(function(child)</code></p>
  <p id="R2tD"><code>              print(&quot;Добавлен объект: &quot; .. child.Name)</code></p>
  <p id="Yj8U"><code>end)</code></p>
  <p id="buBp"><code>workspace.ChildRemoved:Connect(function(child)</code></p>
  <p id="x9t1"><code>              print(&quot;Удалён объект: &quot; .. child.Name)</code></p>
  <p id="vIEZ"><code>end)</code></p>
  <hr />
  <h2 id="llkH">5.6 — Создание своих событий</h2>
  <p id="V62Q">Иногда тебе нужно передавать информацию между скриптами. Для этого можно использовать:</p>
  <h3 id="tpEN">BindableEvent</h3>
  <p id="yLy3"></p>
  <p id="cbOV"><code>-- ServerScriptService</code></p>
  <p id="9sYB"><code>local event = Instance.new(&quot;BindableEvent&quot;)</code></p>
  <p id="QL2a"><code>event.Name = &quot;DoorOpened&quot;</code></p>
  <p id="3smf"><code>event.Parent = workspace</code></p>
  <p id="FTXw"><code>event.Event:Connect(function()</code></p>
  <p id="yWrW"><code>               print(&quot;Дверь открыта!&quot;)</code></p>
  <p id="IZnL"><code>end)</code></p>
  <p id="KsP9"><code>-- Где-то в другом скрипте</code></p>
  <p id="yttt"><code>event:Fire()</code></p>
  <hr />
  <h2 id="vHrG">5.7 — RemoteEvent: клиент ↔ сервер</h2>
  <p id="4OI6"><code>RemoteEvent</code> позволяет отправлять данные между клиентом и сервером.</p>
  <h3 id="0tKZ">На сервере:</h3>
  <p id="yN2N"></p>
  <p id="WVJ2"><code>-- ServerScriptService</code></p>
  <p id="OMCo"><code>local remote = Instance.new(&quot;RemoteEvent&quot;)</code></p>
  <p id="pMEW"><code>remote.Name = &quot;PlayerJumped&quot;</code></p>
  <p id="WOTW"><code>remote.Parent = game.ReplicatedStorage</code></p>
  <p id="Ri1M"><code>remote.OnServerEvent:Connect(function(player)</code></p>
  <p id="ErHk"><code>             print(player.Name .. &quot; прыгнул!&quot;)</code></p>
  <p id="2K65"><code>end)</code></p>
  <h3 id="jZPk">На клиенте (LocalScript):</h3>
  <p id="3HvL"></p>
  <p id="FRwY"><code>-- StarterPlayerScripts</code></p>
  <p id="WaF6"><code>local remote = game.ReplicatedStorage.PlayerJumped</code></p>
  <p id="CtVo"><code>game.Players.LocalPlayer.Character.Humanoid.Jumped:Connect(function()</code></p>
  <p id="Excc"><code>        remote:FireServer()</code></p>
  <p id="TG3I"><code>end)</code></p>
  <hr />
  <h2 id="M1tc">5.8 — RemoteFunction: запрос-ответ</h2>
  <p id="tRjn">Если тебе нужно получить ответ от сервера, используй <code>RemoteFunction</code>.</p>
  <h3 id="yGCf">На сервере:</h3>
  <p id="RUHV"></p>
  <p id="9mOS"><code>local remoteFunc = Instance.new(&quot;RemoteFunction&quot;)</code></p>
  <p id="0J7N"><code>remoteFunc.Name = &quot;GetData&quot;</code></p>
  <p id="rcTf"><code>remoteFunc.Parent = game.ReplicatedStorage</code></p>
  <p id="MukM"><code>remoteFunc.OnServerInvoke = function(player)</code></p>
  <p id="exLW"><code>        return {coins = 100, level = 1}</code></p>
  <p id="ODau"><code>end</code></p>
  <h3 id="UbQZ"><code>На клиенте:</code></h3>
  <p id="JDRn"></p>
  <p id="G3ar"><code>local data = game.ReplicatedStorage.GetData:InvokeServer()</code></p>
  <p id="hpmT"><code>print(data.level)</code></p>
  <hr />
  <h2 id="OFob">5.9 — Практическое задание</h2>
  <h3 id="SBde">Задача:</h3>
  <p id="3mGQ">Создай систему, которая отслеживает, когда игрок нажимает на кнопку, и увеличивает счётчик нажатий. После 5 нажатий — открывает дверь.</p>
  <h3 id="30OZ">Шаги:</h3>
  <ol id="di2S">
    <li id="9Epn">Создай кнопку (<code>Part</code>) с <code>ClickDetector</code>.</li>
    <li id="fG1V">Создай переменную-счётчик.</li>
    <li id="n5kY">При каждом клике увеличивай счётчик.</li>
    <li id="JCaN">Если счётчик &gt;= 5 — уничтожь дверь или перемести её.</li>
  </ol>
  <h3 id="42M7">Пример кода:</h3>
  <p id="dO9e"></p>
  <p id="owp1"><code>local clickCount = 0</code></p>
  <p id="TG3H"><code>local door = workspace.Door</code></p>
  <p id="lQim"><code>workspace.Button.ClickDetector.MouseClick:Connect(function(player)</code></p>
  <p id="CxDb"><code>           clickCount += 1</code></p>
  <p id="v9ER"><code>           print(&quot;Нажато раз: &quot; .. clickCount)</code></p>
  <p id="xEi6"><code>           if clickCount &gt;= 5 then</code></p>
  <p id="rHkL"><code>                      door:Destroy()</code></p>
  <p id="KkYM"><code>           end</code></p>
  <p id="rN7H"><code>end)</code></p>
  <hr />
  <h2 id="RjYv">5.10 — Советы и рекомендации</h2>
  <ul id="yOnm">
    <li id="nJNw">Не забывай проверять существование объекта перед подключением события.</li>
    <li id="amnU">Используй <code>print()</code> для отладки.</li>
    <li id="tqvr">Убедись, что <code>ClickDetector</code> установлен и имеет правильный радиус.</li>
    <li id="VL7J">Используй <code>BindableEvent</code> для внутренней логики.</li>
    <li id="CtI6">Используй <code>RemoteEvent</code> для связи между клиентом и сервером.</li>
  </ul>
  <hr />
  <h2 id="tLxi">5.11 — Ключевые термины</h2>
  <p id="vKqO">Термин - Описание</p>
  <p id="QGif">Event - Событие, которое происходит в игре</p>
  <p id="HUGN">.Connect() - Метод для подписки на событие</p>
  <p id="rtE3">Changed - Событие изменения свойства</p>
  <p id="Be01">Touched - Событие прикосновения объекта</p>
  <p id="afUO">RemoteEvent - Событие между клиентом и сервером</p>
  <p id="9Z4A">RemoteFunction - Вызов функции на сервере с возвратом значения</p>
  <p id="Lo5m">BindableEvent - Локальное событие внутри игры</p>
  <p id="7qh8"></p>
  <h1 id="tEgG">🔹 Глава 6: GUI — Создание интерфейса.</h1>
  <hr />
  <h2 id="7r6K">Введение</h2>
  <p id="mu5N">В этой главе ты узнаешь:</p>
  <ul id="CatB">
    <li id="PxlS">Как создавать и управлять элементами интерфейса (GUI).</li>
    <li id="yWyl">Как использовать <code>ScreenGui</code>, <code>TextLabel</code>, <code>TextButton</code>, <code>ImageButton</code>.</li>
    <li id="TGZI">Как добавлять изображения, анимации и динамическое обновление.</li>
    <li id="c4bu">Как реагировать на действия игрока через кнопки и поля ввода.</li>
    <li id="82Zc">Как правильно размещать элементы на экране с помощью <code>UDim2</code>.</li>
  </ul>
  <hr />
  <h2 id="qxmr">6.1 — Что такое GUI?</h2>
  <p id="gB4j">GUI (Graphical User Interface) — это графический интерфейс, который игрок видит на экране. Он может содержать:</p>
  <ul id="OyHH">
    <li id="5VKC">Текстовые надписи</li>
    <li id="twbx">Кнопки</li>
    <li id="Lgw7">Изображения</li>
    <li id="TC2D">Индикаторы здоровья, очков, таймеров</li>
  </ul>
  <h3 id="j8gj">Основные компоненты GUI:</h3>
  <ul id="3Ypr">
    <li id="yxU7"><code>ScreenGui</code> — контейнер для всех элементов интерфейса.</li>
    <li id="24qm"><code>Frame</code> — панель или фон.</li>
    <li id="7yRv"><code>TextLabel</code> — текстовая надпись.</li>
    <li id="jpbv"><code>TextButton</code> — кликабельная кнопка.</li>
    <li id="yfFz"><code>ImageButton</code> — кнопка с изображением.</li>
    <li id="MI0x"><code>ImageLabel</code> — отображение картинки.</li>
  </ul>
  <hr />
  <h2 id="B9uR">6.2 — Добавление GUI к игроку</h2>
  <p id="LIoX"></p>
  <p id="7HUx"><code>local player = game.Players.LocalPlayer</code></p>
  <p id="eqGy"><code>local gui = Instance.new(&quot;ScreenGui&quot;)</code></p>
  <p id="EjER"><code>gui.Parent = player.PlayerGui</code></p>
  <p id="E13u"><code>local label = Instance.new(&quot;TextLabel&quot;)</code></p>
  <p id="E9D6"><code>label.Text = &quot;Добро пожаловать!&quot;</code></p>
  <p id="ndFz"><code>label.Size = UDim2.new(0, 200, 0, 50)</code></p>
  <p id="EJcy"><code>label.Position = UDim2.new(0.5, -100, 0.1, 0)</code></p>
  <p id="wUVW"><code>label.BackgroundColor3 = Color3.fromRGB(255, 255, 255)</code></p>
  <p id="V5KE"><code>label.TextColor3 = Color3.fromRGB(0, 0, 0)</code></p>
  <p id="U58p"><code>label.FontSize = Enum.FontSize.Size24</code></p>
  <p id="jofQ"><code>label.Parent = gui</code></p>
  <hr />
  <h2 id="oW6k">6.3 — Работа с размерами и позицией: UDim2</h2>
  <p id="nh99"><code>UDim2</code> используется для задания размера и положения элементов относительно экрана.</p>
  <p id="w6DB"></p>
  <p id="3Z1k"><code>-- Ширина: 200 пикселей, высота: 50 пикселей</code></p>
  <p id="Wo8I"><code>UDim2.new(0, 200, 0, 50)</code></p>
  <p id="ph48"><code>-- Позиция: по центру по X, 10% сверху по Y</code></p>
  <p id="3LQr"><code>UDim2.new(0.5, -100, 0.1, 0)</code></p>
  <p id="TD5y"></p>
  <p id="IopJ">Значение - Описание</p>
  <p id="6s4o"><code>0, x</code> - Абсолютное значение в пикселях</p>
  <p id="nEfq"><code>1, x</code> - Относительное значение (доли от размера родителя)</p>
  <hr />
  <h2 id="NYMH">6.4 — Создание кнопок</h2>
  <p id="9F7R"></p>
  <p id="77xJ"><code>local button = Instance.new(&quot;TextButton&quot;)</code></p>
  <p id="zwxK"><code>button.Text = &quot;Нажми меня&quot;</code></p>
  <p id="lyx9"><code>button.Size = UDim2.new(0, 150, 0, 50)</code></p>
  <p id="NKLN"><code>button.Position = UDim2.new(0.5, -75, 0.2, 0)</code></p>
  <p id="Y6ba"><code>button.BackgroundColor3 = Color3.fromRGB(100, 200, 255)</code></p>
  <p id="LHND"><code>button.Parent = gui</code></p>
  <p id="Wp0V"><code>button.MouseButton1Down:Connect(function()</code></p>
  <p id="od64"><code>            print(&quot;Кнопка нажата!&quot;)</code></p>
  <p id="n445"><code>end)</code></p>
  <hr />
  <h2 id="QkHg">6.5 — Использование изображений</h2>
  <h3 id="qeRA">ImageLabel — показывает изображение:</h3>
  <p id="OnVY"></p>
  <p id="GC5D"><code>local image = Instance.new(&quot;ImageLabel&quot;)</code></p>
  <p id="5lgi"><code>image.Image = &quot;rbxassetid://123456789&quot; -- замени на нужный ID</code></p>
  <p id="lyic"><code>image.Size = UDim2.new(0, 100, 0, 100)</code></p>
  <p id="o7wM"><code>image.Position = UDim2.new(0.05, 0, 0.05, 0)</code></p>
  <p id="Qibg"><code>image.Parent = gui</code></p>
  <h3 id="iYhE">ImageButton — кликабельная картинка:</h3>
  <p id="lDDR"></p>
  <p id="6sBT"><code>local imageButton = Instance.new(&quot;ImageButton&quot;)</code></p>
  <p id="33MQ"><code>imageButton.Image = &quot;rbxassetid://987654321&quot;</code></p>
  <p id="x8Gz"><code>imageButton.Size = UDim2.new(0, 100, 0, 100)</code></p>
  <p id="97Hn"><code>imageButton.Position = UDim2.new(0.05, 0, 0.2, 0)</code></p>
  <p id="XFYt"><code>imageButton.Parent = gui</code></p>
  <p id="4BoK"><code>imageButton.MouseButton1Down:Connect(function()</code></p>
  <p id="Yp98"><code>               print(&quot;Изображение нажато!&quot;)</code></p>
  <p id="UPTH"><code>end)</code></p>
  <hr />
  <h2 id="zyVe">6.6 — Обновление интерфейса в реальном времени</h2>
  <p id="yWWE"></p>
  <p id="X2gL"><code>local score = 0</code></p>
  <p id="wk5n"><code>while true do</code></p>
  <p id="uHOX"><code>           wait(1)</code></p>
  <p id="NQBa"><code>           score += 1</code></p>
  <p id="iOym"><code>           label.Text = &quot;Очки: &quot; .. score</code></p>
  <p id="Jb8x"><code>end</code></p>
  <hr />
  <h2 id="04ln">6.7 — Проект: Счётчик нажатий</h2>
  <p id="YmhJ">Создадим кнопку, при нажатии на которую увеличивается счётчик.</p>
  <p id="B0jm"></p>
  <p id="LIvC"><code>local player = game.Players.LocalPlayer</code></p>
  <p id="zy8g"><code>local gui = Instance.new(&quot;ScreenGui&quot;)</code></p>
  <p id="jfL4"><code>gui.Parent = player.PlayerGui</code></p>
  <p id="CZUo"><code>local scoreLabel = Instance.new(&quot;TextLabel&quot;)</code></p>
  <p id="YtJU"><code>scoreLabel.Text = &quot;Счёт: 0&quot;</code></p>
  <p id="2LIQ"><code>scoreLabel.Size = UDim2.new(0, 200, 0, 50)</code></p>
  <p id="G5zM"><code>scoreLabel.Position = UDim2.new(0.5, -100, 0.1, 0)</code></p>
  <p id="JDOC"><code>scoreLabel.Parent = gui</code></p>
  <p id="WDQd"><code>local clickButton = Instance.new(&quot;TextButton&quot;)</code></p>
  <p id="GLuh"><code>clickButton.Text = &quot;Нажми!&quot;</code></p>
  <p id="4O5W"><code>clickButton.Size = UDim2.new(0, 150, 0, 50)</code></p>
  <p id="TINU"><code>clickButton.Position = UDim2.new(0.5, -75, 0.2, 0)</code></p>
  <p id="YGJA"><code>clickButton.Parent = gui</code></p>
  <p id="jg3s"><code>local score = 0</code></p>
  <p id="66lI"><code>clickButton.MouseButton1Down:Connect(function()</code></p>
  <p id="9z3P"><code>            score += 1</code></p>
  <p id="CAgH"><code>            scoreLabel.Text = &quot;Счёт: &quot; .. score</code></p>
  <p id="KZjI"><code>end)</code></p>
  <hr />
  <h2 id="8nop">6.8 — Советы и рекомендации</h2>
  <ul id="mOF7">
    <li id="udpA">Убедись, что GUI находится в <code>PlayerGui</code>, иначе он не будет отображаться.</li>
    <li id="YaiI">Используй <code>UDim2</code> для правильного позиционирования.</li>
    <li id="Ecwk">Не забывай удалять старые GUI перед созданием новых.</li>
    <li id="bP8T">Для сложных интерфейсов используй <code>Frame</code> как контейнер.</li>
    <li id="uwVp">Тестируй GUI на разных разрешениях экрана.</li>
  </ul>
  <hr />
  <h2 id="Augr">6.9 — Ключевые термины</h2>
  <p id="j0hA">Термин - Описание</p>
  <p id="LWr6">ScreenGui - Основной контейнер для GUI</p>
  <p id="ncHL">TextLabel - Текстовая надпись</p>
  <p id="FtGg">TextButton - Кликабельная кнопка с текстом</p>
  <p id="6qec">ImageLabel - Элемент для отображения изображения</p>
  <p id="1N7j">ImageButton - Кликабельная кнопка с изображением</p>
  <p id="Z6Bg">UDim2 - Размер и позиция элемента</p>
  <p id="gpE2">MouseButton1Down - Событие нажатия мыши/пальца</p>
  <p id="sElg"></p>
  <h1 id="0KVu">🔹 Глава 7: Работа с игроками и персонажами.</h1>
  <hr />
  <h2 id="R8zo">Введение</h2>
  <p id="Z1TZ">В этой главе ты узнаешь:</p>
  <ul id="5Ls7">
    <li id="x2Yu">Как получить доступ к текущему игроку.</li>
    <li id="3Upc">Как управлять персонажем: перемещение, анимация, здоровье.</li>
    <li id="jS2I">Как работать с инвентарём и оружием.</li>
    <li id="bO3j">Как создавать систему здоровья и уровней.</li>
    <li id="56Ts">Как взаимодействовать с другими игроками через чат и UI.</li>
  </ul>
  <hr />
  <h2 id="4fco">7.1 — Получение информации об игроке</h2>
  <p id="b5aA"></p>
  <p id="iU6D"><code>local player = game.Players.LocalPlayer -- Текущий игрок</code></p>
  <p id="LvbG"><code>print(player.Name) -- Имя игрока</code></p>
  <p id="JL0J"><code>print(player.UserId) -- Уникальный ID</code></p>
  <p id="mseE"><code>print(player.DisplayName) -- Отображаемое имя</code></p>
  <p id="poNZ"></p>
  <h3 id="lg0m">Свойства игрока:</h3>
  <p id="za8X"></p>
  <p id="k8SD">Свойство - Описание</p>
  <p id="HKM2"><code>Name</code> - Логин игрока</p>
  <p id="iIn3"><code>UserId</code> - Уникальный числовой ID</p>
  <p id="JNC6"><code>DisplayName</code> - Отображаемое имя</p>
  <p id="Zlkv"><code>Character</code> - Персонаж игрока (если загружен)</p>
  <p id="PWe7"><code>PlayerGui</code> - Интерфейс игрока</p>
  <p id="YJFi"><code>Team</code> - Команда игрока</p>
  <hr />
  <h2 id="m4c9">7.2 — Работа с персонажем</h2>
  <p id="JTPA"></p>
  <p id="jl0Z"><code>local character = player.Character or player.CharacterAdded:Wait()</code></p>
  <p id="HG37"><code>print(character.Name) -- Обычно &quot;Character&quot;</code></p>
  <h3 id="8pUf">Основные части персонажа:</h3>
  <ul id="Y9bg">
    <li id="wagL"><code>HumanoidRootPart</code> — корневая часть (обычно торс).</li>
    <li id="4Luy"><code>Head</code> — голова.</li>
    <li id="rVQd"><code>Torso</code> — туловище (устарело, но иногда используется).</li>
    <li id="in1j"><code>Humanoid</code> — компонент управления жизнью и движениями.</li>
  </ul>
  <h4 id="0d3J">Перемещение персонажа</h4>
  <p id="5kp9"></p>
  <p id="APBJ"><code>character.HumanoidRootPart.CFrame = CFrame.new(0, 10, 0)</code></p>
  <h4 id="v5aB">Поворот персонажа</h4>
  <p id="QWxO"></p>
  <p id="FjmB"><code>character.HumanoidRootPart.CFrame = CFrame.Angles(0, math.rad(90), 0)</code></p>
  <hr />
  <h2 id="c78k">7.3 — Система здоровья</h2>
  <p id="wjtP"></p>
  <p id="fGaz"><code>local humanoid = character:FindFirstChildOfClass(&quot;Humanoid&quot;)</code></p>
  <p id="P8Qg"><code>if humanoid then</code></p>
  <p id="PpGd"><code>            humanoid.HealthChanged:Connect(function(newHealth)</code></p>
  <p id="oxpb"><code>                        print(&quot;Здоровье: &quot; .. newHealth)</code></p>
  <p id="QTX4"><code>            end)</code></p>
  <p id="0h70"><code>end</code></p>
  <h4 id="fvkr">Установка максимального здоровья</h4>
  <p id="zz6b"></p>
  <p id="FaJS"><code>humanoid.MaxHealth = 200</code></p>
  <p id="FnlG"><code>humanoid.Health = 200</code></p>
  <h4 id="YXrj">Нанесение урона</h4>
  <p id="3ESf"></p>
  <p id="bFhr"><code>humanoid.Health -= 50</code></p>
  <hr />
  <h2 id="cM7L">7.4 — Инвентарь игрока</h2>
  <p id="iEVa">Инвентарь хранится в <code>Backpack</code>. Чтобы добавить предмет:</p>
  <p id="qlt2"></p>
  <p id="siLp"><code>local tool = Instance.new(&quot;Tool&quot;)</code></p>
  <p id="FM0K"><code>tool.Name = &quot;Меч&quot;</code></p>
  <p id="eAzd"><code>tool.RequiresHandle = false</code></p>
  <p id="g7lZ"><code>tool.TextureId = &quot;rbxassetid://123456789&quot; -- замени на нужный ID</code></p>
  <p id="6OcO"><code>tool.Parent = player.Backpack</code></p>
  <p id="P8wo">Когда игрок возьмёт предмет в руки, он появится в <code>StarterPlayer.StarterCharacter</code>.</p>
  <hr />
  <h2 id="lrKA">7.5 — Создание системы уровней</h2>
  <p id="PsGQ"></p>
  <p id="SCaY"><code>-- Добавляем лидерборд</code></p>
  <p id="k5ch"><code>local leaderstats = Instance.new(&quot;Folder&quot;)</code></p>
  <p id="AqzL"><code>leaderstats.Name = &quot;leaderstats&quot;</code></p>
  <p id="GuxN"><code>leaderstats.Parent = player</code></p>
  <p id="GqVg"><code>local level = Instance.new(&quot;IntValue&quot;)</code></p>
  <p id="H5FQ"><code>level.Name = &quot;Level&quot;</code></p>
  <p id="TGGA"><code>level.Value = 1</code></p>
  <p id="enPO"><code>level.Parent = leaderstats</code></p>
  <p id="gcGX"><code>local exp = Instance.new(&quot;IntValue&quot;)</code></p>
  <p id="oXdd"><code>exp.Name = &quot;Exp&quot;</code></p>
  <p id="LtsT"><code>exp.Value = 0</code></p>
  <p id="JFdI"><code>exp.Parent = leaderstats</code></p>
  <p id="X37X"><code>-- Функция для повышения уровня</code></p>
  <p id="VhLL"><code>function addExp(amount)</code></p>
  <p id="UCiJ"><code>          exp.Value += amount</code></p>
  <p id="zNxR"><code>          if exp.Value &gt;= 100 then</code></p>
  <p id="uquC"><code>                   exp.Value = 0</code></p>
  <p id="nEh8"><code>                   level.Value += 1</code></p>
  <p id="VKT2"><code>                   print(&quot;Уровень повышен до &quot; .. level.Value)</code></p>
  <p id="yV7f"><code>          end</code></p>
  <p id="UpLn"><code>end</code></p>
  <p id="WxxE"><code>-- Вызываем функцию</code></p>
  <p id="XeKI"><code>addExp(150)</code></p>
  <hr />
  <h2 id="tKar">7.6 — Проект: Мини-игра &quot;Бой с боссом&quot;</h2>
  <p id="cj1G">Создадим простого босса, который теряет здоровье при нажатии на него.</p>
  <h3 id="7KuC">Шаг 1: Создай Part для босса</h3>
  <p id="2gxs"></p>
  <p id="F7rb"><code>local boss = Instance.new(&quot;Part&quot;)</code></p>
  <p id="LenU"><code>boss.Name = &quot;Boss&quot;</code></p>
  <p id="R6sZ"><code>boss.Size = Vector3.new(5, 5, 5)</code></p>
  <p id="26bD"><code>boss.BrickColor = BrickColor.Red()</code></p>
  <p id="IYgJ"><code>boss.Anchored = true</code></p>
  <p id="5q2q"><code>boss.Position = Vector3.new(0, 5, 20)</code></p>
  <p id="VYva"><code>boss.Parent = workspace</code></p>
  <h3 id="1ZzF">Шаг 2: Добавь здоровье</h3>
  <p id="bqXf"></p>
  <p id="liiW"><code>local bossHealth = 100</code></p>
  <p id="tLaG"><code>boss.Touched:Connect(function(hit)</code></p>
  <p id="sIJ9"><code>           local character = hit.Parent</code></p>
  <p id="ZYNm"><code>           local humanoid = character:FindFirstChild(&quot;Humanoid&quot;)</code></p>
  <p id="lR5A"><code>           if humanoid then</code></p>
  <p id="zzji"><code>                    bossHealth -= 10</code></p>
  <p id="OdtF"><code>                    print(&quot;Здоровье босса: &quot; .. bossHealth)</code></p>
  <p id="Qmxz"><code>                    if bossHealth &lt;= 0 then</code></p>
  <p id="5jZY"><code>                              print(&quot;Босс побеждён!&quot;)</code></p>
  <p id="sQqa"><code>                              boss:Destroy()</code></p>
  <p id="4s89"><code>                    end</code></p>
  <p id="cgpG"><code>           end</code></p>
  <p id="s8ce"><code>end)</code></p>
  <hr />
  <h2 id="ulvq">7.7 — Советы и рекомендации</h2>
  <ul id="fLR1">
    <li id="FrQF">Используй <code>CharacterAdded</code> вместо <code>Character</code>, чтобы избежать ошибок.</li>
    <li id="nc4o">Проверяй наличие <code>Humanoid</code> перед его использованием.</li>
    <li id="gFJr">Не забывай очищать старые данные при повторном входе игрока.</li>
    <li id="JiJ0">Используй <code>leaderstats</code> для отображения статистики.</li>
    <li id="WQ7l">Тестируй взаимодействие с объектами через <code>Touched</code> и <code>MouseClick</code>.</li>
  </ul>
  <hr />
  <h2 id="r95a">7.8 — Ключевые термины</h2>
  <p id="hA2v">Термин - Описание</p>
  <p id="mnB4">LocalPlayer - Текущий игрок</p>
  <p id="3qkR">Character - Модель персонажа</p>
  <p id="jM1F">Humanoid - Управление здоровьем и движением</p>
  <p id="lavh">Backpack - Хранилище предметов игрока</p>
  <p id="EuOS">Leaderstats - Отображение рейтинга игрока</p>
  <p id="uGTz">CFrame - Положение и поворот объекта</p>
  <p id="nb5Q">Touched - Событие прикосновения объекта</p>
  <p id="fcq2"></p>
  <h1 id="ENPg">🔹 Глава 8: Анимация и физика персонажей.</h1>
  <hr />
  <h2 id="eIS1">Введение</h2>
  <p id="sD1B">В этой главе ты узнаешь:</p>
  <ul id="90Yz">
    <li id="kZr5">Как загружать и воспроизводить анимации.</li>
    <li id="Euh1">Как использовать <code>Animator</code> и <code>AnimationTrack</code>.</li>
    <li id="i0RZ">Как управлять движением персонажа с помощью <code>BodyMovers</code>.</li>
    <li id="y6Sm">Как создавать эффекты полёта, пружинности, телепортации.</li>
    <li id="i1Sn">Как работать с камерой и гравитацией.</li>
  </ul>
  <hr />
  <h2 id="Aw9z">8.1 — Основы анимации в Roblox</h2>
  <h3 id="nSSB">Что такое анимация?</h3>
  <p id="aznI">Анимация в Roblox — это заранее записанный набор движений персонажа. Она может быть:</p>
  <ul id="nZlJ">
    <li id="tmqf">Прыжок</li>
    <li id="XKMW">Бег</li>
    <li id="nQCu">Смерть</li>
    <li id="JUuL">Удар мечом</li>
    <li id="ZxtI">И многое другое</li>
  </ul>
  <h3 id="da5W">Как получить анимацию?</h3>
  <p id="9gbf">На <a href="https://www.roblox.com/library" target="_blank">https://www.roblox.com/library </a>можно найти готовые анимации. Каждая имеет свой ID, например: <code>rbxassetid://123456789</code>.</p>
  <hr />
  <h2 id="s9rp">8.2 — Загрузка и воспроизведение анимации</h2>
  <p id="Ac4t"></p>
  <p id="bof2"><code>local player = game.Players.LocalPlayer</code></p>
  <p id="VxUX"><code>local character = player.Character or player.CharacterAdded:Wait()</code></p>
  <p id="Rm02"><code>local animator = character:FindFirstChildOfClass(&quot;Animator&quot;)</code></p>
  <p id="VN92"><code>if animator then</code></p>
  <p id="GCc1"><code>          local animation = Instance.new(&quot;Animation&quot;)</code></p>
  <p id="SLoO"><code>          animation.AnimationId = &quot;rbxassetid://123456789&quot; -- замени на нужный ID</code></p>
  <p id="r329"><code>          local track = animator:LoadAnimation(animation)</code></p>
  <p id="3FBz"><code>          track:Play()</code></p>
  <p id="bNQX"><code>end</code></p>
  <hr />
  <h2 id="YWkn">8.3 — Управление анимацией</h2>
  <h3 id="Tk3f">Воспроизведение и остановка</h3>
  <p id="UfsN"></p>
  <p id="7uAV"><code>track:Play() -- воспроизвести</code></p>
  <p id="1YkJ"><code>track:Stop() -- остановить</code></p>
  <h3 id="k0dk">Изменение скорости</h3>
  <p id="EtDS"></p>
  <p id="E5Z5"><code>track:AdjustSpeed(2) -- удвоить скорость</code></p>
  <p id="gGjs"><code>track:AdjustSpeed(0.5) -- замедлить в 2 раза</code></p>
  <h3 id="e5OS">Повтор анимации</h3>
  <p id="VtpI"></p>
  <p id="L4jT"><code>track.Looped = true -- зациклить</code></p>
  <hr />
  <h2 id="PAky">8.4 — BodyMovers: управление физикой объектов</h2>
  <p id="PPib">BodyMovers — это компоненты, которые позволяют перемещать объекты с учётом физики.</p>
  <h3 id="7G1k">BodyPosition — перемещение в точку</h3>
  <p id="qrGY"></p>
  <p id="FPwP"><code>local part = workspace.Part</code></p>
  <p id="pTKh"><code>local bodyPos = Instance.new(&quot;BodyPosition&quot;)</code></p>
  <p id="xM6I"><code>bodyPos.Position = Vector3.new(0, 10, 0)</code></p>
  <p id="rvxv"><code>bodyPos.MaxForce = Vector3.new(4000, 4000, 4000)</code></p>
  <p id="wR9e"><code>bodyPos.Parent = part</code></p>
  <h3 id="HZSN">BodyGyro — поворот объекта</h3>
  <p id="uhZu"></p>
  <p id="pLSf"><code>local bodyGyro = Instance.new(&quot;BodyGyro&quot;)</code></p>
  <p id="9uFm"><code>bodyGyro.CFrame = CFrame.Angles(0, math.rad(90), 0)</code></p>
  <p id="hKJn"><code>bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)</code></p>
  <p id="Ggbe"><code>bodyGyro.Parent = part</code></p>
  <h3 id="SOop">BodyVelocity — постоянное движение</h3>
  <p id="pmnZ"></p>
  <p id="rLiH">local velocity = Instance.new(&quot;BodyVelocity&quot;)</p>
  <p id="b59r">velocity.Velocity = Vector3.new(0, 0, 10) -- движение вперёд</p>
  <p id="QyzD">velocity.MaxForce = Vector3.new(4000, 4000, 4000)</p>
  <p id="oDuo">velocity.Parent = part</p>
  <hr />
  <h2 id="2dk6">8.5 — Создание летающего объекта</h2>
  <p id="zvA1">Создадим простой летающий диск, который будет подниматься вверх.</p>
  <p id="loPy"></p>
  <p id="wRM6"><code>local disc = workspace.Disc</code></p>
  <p id="L74t"><code>while true do</code></p>
  <p id="yr5w"><code>          wait(0.1)</code></p>
  <p id="VWf1"><code>          disc.CFrame = disc.CFrame * CFrame.Angles(0, math.rad(10), 0)</code></p>
  <p id="VkKN"><code>          local bodyPos = Instance.new(&quot;BodyPosition&quot;)</code></p>
  <p id="ztwo"><code>          bodyPos.Position = disc.Position + Vector3.new(0, 0.5, 0)</code></p>
  <p id="fzrw"><code>          bodyPos.MaxForce = Vector3.new(4000, 4000, 4000)</code></p>
  <p id="K5lv"><code>          bodyPos.Parent = disc</code></p>
  <p id="JkXe"><code>          wait(1)</code></p>
  <p id="x5tH"><code>          bodyPos:Destroy()</code></p>
  <p id="ZbPO"><code>end</code></p>
  <hr />
  <h2 id="AGQ5">8.6 — Проект: Полёт персонажа</h2>
  <p id="334c">Добавим игроку способность летать при нажатии на кнопку.</p>
  <h3 id="4kwp">Шаг 1: Создай GUI кнопку</h3>
  <p id="uWgZ"> </p>
  <p id="PuBd"><code>local gui = Instance.new(&quot;ScreenGui&quot;)</code></p>
  <p id="dg81"><code>gui.Parent = game.Players.LocalPlayer.PlayerGui</code></p>
  <p id="cCbI"><code>local flyButton = Instance.new(&quot;TextButton&quot;)</code></p>
  <p id="0HlU"><code>flyButton.Text = &quot;Лететь&quot;</code></p>
  <p id="Mia7"><code>flyButton.Size = UDim2.new(0, 100, 0, 50)</code></p>
  <p id="nX8v"><code>flyButton.Position = UDim2.new(0.8, 0, 0.8, 0)</code></p>
  <p id="gEKa"><code>flyButton.Parent = gui</code></p>
  <h3 id="QjPQ">Шаг 2: Добавь функционал</h3>
  <p id="kgcw"></p>
  <p id="4I0x"><code>local flying = false</code></p>
  <p id="ex96"><code>local bodyGyro</code></p>
  <p id="6mTp"><code>local bodyVelocity</code></p>
  <p id="RHdJ"><code>flyButton.MouseButton1Down:Connect(function()</code></p>
  <p id="z59B"><code>          flying = not flying</code></p>
  <p id="EduQ"><code>          if flying then</code></p>
  <p id="C5i6"><code>                    local character = game.Players.LocalPlayer.Character</code></p>
  <p id="jv2t"><code>                    local root = character.HumanoidRootPart</code></p>
  <p id="gejk"><code>                    bodyGyro = Instance.new(&quot;BodyGyro&quot;)</code></p>
  <p id="bnjF"><code>                    bodyGyro.P = 1000</code></p>
  <p id="TjM9"><code>                    bodyGyro.D = 100</code></p>
  <p id="6SKl"><code>                    bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)</code></p>
  <p id="1GJv"><code>                    bodyGyro.Parent = root</code></p>
  <p id="lTXh"><code>                    bodyVelocity = Instance.new(&quot;BodyVelocity&quot;)</code></p>
  <p id="RkMe"><code>                    bodyVelocity.Velocity = Vector3.new(0, 5, 0)</code></p>
  <p id="N7gr"><code>                    bodyVelocity.MaxForce = Vector3.new(4000, 4000, 4000)</code></p>
  <p id="UJrw"><code>                    bodyVelocity.Parent = root</code></p>
  <p id="AUQ1"><code>          else</code></p>
  <p id="X6vm"><code>                    if bodyGyro then bodyGyro:Destroy() end</code></p>
  <p id="QVTN"><code>                    if bodyVelocity then bodyVelocity:Destroy() end</code></p>
  <p id="Dn3K"><code>          end</code></p>
  <p id="UK2I"><code>end)</code></p>
  <hr />
  <h2 id="C0cE">8.7 — Советы и рекомендации</h2>
  <ul id="Mq6R">
    <li id="PEQB">Не забывай удалять старые BodyMovers, чтобы избежать багов.</li>
    <li id="X0PN">Тестируй анимации перед использованием.</li>
    <li id="37ys">Используй <code>CFrame</code> для плавного движения.</li>
    <li id="UnVf">Для сложных механик используй <code>RunService</code> и <code>Heartbeat</code>.</li>
    <li id="IshT">Сохраняй ссылки на треки и траектории, чтобы их можно было остановить.</li>
  </ul>
  <hr />
  <h2 id="Ckv1">8.8 — Ключевые термины</h2>
  <p id="M8Oc">Термин - Описание</p>
  <p id="LpVc">Animation - Анимация персонажа</p>
  <p id="rsVA">Animator - Компонент для управления анимациями</p>
  <p id="GYMc">BodyPosition - Перемещает объект в заданную точку</p>
  <p id="ybc7">BodyGyro - Поворачивает объект</p>
  <p id="KtgY">BodyVelocity - Заставляет объект двигаться постоянно</p>
  <p id="Cirj">CFrame - Позиция и поворот объекта</p>
  <p id="TPHL">Loop - Повтор анимации</p>
  <p id="Wy5t">MaxForce / MaxTorque - Максимальная сила воздействия</p>
  <p id="E9nH"></p>
  <h1 id="tlUi">🔹 Глава 9: Сохранение данных с DataStore.</h1>
  <hr />
  <h2 id="ZVGD">Введение</h2>
  <p id="zRWK">В этой главе ты узнаешь:</p>
  <ul id="OrZx">
    <li id="PXIP">Как сохранять данные игрока между сессиями.</li>
    <li id="uKyp">Как использовать <code>DataStoreService</code> и работать с хранилищами.</li>
    <li id="6Vlw">Как сохранять таблицы, числа, строки и сложные структуры.</li>
    <li id="wfMX">Как обрабатывать ошибки при работе с данными.</li>
    <li id="ecYF">Как создать полноценную систему сохранения прогресса: уровень, монеты, инвентарь и т.д.</li>
  </ul>
  <hr />
  <h2 id="IenT">9.1 — Что такое DataStore?</h2>
  <p id="Ranp"><code>DataStore</code> — это система хранения данных в Roblox, которая позволяет сохранять информацию о игроке даже после выхода из игры.</p>
  <h3 id="N23y">Основные понятия:</h3>
  <p id="VcYF">Термин - Описание</p>
  <p id="N5yy">DataStoreService - Сервис для работы с хранилищами</p>
  <p id="V3fT">DataStore - Конкретное хранилище (например, &quot;PlayerStats&quot;)</p>
  <p id="IYAG">Key - Уникальный идентификатор записи (например, ID игрока)</p>
  <p id="9Fjh">SetAsync / GetAsync - Методы для сохранения и получения данных</p>
  <hr />
  <h2 id="3cFS">9.2 — Подключение к DataStore</h2>
  <p id="ulJf"></p>
  <p id="gFbM"><code>local ds = game:GetService(&quot;DataStoreService&quot;)</code></p>
  <p id="YrIj"><code>local playerDataStore = ds:GetDataStore(&quot;PlayerStats&quot;)</code></p>
  <hr />
  <h2 id="qIjR">9.3 — Сохранение данных</h2>
  <p id="NHa9"></p>
  <p id="DrzI"><code>-- Сохраняем данные игрока</code></p>
  <p id="1Iuq"><code>playerDataStore:SetAsync(&quot;player_123&quot;, {</code></p>
  <p id="vklO"><code>coins = 100,</code></p>
  <p id="BCfY"><code>    level = 1,</code></p>
  <p id="QA4l"><code>    inventory = {&quot;Меч&quot;, &quot;Щит&quot;}</code></p>
  <p id="dDTn"><code>})</code></p>
  <hr />
  <h2 id="pp4u">9.4 — Получение данных</h2>
  <p id="CNKL"></p>
  <p id="zFlz"><code>local data = playerDataStore:GetAsync(&quot;player_123&quot;)</code></p>
  <p id="moEm"><code>if data then</code></p>
  <p id="HO1X"><code>    print(&quot;Уровень: &quot; .. data.level)</code></p>
  <p id="iGKM"><code>    print(&quot;Монеты: &quot; .. data.coins)</code></p>
  <p id="ZL5i"><code>else</code></p>
  <p id="OiLu"><code>    print(&quot;Нет сохранённых данных.&quot;)</code></p>
  <p id="aAxQ"><code>end</code></p>
  <hr />
  <h2 id="QwVb">9.5 — Обработка ошибок</h2>
  <p id="6ooT">Работа с <code>DataStore</code> может вызвать ошибки (например, нет подключения). Используй <code>pcall()</code> или <code>xpcall()</code>:</p>
  <p id="UujB"></p>
  <p id="EO02"><code>local success, result = pcall(function()</code></p>
  <p id="1kZf"><code>    return playerDataStore:GetAsync(&quot;player_123&quot;)</code></p>
  <p id="05QE"><code>end)</code></p>
  <p id="cgjG"><code>if success then</code></p>
  <p id="7LU1"><code>    print(result)</code></p>
  <p id="uXf4"><code>else</code></p>
  <p id="l55V"><code>    warn(&quot;Ошибка при получении данных: &quot; .. result)</code></p>
  <p id="cp0J"><code>end</code></p>
  <hr />
  <h2 id="2Xz8">9.6 — Сохранение при входе и выходе</h2>
  <p id="GHkx"></p>
  <p id="TJlS"><code>game.Players.PlayerAdded:Connect(function(player)</code></p>
  <p id="snQd"><code>    local userId = &quot;player_&quot; .. player.UserId</code></p>
  <p id="MmPj"><code>    local data = playerDataStore:GetAsync(userId)</code></p>
  <p id="5RKk"><code>    if not data then</code></p>
  <p id="JePp"><code>        data = {coins = 0, level = 1}</code></p>
  <p id="m192"><code>    end</code></p>
  <p id="pX1U"><code>    -- Создаём лидерборд</code></p>
  <p id="rKtn"><code>    local leaderstats = Instance.new(&quot;Folder&quot;)</code></p>
  <p id="Uun9"><code>    leaderstats.Name = &quot;leaderstats&quot;</code></p>
  <p id="Xd3Y"><code>    leaderstats.Parent = player</code></p>
  <p id="1Sif"><code>    local coins = Instance.new(&quot;IntValue&quot;)</code></p>
  <p id="4CK6"><code>    coins.Name = &quot;Coins&quot;</code></p>
  <p id="Wwqb"><code>    coins.Value = data.coins</code></p>
  <p id="oanb"><code>    coins.Parent = leaderstats</code></p>
  <p id="Dz8P"><code>    local level = Instance.new(&quot;IntValue&quot;)</code></p>
  <p id="tdo9"><code>    level.Name = &quot;Level&quot;</code></p>
  <p id="tIes"><code>    level.Value = data.level</code></p>
  <p id="zidF"><code>    level.Parent = leaderstats</code></p>
  <p id="ffDZ"><code>end)</code></p>
  <p id="Tvv6"><code>game.Players.PlayerRemoving:Connect(function(player)</code></p>
  <p id="Mryt"><code>    local userId = &quot;player_&quot; .. player.UserId</code></p>
  <p id="haNz"><code>    local leaderstats = player:FindFirstChild(&quot;leaderstats&quot;)</code></p>
  <p id="Tuxj"><code>    if leaderstats then</code></p>
  <p id="NTl5"><code>        local coins = leaderstats:FindFirstChild(&quot;Coins&quot;)</code></p>
  <p id="R6Ti"><code>        local level = leaderstats:FindFirstChild(&quot;Level&quot;)</code></p>
  <p id="GD1a"><code>        if coins and level then</code></p>
  <p id="dDw9"><code>            playerDataStore:SetAsync(userId, {</code></p>
  <p id="Dz7c"><code>                coins = coins.Value,</code></p>
  <p id="Lc2E"><code>                level = level.Value</code></p>
  <p id="EtYZ"><code>            })</code></p>
  <p id="9LEf"><code>        end</code></p>
  <p id="WfpY"><code>    end</code></p>
  <p id="Mzc1"><code>end)</code></p>
  <hr />
  <h2 id="d8iC">9.7 — Проект: Система магазина и покупок</h2>
  <p id="apmH">Создадим простой магазин, где игрок может купить предмет за монеты.</p>
  <h3 id="mCoU">Шаг 1: Добавь кнопку в GUI</h3>
  <p id="wM8i"></p>
  <p id="3cr1"><code>local gui = Instance.new(&quot;ScreenGui&quot;)</code></p>
  <p id="pHn9"><code>gui.Parent = game.Players.LocalPlayer.PlayerGui</code></p>
  <p id="SkTm"><code>local buyButton = Instance.new(&quot;TextButton&quot;)</code></p>
  <p id="bq33"><code>buyButton.Text = &quot;Купить меч&quot;</code></p>
  <p id="ounF"><code>buyButton.Size = UDim2.new(0, 150, 0, 50)</code></p>
  <p id="BS6H"><code>buyButton.Position = UDim2.new(0.5, -75, 0.2, 0)</code></p>
  <p id="B4oV"><code>buyButton.Parent = gui</code></p>
  <h3 id="B9mV">Шаг 2: Реализуй логику покупки</h3>
  <p id="H3F6"></p>
  <p id="adxU"><code>buyButton.MouseButton1Down:Connect(function()</code></p>
  <p id="FbHE"><code>    local player = game.Players.LocalPlayer</code></p>
  <p id="NJa2"><code>    local leaderstats = player:FindFirstChild(&quot;leaderstats&quot;)</code></p>
  <p id="fXSw"><code>    local coins = leaderstats and leaderstats:FindFirstChild(&quot;Coins&quot;)</code></p>
  <p id="tKM9"><code>    if coins and coins.Value &gt;= 50 then</code></p>
  <p id="FMsz"><code>        coins.Value -= 50</code></p>
  <p id="x6Jy"><code>        print(&quot;Вы купили меч!&quot;)</code></p>
  <p id="MmwQ"><code>        local tool = Instance.new(&quot;Tool&quot;)</code></p>
  <p id="hIrI"><code>        tool.Name = &quot;Меч&quot;</code></p>
  <p id="mNmq"><code>        tool.RequiresHandle = false</code></p>
  <p id="whos"><code>        tool.TextureId = &quot;rbxassetid://123456789&quot;</code></p>
  <p id="9IP8"><code>        tool.Parent = player.Backpack</code></p>
  <p id="V1rp"><code>    else</code></p>
  <p id="6Pf9"><code>        print(&quot;Недостаточно монет!&quot;)</code></p>
  <p id="LoIz"><code>    end</code></p>
  <p id="xaf0"><code>end)</code></p>
  <hr />
  <h2 id="K99b">9.8 — Советы и рекомендации</h2>
  <ul id="lCs4">
    <li id="GYYh">Не сохраняй слишком большие объекты в DataStore.</li>
    <li id="v39m">Используй уникальные ключи для каждого игрока.</li>
    <li id="4FYQ">Добавляй обработку ошибок, особенно при публикации.</li>
    <li id="O76q">Проверяй наличие <code>leaderstats</code> перед изменением.</li>
    <li id="PTHw">Используй отдельные хранилища для разных типов данных.</li>
  </ul>
  <hr />
  <h2 id="G8hu">9.9 — Ключевые термины</h2>
  <p id="DZvL">Термин - Описание</p>
  <p id="9rTm">DataStoreService - Сервис для работы с хранилищами</p>
  <p id="BjV1">DataStore - Хранилище с данными</p>
  <p id="t1MT">SetAsync - Сохраняет данные по ключу</p>
  <p id="ShiE">GetAsync - Получает данные по ключу</p>
  <p id="keql">pcall - Безопасный вызов функции</p>
  <p id="6BKs">Leaderstats - Отображение рейтинга игрока</p>
  <p id="zr4P">Inventory - Инвентарь игрока</p>
  <p id="MjUy"></p>
  <h1 id="ZckZ">🔹 Глава 10: Клиент-серверное взаимодействие.</h1>
  <hr />
  <h2 id="qAU7">Введение</h2>
  <p id="HBwY">В этой главе ты узнаешь:</p>
  <ul id="pfmF">
    <li id="xmWI">Что такое клиент и сервер в Roblox.</li>
    <li id="aMfZ">Как использовать <code>RemoteEvent</code> и <code>RemoteFunction</code>.</li>
    <li id="eFsV">Как безопасно передавать данные между клиентом и сервером.</li>
    <li id="5yKB">Как создавать команды, меню, чат и другие интерактивные элементы.</li>
    <li id="JrHb">Как избежать распространённых ошибок безопасности.</li>
  </ul>
  <hr />
  <h2 id="CV7M">10.1 — Архитектура клиент-сервер в Roblox</h2>
  <p id="rHe0">Roblox использует клиент-серверную архитектуру:</p>
  <p id="uNZd">Сторона - Описание</p>
  <p id="JCcM">Сервер - Обрабатывает логику игры, данные, события.</p>
  <p id="BOww">Клиент - Отображает графику, обрабатывает ввод игрока.</p>
  <p id="ok31"></p>
  <h3 id="AUoc">Почему важно разделять логику?</h3>
  <ul id="DEGe">
    <li id="wfZR">Безопасность: игрок не должен управлять важными данными напрямую.</li>
    <li id="EP6f">Производительность: тяжёлые вычисления лучше выполнять на сервере.</li>
    <li id="67Wi">Централизация: все игроки видят одни и те же данные.</li>
  </ul>
  <hr />
  <h2 id="26r2">10.2 — RemoteEvent: передача событий от клиента к серверу</h2>
  <p id="tHVF"><code>RemoteEvent</code> используется для отправки информации от клиента к серверу (например, нажатие кнопки).</p>
  <h3 id="u2fS">На сервере:</h3>
  <p id="6Zwf"></p>
  <p id="Z26C"><code>-- ServerScriptService</code></p>
  <p id="5NPx"><code>local remote = Instance.new(&quot;RemoteEvent&quot;)</code></p>
  <p id="hnm9"><code>remote.Name = &quot;PlayerJumped&quot;</code></p>
  <p id="wooH"><code>remote.Parent = game.ReplicatedStorage</code></p>
  <p id="tojq"><code>remote.OnServerEvent:Connect(function(player)</code></p>
  <p id="Az3S"><code>    print(player.Name .. &quot; прыгнул!&quot;)</code></p>
  <p id="5wCt"><code>end)</code></p>
  <h3 id="o2jd">На клиенте (LocalScript):</h3>
  <p id="JUpn"></p>
  <p id="4jNR"><code>-- StarterPlayerScripts</code></p>
  <p id="Sd31"><code>local remote = game.ReplicatedStorage.PlayerJumped</code></p>
  <p id="WLGk"><code>game.Players.LocalPlayer.Character.Humanoid.Jumped:Connect(function()</code></p>
  <p id="wjx4"><code>    remote:FireServer()</code></p>
  <p id="gaca"><code>end)</code></p>
  <hr />
  <h2 id="H94D">10.3 — RemoteFunction: запрос-ответ между клиентом и сервером</h2>
  <p id="Kllu"><code>RemoteFunction</code> позволяет запрашивать данные с сервера и получать ответ.</p>
  <h3 id="3mXi">На сервере:</h3>
  <p id="x7js"></p>
  <p id="UaMf"><code>-- ServerScriptService</code></p>
  <p id="Rd4h"><code>local remoteFunc = Instance.new(&quot;RemoteFunction&quot;)</code></p>
  <p id="0Pjx"><code>remoteFunc.Name = &quot;GetData&quot;</code></p>
  <p id="5RHG"><code>remoteFunc.Parent = game.ReplicatedStorage</code></p>
  <p id="XtBg"><code>remoteFunc.OnServerInvoke = function(player)</code></p>
  <p id="v5Ce"><code>    return {coins = 100, level = 1}</code></p>
  <p id="wym8"><code>end</code></p>
  <h3 id="UHij">На клиенте:</h3>
  <p id="aCxG"></p>
  <p id="F4Ed"><code>-- LocalScript</code></p>
  <p id="Z9e7"><code>local data = game.ReplicatedStorage.GetData:InvokeServer()</code></p>
  <p id="n8hW"><code>print(data.level)</code></p>
  <hr />
  <h2 id="LmSG">10.4 — Использование ReplicatedStorage</h2>
  <p id="kiju"><code>ReplicatedStorage</code> — это папка, которая доступна как на сервере, так и на клиенте. Именно здесь следует хранить <code>RemoteEvent</code> и <code>RemoteFunction</code>.</p>
  <h3 id="Ji1H">Пример структуры:</h3>
  <p id="WYAx"></p>
  <p id="wfIV"><code>ReplicatedStorage</code></p>
  <p id="s6dM"><code>│</code></p>
  <p id="0eqm"><code>├── RemoteEvents</code></p>
  <p id="cmhE"><code>│ └── PlayerJumped</code></p>
  <p id="uNPA"><code>│</code></p>
  <p id="Dkd5"><code>└── RemoteFunctions</code></p>
  <p id="nwAB"><code>└── GetData</code></p>
  <hr />
  <h2 id="ODMg">10.5 — Создание системы команд</h2>
  <p id="hQ6g">Создадим простую систему команд, где игрок может ввести <code>/fly on</code> или <code>/fly off</code>, чтобы активировать полёт.</p>
  <h3 id="wgom">Шаг 1: Добавь скрипт на сервере</h3>
  <p id="CJWC"></p>
  <p id="pYIh"><code>-- ServerScriptService<br />local commands = {}</code></p>
  <p id="Zzpw"><code>function commands.fly(player, args)<br />    local enabled = args[1] == &quot;on&quot;<br />    local character = player.Character<br />    if not character then return end</code></p>
  <p id="3ZDa"><code>    local root = character:FindFirstChild(&quot;HumanoidRootPart&quot;)<br />    if not root then return end</code></p>
  <p id="xPp3"><code>    local bodyGyro = root:FindFirstChild(&quot;FlyGyro&quot;)<br />    if enabled and not bodyGyro then<br />        bodyGyro = Instance.new(&quot;BodyGyro&quot;)<br />        bodyGyro.P = 1000<br />        bodyGyro.D = 100<br />        bodyGyro.MaxTorque = Vector3.new(4000, 4000, 4000)<br />        bodyGyro.Parent = root<br />    elseif not enabled and bodyGyro then<br />        bodyGyro:Destroy()<br />    end<br />end</code></p>
  <p id="XmkT"><code>— Подключаем обработчик команд<br />game.Players.PlayerAdded:Connect(function(player)<br />    player.Chatted:Connect(function(message)<br />        local prefix = &quot;/&quot;<br />        if message:sub(1, 1) == prefix then<br />            local cmd = message:sub(2):split(&quot; &quot;)<br />            local commandName = cmd[1]<br />            if commands[commandName] then<br />                table.remove(cmd, 1)<br />                commands[commandName](player, cmd)<br />            end<br />        end<br />    end)<br />end)</code></p>
  <hr />
  <h2 id="z4WN">10.6 — Советы по безопасности</h2>
  <ul id="ZlxY">
    <li id="NBtj">Не доверяй данным от клиента — всегда проверяй их на сервере.</li>
    <li id="V3G7">Используй <code>RemoteEvent</code> только для безопасных действий.</li>
    <li id="XEE0">Избегай выполнения важных операций на клиенте.</li>
    <li id="95WB">Проверяй, является ли игрок владельцем объекта.</li>
    <li id="Y21C">Используй <code>IsA()</code> для проверки типа объекта.</li>
  </ul>
  <hr />
  <h2 id="kksb">10.7 — Проект: Чат с командами</h2>
  <p id="2r3x">Добавим в игру возможность вводить команды через чат.</p>
  <h3 id="gktc">Шаг 1: Обработка сообщений</h3>
  <p id="vTwe"></p>
  <p id="BwvH"><code>-- ServerScriptService<br />game.Players.PlayerAdded:Connect(function(player)<br />    player.Chatted:Connect(function(message)<br />        if message:sub(1, 1) == &quot;/&quot; then<br />            local args = string.split(message:sub(2), &quot; &quot;)<br />            local command = args[1]</code></p>
  <p id="myMb"><code>            if command == &quot;heal&quot; then<br />                local targetName = args[2]<br />                local amount = tonumber(args[3])</code></p>
  <p id="m3ot"><code>                if targetName and amount then<br />                    local target = game.Players:FindFirstChild(targetName)<br />                    if target then<br />                        local humanoid = target.Character and target.Character:FindFirstChild(&quot;Humanoid&quot;)<br />                        if humanoid then<br />                            humanoid.Health += amount<br />                            print(player.Name .. &quot; вылечил &quot; .. target.Name .. &quot; на &quot; .. amount)<br />                        end<br />                    end<br />                end<br />            end<br />        end<br />    end)<br />end)</code></p>
  <p id="j8RA"></p>
  <h2 id="CEFa">10.8 — Ключевые термины</h2>
  <p id="LG0d">Термин - Описание</p>
  <p id="eFtQ">RemoteEvent - Передача данных от клиента к серверу</p>
  <p id="9ZzV">RemoteFunction - Запрос-ответ между клиентом и сервером</p>
  <p id="zFhP">ReplicatedStorage - Хранилище объектов, доступных всем сторонам</p>
  <p id="hvyW">Client - Сторона, связанная с игроком</p>
  <p id="FMZu">Server - Центральная часть игры, обрабатывающая логику</p>
  <p id="wqJm">FireServer - Вызов события на сервере</p>
  <p id="w9Ju">InvokeServer - Вызов функции на сервере с ожиданием результата</p>
  <p id="V3Pv"></p>
  <h1 id="6Naz">🔹 Глава 11: Модульные скрипты и библиотеки.</h1>
  <hr />
  <h2 id="jdEu">Введение</h2>
  <p id="93Hi">В этой главе ты узнаешь:</p>
  <ul id="zme8">
    <li id="8Ig1">Как создавать модульные скрипты (ModuleScript).</li>
    <li id="jAK8">Как использовать <code>require()</code> для подключения библиотек.</li>
    <li id="CcD8">Как упорядочивать код в больших проектах.</li>
    <li id="dMXm">Как создавать переиспользуемые функции для GUI, инвентаря, событий и т.д.</li>
    <li id="xdez">Как работать с таблицами как с классами.</li>
  </ul>
  <hr />
  <h2 id="6hXk">11.1 — Что такое ModuleScript?</h2>
  <p id="MSCB"><code>ModuleScript</code> — это специальный тип скрипта, который возвращает значение (обычно таблицу), которое можно использовать в других скриптах через <code>require()</code>.</p>
  <h3 id="fo1b">Преимущества:</h3>
  <ul id="2X6x">
    <li id="YbFj">Повторное использование кода.</li>
    <li id="cbNN">Удобство управления большими проектами.</li>
    <li id="3CMP">Легче читать и поддерживать.</li>
    <li id="xtcM">Возможность создания библиотек.</li>
  </ul>
  <hr />
  <h2 id="4HxH">11.2 — Создание простого ModuleScript</h2>
  <h3 id="8jnn">Шаг 1: Создай ModuleScript в ReplicatedStorage</h3>
  <p id="368b"><code>-- Shared/Utils.lua<br />local module = {}</code></p>
  <p id="KARz"><code>function module.formatCoins(coins)<br />    return string.format(&quot;%d монет&quot;, coins)<br />end</code></p>
  <p id="yIBd"><code>function module.addCoins(player, amount)<br />    local leaderstats = player:FindFirstChild(&quot;leaderstats&quot;)<br />    if leaderstats then<br />        local coins = leaderstats:FindFirstChild(&quot;Coins&quot;)<br />        if coins then<br />            coins.Value += amount<br />        end<br />    end<br />end</code></p>
  <p id="efb7"><code>return module</code></p>
  <hr />
  <h2 id="a7st">11.3 — Использование ModuleScript</h2>
  <p id="6oob">Теперь можем использовать его в любом другом скрипте:</p>
  <p id="Utfh"><code>-- ServerScriptService<br />local utils = require(game.ReplicatedStorage.Utils)</code></p>
  <p id="BoAS"><code>game.Players.PlayerAdded:Connect(function(player)<br />    utils.addCoins(player, 50)<br />end)</code></p>
  <hr />
  <h2 id="BGiY">11.4 — Структура проекта с модулями</h2>
  <p id="vBkb">Рекомендуемая структура:</p>
  <p id="GZvn"></p>
  <p id="QLVV"><code>ReplicatedStorage</code></p>
  <p id="GWmU"><code>│</code></p>
  <p id="H1L2"><code>├── Modules</code></p>
  <p id="Jlwo"><code>│ ├── Utils.lua</code></p>
  <p id="1WGb"><code>│ ├── Inventory.lua</code></p>
  <p id="3mBo"><code>│ └── Levels.lua</code></p>
  <p id="lOJ6"><code>│</code></p>
  <p id="xXXN"><code>└── RemoteEvents</code></p>
  <p id="aHz8"><code>└── PlayerJumped</code></p>
  <hr />
  <h2 id="lkl2">11.5 — Работа с таблицами как с классами</h2>
  <p id="63ya">Можно имитировать ООП с помощью таблиц и функций:</p>
  <p id="x3SH"><code>-- Shared/PlayerData.lua<br />local PlayerData = {}<br />PlayerData.__index = PlayerData</code></p>
  <p id="IQyo"><code>function PlayerData.new(player)<br />    local self = setmetatable({}, PlayerData)<br />    self.player = player<br />    self.coins = 0<br />    self.level = 1<br />    return self<br />end</code></p>
  <p id="wz3n"><code>function PlayerData:addCoins(amount)<br />    self.coins += amount<br />    print(self.player.Name .. &quot; получил &quot; .. amount .. &quot; монет&quot;)<br />end</code></p>
  <p id="L1FM"><code>return PlayerData</code></p>
  <p id="zcLK">Использование:</p>
  <p id="Qieu"><code>-- ServerScriptService<br />local PlayerData = require(game.ReplicatedStorage.PlayerData)</code></p>
  <p id="Tkrp"><code>game.Players.PlayerAdded:Connect(function(player)<br />    local data = PlayerData.new(player)<br />    data:addCoins(100)<br />end)</code></p>
  <hr />
  <h2 id="z72u">11.6 — Проект: Библиотека для GUI</h2>
  <p id="aSS3">Создадим простую библиотеку для создания кнопок.</p>
  <h3 id="X7LT">Шаг 1: Создай ModuleScript</h3>
  <p id="DRT8"></p>
  <p id="wYMl"><code>-- Shared/GUIUtils.lua<br />local guiUtils = {}</code></p>
  <p id="JtTu"><code>function guiUtils.createButton(parent, text, size, position, callback)<br />    local button = Instance.new(&quot;TextButton&quot;)<br />    button.Text = text<br />    button.Size = size<br />    button.Position = position<br />    button.BackgroundColor3 = Color3.fromRGB(100, 200, 255)<br />    button.Parent = parent</code></p>
  <p id="Pbe5"><code>    button.MouseButton1Down:Connect(function()<br />        callback()<br />    end)</code></p>
  <p id="EHji"><code>    return button<br />end</code></p>
  <p id="OHVO"><code>return guiUtils</code></p>
  <h3 id="xLDf">Шаг 2: Используй библиотеку</h3>
  <p id="JP1u"></p>
  <p id="RyZu"><code>-- LocalScript<br />local guiUtils = require(game.ReplicatedStorage.GUIUtils)</code></p>
  <p id="SIAa"><code>local player = game.Players.LocalPlayer<br />local gui = Instance.new(&quot;ScreenGui&quot;)<br />gui.Parent = player.PlayerGui</code></p>
  <p id="bqAQ"><code>guiUtils.createButton(gui, &quot;Нажми меня&quot;, UDim2.new(0, 150, 0, 50), UDim2.new(0.5, -75, 0.2, 0), function()<br />    print(&quot;Кнопка нажата!&quot;)<br />end)</code></p>
  <hr />
  <h2 id="tQag">11.7 — Советы по использованию модулей</h2>
  <ul id="cW9t">
    <li id="9NKQ">Храни все общие функции в <code>ReplicatedStorage/Modules</code>.</li>
    <li id="Ohtj">Давай понятные имена своим модулям.</li>
    <li id="c7bo">Тестируй каждый модуль отдельно.</li>
    <li id="V42F">Не используй глобальные переменные внутри модулей.</li>
    <li id="RQYn">Обрабатывай ошибки при загрузке модулей.</li>
  </ul>
  <hr />
  <h2 id="zw6c">11.8 — Ключевые термины</h2>
  <p id="ZkXD">Термин - Описание</p>
  <p id="gPwm">ModuleScript - Скрипт, возвращающий значение</p>
  <p id="icfK">require() - Загружает ModuleScript</p>
  <p id="lbcb">__index - Метатаблица для доступа к методам</p>
  <p id="wfp3">setmetatable - Привязывает метатаблицу к таблице</p>
  <p id="xXZO">namespace - Группировка связанных функций</p>
  <p id="Ch0t">OOP - Объектно-ориентированное программирование (через таблицы)</p>
  <p id="SVHR">reusable code - Код, который можно использовать повторно</p>
  <p id="Q3F2"></p>
  <h1 id="uZHD">🔹 Глава 12: Работа с файлами и внешними данными.</h1>
  <hr />
  <h2 id="jhgz">Введение</h2>
  <p id="VQhc">В этой главе ты узнаешь:</p>
  <ul id="cQYG">
    <li id="qMeS">Как сохранять данные локально на компьютере (в ограниченном режиме).</li>
    <li id="wqtm">Как использовать <code>HttpService</code> для работы с JSON и другими форматами.</li>
    <li id="C3Tg">Как читать и записывать данные из файла (в тестовой среде).</li>
    <li id="qJ3q">Как использовать внешние данные для создания динамических игр.</li>
    <li id="Bp3D">Как обрабатывать ошибки при работе с внешними ресурсами.</li>
  </ul>
  <hr />
  <h2 id="oAvC">12.1 — Возможности и ограничения работы с файлами в Roblox</h2>
  <p id="mME5">Roblox <strong>не позволяет напрямую читать/писать файлы на жёсткий диск </strong>пользователя из соображений безопасности. Однако есть способы:</p>
  <ul id="anQb">
    <li id="3lIx">Использование <code>HttpService</code> для сериализации данных.</li>
    <li id="jI5E">Сохранение данных через <code>DataStore</code>.</li>
    <li id="bs85">Локальное хранение данных в песочнице (только для тестирования).</li>
  </ul>
  <hr />
  <h2 id="kxXb">12.2 — HttpService: работа с JSON</h2>
  <p id="hs8c"><code>HttpService</code> — это мощный инструмент для преобразования Lua-таблиц в JSON-строки и обратно.</p>
  <h3 id="in8D">Включение HttpService:</h3>
  <ol id="4afV">
    <li id="T6ab">Открой Roblox Studio.</li>
    <li id="NqZ3">Перейди в <strong>File → Settings → Security </strong>.</li>
    <li id="jpmo">Включи <strong>Http Enabled </strong>.</li>
  </ol>
  <h3 id="owdm">Сериализация данных:</h3>
  <p id="gF5b"><code>local http = game:GetService(&quot;HttpService&quot;)</code></p>
  <p id="BrRK"><code>local data = {<br />    name = &quot;Алекс&quot;,<br />    level = 5,<br />    inventory = {&quot;Меч&quot;, &quot;Щит&quot;}<br />}</code></p>
  <p id="h23P"><code>local jsonData = http:JSONEncode(data)<br />print(jsonData) — {&quot;name&quot;:&quot;Алекс&quot;,&quot;level&quot;:5,&quot;inventory&quot;:[&quot;Меч&quot;,&quot;Щит&quot;]}</code></p>
  <h3 id="IXZ2">Десериализация данных:</h3>
  <p id="YxL7"></p>
  <p id="x6NV"><code>local decoded = http:JSONDecode(jsonData)</code></p>
  <p id="gFeO"><code>print(decoded.name) -- Алекс</code></p>
  <hr />
  <h2 id="CmK6">12.3 — Локальное хранение данных (тестирование)</h2>
  <p id="uVKT">Хотя Roblox не поддерживает прямую работу с файлами, можно эмулировать чтение/запись с помощью <code>setclipboard()</code> и <code>print()</code>.</p>
  <h3 id="jKBb">Эмуляция записи:</h3>
  <p id="rCMD"></p>
  <p id="U7sC"><code>setclipboard(jsonData) -- копирует данные в буфер обмена</code></p>
  <p id="MwRi"><code>print(&quot;Сохранено в буфер обмена:&quot;)</code></p>
  <p id="mZw7"><code>print(jsonData)</code></p>
  <p id="DUNC"></p>
  <h3 id="vfKm">Эмуляция чтения:</h3>
  <p id="oqwH"></p>
  <p id="GMvK"><code>-- Представим, что игрок вставил данные в консоль</code></p>
  <p id="MnPC"><code>local pastedData = &#x27;{&quot;name&quot;:&quot;Алекс&quot;,&quot;level&quot;:5,&quot;inventory&quot;:[&quot;Меч&quot;,&quot;Щит&quot;]}&#x27;</code></p>
  <p id="OY9m"><code>local loaded = http:JSONDecode(pastedData)</code></p>
  <p id="5amu"><code>print(&quot;Имя: &quot; .. loaded.name)</code></p>
  <hr />
  <h2 id="C1pD">12.4 — Подключение к внешним API (при наличии разрешения)</h2>
  <p id="R8Ai">Roblox позволяет делать HTTP-запросы к внешним серверам через <code>http:request()</code>. Это может быть полезно для:</p>
  <ul id="JgG0">
    <li id="eCT0">Получения погоды</li>
    <li id="jN0h">Проверки статуса серверов</li>
    <li id="Kg6n">Загрузки данных из сторонних сервисов</li>
  </ul>
  <h3 id="bfrc">Пример GET-запроса:</h3>
  <p id="AbvY"><code>local http = game:GetService(&quot;HttpService&quot;)</code></p>
  <p id="SUyR"><code>http:GetAsync(&quot;<a href="https://api.example.com/data" target="_blank">https://api.example.com/data</a> &quot;)<br />    :andThen(function(response)<br />        print(&quot;Ответ от сервера:&quot;, response)<br />    end)<br />    :catch(function(err)<br />        warn(&quot;Ошибка:&quot;, err)<br />    end)</code></p>
  <h3 id="29xR">Пример POST-запроса:</h3>
  <p id="A5Wu"><code>local payload = http:JSONEncode({username = &quot;Alex&quot;, action = &quot;login&quot;})<br />http:PostAsync(&quot;<a href="https://api.example.com/login" target="_blank">https://api.example.com/login</a> &quot;, payload)<br />    :andThen(function(response)<br />        print(&quot;Успешный вход:&quot;, response)<br />    end)<br />    :catch(function(err)<br />        warn(&quot;Ошибка авторизации:&quot;, err)<br />    end)</code></p>
  <blockquote id="RkEc">⚠️ Обрати внимание: большинство API требуют ключей и CORS-разрешений. Roblox имеет ограничения на такие запросы, поэтому используй их только в тестовых или контролируемых условиях.</blockquote>
  <hr />
  <h2 id="NiL8">12.5 — Проект: Локальная система сохранения прогресса</h2>
  <p id="tDPq">Создадим систему, которая позволяет временно сохранять данные в буфере обмена.</p>
  <h3 id="1qKD">Шаг 1: Сохранить прогресс</h3>
  <p id="Bcpt"><code>local http = game:GetService(&quot;HttpService&quot;)</code></p>
  <p id="NTuf"><code>local playerData = {<br />    coins = 100,<br />    level = 3<br />}</code></p>
  <p id="YKW2"><code>local saveString = http:JSONEncode(playerData)<br />setclipboard(saveString)<br />print(&quot;Сохранено в буфер обмена:&quot;)<br />print(saveString)</code></p>
  <h3 id="m7Oy">Шаг 2: Загрузить прогресс</h3>
  <p id="SDKu"><code>-- Представим, что игрок вставил строку<br />local pasteInput = &#x27;[{&quot;coins&quot;:100,&quot;level&quot;:3}]&#x27;<br />local loadedData = http:JSONDecode(pasteInput)</code></p>
  <p id="CX9N"><code>if loadedData then<br />    print(&quot;Загружено:&quot;)<br />    print(&quot;Монеты:&quot;, loadedData.coins)<br />    print(&quot;Уровень:&quot;, loadedData.level)<br />else<br />    warn(&quot;Неверный формат данных.&quot;)<br />end</code></p>
  <hr />
  <h2 id="F4Iv">12.6 — Советы по работе с данными</h2>
  <ul id="jq8E">
    <li id="CODT">Всегда проверяй типы данных перед сериализацией.</li>
    <li id="BELz">Используй <code>pcall()</code> при работе с JSON, чтобы избежать крахов.</li>
    <li id="wbV4">Не отправляй конфиденциальные данные на внешние серверы.</li>
    <li id="5lxK">Для реального сохранения используй <code>DataStore</code>.</li>
    <li id="WFzT">При использовании <code>HttpService</code> тестируй все возможные ошибки.</li>
  </ul>
  <hr />
  <h2 id="imBS">12.7 — Ключевые термины</h2>
  <p id="fIow">Термин - Описание</p>
  <p id="s5TM">HttpService - Сервис для работы с HTTP и JSON</p>
  <p id="em5D">JSONEncode - Преобразует таблицу в JSON-строку</p>
  <p id="FQdS">JSONDecode - Преобразует JSON-строку в таблицу</p>
  <p id="otZY">setclipboard - Копирует текст в буфер обмена (только клиент)</p>
  <p id="eZcm">GetAsync - Выполняет GET-запрос</p>
  <p id="5Jtu">PostAsync - Выполняет POST-запрос</p>
  <p id="fyRE">CORS - Политика безопасности для внешних запросов</p>
  <p id="MO96"></p>
  <h1 id="hiuP">🔹 Глава 13: JSON и работа с форматами данных.</h1>
  <hr />
  <h2 id="xQmV">Введение</h2>
  <p id="PqxD">В этой главе ты узнаешь:</p>
  <ul id="RFuh">
    <li id="WeEk">Что такое JSON и зачем он нужен в Roblox.</li>
    <li id="kTUV">Как сериализовать и десериализовать данные.</li>
    <li id="9JwW">Как работать с вложенными структурами, массивами, сложными таблицами.</li>
    <li id="KoDv">Как использовать JSON для обмена данными между клиентом и сервером.</li>
    <li id="smUz">Как создавать шаблоны конфигураций, сохранять инвентарь, уровни и многое другое.</li>
  </ul>
  <hr />
  <h2 id="EagS">13.1 — Что такое JSON?</h2>
  <p id="Acc4">JSON (JavaScript Object Notation) — это лёгкий формат обмена данными, который легко читается человеком и машиной.</p>
  <h3 id="RGrc">Пример JSON:</h3>
  <p id="uwPR"><code>{<br />    &quot;name&quot;: &quot;Алекс&quot;,<br />    &quot;level&quot;: 5,<br />    &quot;inventory&quot;: [&quot;Меч&quot;, &quot;Щит&quot;, &quot;Зелье&quot;],<br />    &quot;stats&quot;: {<br />        &quot;health&quot;: 100,<br />        &quot;mana&quot;: 50<br />    }<br />}</code></p>
  <h3 id="aybv">Почему используется в Roblox?</h3>
  <ul id="R63N">
    <li id="YUgV">Легко передаётся через <code>HttpService</code>.</li>
    <li id="ERSX">Подходит для хранения сложных данных.</li>
    <li id="neeb">Используется при работе с API.</li>
    <li id="vb3t">Удобен для отладки и тестирования.</li>
  </ul>
  <hr />
  <h2 id="KyFv">13.2 — Сериализация данных в JSON</h2>
  <p id="9FIh">С помощью <code>HttpService</code> можно преобразовать Lua-таблицы в JSON-строки.</p>
  <h3 id="y2Oe">Пример:</h3>
  <p id="2OgY"><code>local http = game:GetService(&quot;HttpService&quot;)</code></p>
  <p id="oeVg"><code>local playerData = {<br />    name = &quot;Алекс&quot;,<br />    level = 5,<br />    inventory = {&quot;Меч&quot;, &quot;Щит&quot;},<br />    stats = {<br />        health = 100,<br />        mana = 50<br />    }<br />}</code></p>
  <p id="Vp0r"><code>local jsonData = http:JSONEncode(playerData)<br />print(jsonData)</code></p>
  <h3 id="UEf7">Результат:</h3>
  <p id="eP42"><code>{&quot;name&quot;:&quot;Алекс&quot;,&quot;level&quot;:5,&quot;inventory&quot;:[&quot;Меч&quot;,&quot;Щит&quot;],&quot;stats&quot;:{&quot;health&quot;:100,&quot;mana&quot;:50}}</code></p>
  <blockquote id="xA5q">⚠️ JSON не сохраняет порядок ключей в таблицах.</blockquote>
  <hr />
  <h2 id="7v3V">13.3 — Десериализация JSON в Lua-таблицу</h2>
  <p id="4gED">Из строки JSON можно получить обратно Lua-таблицу.</p>
  <p id="3cU5"></p>
  <p id="8ghe"><code>local jsonString = &#x27;{&quot;name&quot;:&quot;Алекс&quot;,&quot;level&quot;:5,&quot;inventory&quot;:[&quot;Меч&quot;,&quot;Щит&quot;],&quot;stats&quot;:{&quot;health&quot;:100,&quot;mana&quot;:50}}&#x27;</code></p>
  <p id="vszs"><code>local decoded = http:JSONDecode(jsonString)</code></p>
  <p id="Ekdw"><code>print(decoded.name) -- Алекс</code></p>
  <p id="UW9S"><code>print(decoded.stats.health) -- 100</code></p>
  <hr />
  <h2 id="aiLR">13.4 — Работа с массивами и вложенными объектами</h2>
  <p id="wwJ5">JSON поддерживает массивы (<code>{}</code>) и вложенные объекты (<code>[]</code>).</p>
  <h3 id="kTRp">Массив:</h3>
  <p id="dAYv"><code>[&quot;яблоко&quot;, &quot;банан&quot;, &quot;апельсин&quot;]</code></p>
  <h3 id="CWuC">Вложенный объект:</h3>
  <p id="X285"><code>{<br />    &quot;user&quot;: {<br />        &quot;id&quot;: 123,<br />        &quot;email&quot;: &quot;alex@example.com&quot;<br />    },<br />    &quot;roles&quot;: [&quot;admin&quot;, &quot;moderator&quot;]<br />}</code></p>
  <hr />
  <h2 id="7sEG">13.5 — Обработка ошибок при работе с JSON</h2>
  <p id="amnT">При неправильном формате JSON может произойти ошибка. Используй <code>pcall()</code>:</p>
  <p id="tL4V"><code>local success, result = pcall(function()<br />    return http:JSONDecode(&quot;{invalid json}&quot;)<br />end)</code></p>
  <p id="tHdF"><code>if not success then<br />    warn(&quot;Ошибка JSON:&quot;, result)<br />else<br />    print(&quot;Данные загружены:&quot;, result)<br />end</code></p>
  <hr />
  <h2 id="ICiH">13.6 — Проект: Сохранение инвентаря игрока в JSON</h2>
  <p id="wfQc">Создадим систему, которая сохраняет инвентарь игрока в JSON.</p>
  <h3 id="yDla">Шаг 1: Создай инструменты</h3>
  <p id="pV6X"><code>-- ServerScriptService<br />local toolNames = {&quot;Меч&quot;, &quot;Лук&quot;, &quot;Щит&quot;, &quot;Зелье&quot;}</code></p>
  <p id="Pyob"><code>game.Players.PlayerAdded:Connect(function(player)<br />    local backpack = player.Backpack</code></p>
  <p id="tMle"><code>    for _, name in ipairs(toolNames) do<br />        local tool = Instance.new(&quot;Tool&quot;)<br />        tool.Name = name<br />        tool.RequiresHandle = false<br />        tool.Parent = backpack<br />    end<br />end)</code></p>
  <h3 id="SMvf">Шаг 2: Сохрани инвентарь в JSON</h3>
  <p id="JjqI"><code>-- LocalScript<br />local http = game:GetService(&quot;HttpService&quot;)</code></p>
  <p id="Ezlt"><code>local function saveInventory()<br />    local player = game.Players.LocalPlayer<br />    local backpack = player.Backpack<br />    local inventory = {}</code></p>
  <p id="Xanc"><code>    for _, item in ipairs(backpack:GetChildren()) do<br />        if item:IsA(&quot;Tool&quot;) then<br />            table.insert(inventory, item.Name)<br />        end<br />    end</code></p>
  <p id="TLls"><code>    local json = http:JSONEncode(inventory)<br />    setclipboard(json)<br />    print(&quot;Инвентарь сохранён в буфер обмена:&quot;)<br />    print(json)<br />end</code></p>
  <p id="CNr4"><code>-- Вызови функцию по кнопке<br />local gui = Instance.new(&quot;ScreenGui&quot;)<br />gui.Parent = player.PlayerGui</code></p>
  <p id="I728"><code>local button = Instance.new(&quot;TextButton&quot;)<br />button.Text = &quot;Сохранить инвентарь&quot;<br />button.Size = UDim2.new(0, 200, 0, 50)<br />button.Position = UDim2.new(0.5, -100, 0.2, 0)<br />button.Parent = gui</code></p>
  <p id="hHm1"><code>button.MouseButton1Down:Connect(saveInventory)</code></p>
  <hr />
  <h2 id="rs2i">13.7 — Советы и рекомендации</h2>
  <ul id="FFAx">
    <li id="h5yH">Используй JSON для временного хранения данных.</li>
    <li id="6umu">Проверяй типы данных перед сериализацией.</li>
    <li id="zJqP">Не используй JSON для критически важных операций без проверки.</li>
    <li id="1PJk">Для долгосрочного хранения используй <code>DataStore</code>.</li>
    <li id="X6WS">При работе с API всегда используй безопасные методы передачи.</li>
  </ul>
  <hr />
  <h2 id="RSH1">13.8 — Ключевые термины</h2>
  <p id="XUZB">Термин - Описание</p>
  <p id="ZwJp">JSON - Формат обмена данными</p>
  <p id="q4Pl">JSONEncode - Преобразует таблицу в JSON</p>
  <p id="Hbvl">JSONDecode - Преобразует JSON в таблицу</p>
  <p id="QrFE">HttpService - Сервис для работы с JSON и HTTP</p>
  <p id="RbjF">Массив - Упорядоченная последовательность элементов</p>
  <p id="73Os">Объект - Набор пар ключ-значение</p>
  <p id="lDnN">Вложенная структура - Объект внутри другого объекта</p>
  <p id="oixY"></p>
  <h1 id="wbHo">🔹 Глава 14: Работа с аудио и звуками.</h1>
  <hr />
  <h2 id="OJdw">Введение</h2>
  <p id="AQTy">В этой главе ты узнаешь:</p>
  <ul id="wvFM">
    <li id="KRyn">Как добавлять и воспроизводить звуки в Roblox.</li>
    <li id="aOKW">Как использовать <code>Sound</code> и <code>SoundService</code>.</li>
    <li id="dkmV">Как управлять громкостью, позицией, повторением.</li>
    <li id="LviX">Как связывать звуки с событиями (например, нажатие кнопки, выстрел).</li>
    <li id="rftC">Как создавать фоновую музыку и динамические звуки.</li>
  </ul>
  <hr />
  <h2 id="8KWo">14.1 — Основы работы со звуком в Roblox</h2>
  <p id="5I4o">Roblox использует объект <code>Sound</code>, который можно прикрепить к любой части или персонажу.</p>
  <h3 id="9Szk">Пример простого звука:</h3>
  <p id="519b"><code>local sound = Instance.new(&quot;Sound&quot;)</code></p>
  <p id="oI0v"><code>sound.SoundId = &quot;rbxassetid://123456789&quot; -- замени на нужный ID</code></p>
  <p id="fAL1"><code>sound.Volume = 1</code></p>
  <p id="hiDe"><code>sound.Parent = workspace</code></p>
  <p id="299V"><code>sound:Play()</code></p>
  <blockquote id="0h7Z">💡 Чтобы найти SoundId, зайди на <a href="https://www.roblox.com/library" target="_blank">https://www.roblox.com/library </a>, выбери звук и скопируй его ID.</blockquote>
  <hr />
  <h2 id="AGfr">14.2 — Свойства звука</h2>
  <p id="dI4p">Свойство - Описание</p>
  <p id="xod0"><code>SoundId</code> - ID звука (из библиотеки Roblox)</p>
  <p id="0W65"><code>Volume</code> - Громкость (от 0 до 10)</p>
  <p id="emID"><code>Pitch</code> - Изменение тональности (от 0.1 до 2)</p>
  <p id="UvY2"><code>Looped</code> - Зациклить звук</p>
  <p id="nBDE"><code>PlaybackSpeed</code> - Скорость воспроизведения</p>
  <p id="382A"><code>IsPlaying</code> - Проверяет, играет ли звук сейчас</p>
  <h3 id="eJRG">Пример изменения свойств:</h3>
  <p id="D6wi"><code>sound.Volume = 0.5</code></p>
  <p id="6jet"><code>sound.Pitch = 1.2</code></p>
  <p id="HVUy"><code>sound.Looped = true</code></p>
  <hr />
  <h2 id="AVZi">14.3 — Управление воспроизведением</h2>
  <h3 id="RLVk">Воспроизведение:</h3>
  <p id="A7SF"><code>sound:Play()</code></p>
  <h3 id="WPHl">Остановка:</h3>
  <p id="icE1"><code>sound:Stop()</code></p>
  <h3 id="0Df7">Пауза:</h3>
  <p id="dvxx"><code>sound:Pause()</code></p>
  <hr />
  <h2 id="OT8O">14.4 — Создание фоновой музыки</h2>
  <p id="RyhE">Фоновая музыка обычно размещается в <code>SoundService</code>.</p>
  <p id="l43A"><code>local music = Instance.new(&quot;Sound&quot;)</code></p>
  <p id="df6X"><code>music.SoundId = &quot;rbxassetid://987654321&quot;</code></p>
  <p id="3XlN"><code>music.Volume = 0.7</code></p>
  <p id="2Ed2"><code>music.Looped = true</code></p>
  <p id="cMRZ"><code>music.Parent = game:GetService(&quot;SoundService&quot;)</code></p>
  <p id="CnGm"><code>music:Play()</code></p>
  <hr />
  <h2 id="EpjS">14.5 — Локализация звука</h2>
  <p id="Zgiw">Звук может быть локализован — он будет громче, если игрок рядом с источником.</p>
  <p id="vIN3"><code>local part = workspace.Part</code></p>
  <p id="1MoX"><code>local sound = part:FindFirstChild(&quot;Sound&quot;) or Instance.new(&quot;Sound&quot;)</code></p>
  <p id="qJv5"><code>sound.SoundId = &quot;rbxassetid://123456789&quot;</code></p>
  <p id="OkCP"><code>sound.Volume = 1</code></p>
  <p id="4E7Z"><code>sound.EmitterSize = 10 -- радиус действия звука</code></p>
  <p id="OLee"><code>sound.PlayOnRemove = false</code></p>
  <p id="4rRk"><code>sound.Parent = part</code></p>
  <hr />
  <h2 id="uQgy">14.6 — Проект: Музыкальная кнопка</h2>
  <p id="kr1n">Создадим кнопку, которая запускает и останавливает музыку.</p>
  <h3 id="NqHD">Шаг 1: Создай GUI кнопку</h3>
  <p id="tOVx"><code>local player = game.Players.LocalPlayer</code></p>
  <p id="fiav"><code>local gui = Instance.new(&quot;ScreenGui&quot;)</code></p>
  <p id="2LGZ"><code>gui.Parent = player.PlayerGui</code></p>
  <p id="0K7F"><code>local button = Instance.new(&quot;TextButton&quot;)</code></p>
  <p id="Pkxi"><code>button.Text = &quot;Включить музыку&quot;</code></p>
  <p id="Beyc"><code>button.Size = UDim2.new(0, 200, 0, 50)</code></p>
  <p id="FLyB"><code>button.Position = UDim2.new(0.5, -100, 0.2, 0)</code></p>
  <p id="MScq"><code>button.Parent = gui</code></p>
  <h3 id="AGd5">Шаг 2: Добавь функционал</h3>
  <p id="9YR5"><code>local isPlaying = false<br />local music = Instance.new(&quot;Sound&quot;)<br />music.SoundId = &quot;rbxassetid://987654321&quot;<br />music.Volume = 0.5<br />music.Looped = true<br />music.Parent = game:GetService(&quot;SoundService&quot;)</code></p>
  <p id="bBXU"><code>button.MouseButton1Down:Connect(function()<br />    if not isPlaying then<br />        music:Play()<br />        button.Text = &quot;Выключить музыку&quot;<br />    else<br />        music:Stop()<br />        button.Text = &quot;Включить музыку&quot;<br />    end<br />    isPlaying = not isPlaying<br />end)</code></p>
  <hr />
  <h2 id="Nrfl">14.7 — Советы и рекомендации</h2>
  <ul id="kK7P">
    <li id="fGp0">Используй <code>SoundService</code> для фоновой музыки.</li>
    <li id="5Tch">Для локальных звуков привязывай <code>Sound</code> к <code>Part</code>.</li>
    <li id="3G6A">Не забывай очищать звуки после использования.</li>
    <li id="5VHP">Тестируй звуки в разных условиях (в помещении, на улице).</li>
    <li id="yqxW">Используй <code>EmitterSize</code> для реалистичного звучания.</li>
  </ul>
  <hr />
  <h2 id="5AGh">14.8 — Ключевые термины</h2>
  <p id="2T52">Термин - Описание</p>
  <p id="BUvG">Sound - Объект для воспроизведения звука</p>
  <p id="xPmY">SoundService - Сервис для глобальных звуков</p>
  <p id="sCEO">SoundId - ID звука из Roblox Library</p>
  <p id="rXe7">Volume - Громкость звука</p>
  <p id="lpdi">Pitch - Тональность</p>
  <p id="TABd">Looped - Зацикленное воспроизведение</p>
  <p id="lnWR">EmitterSize - Радиус действия звука</p>
  <p id="bgoc">PlaybackSpeed - Скорость воспроизведения</p>
  <p id="ZmIt"></p>
  <h1 id="nnA2">🔹 Глава 15: Таймеры, корутины и многозадачность.</h1>
  <hr />
  <h2 id="zBaU">Введение</h2>
  <p id="gr1r">В этой главе ты узнаешь:</p>
  <ul id="8bfN">
    <li id="5XIi">Как использовать таймеры для отложенного выполнения.</li>
    <li id="TF7H">Что такое <code>wait()</code> и как его правильно использовать.</li>
    <li id="VCTB">Как работают корутины и зачем они нужны.</li>
    <li id="AeLP">Как выполнять несколько задач одновременно.</li>
    <li id="e2Au">Как создавать сложные механики с задержками, анимациями и событиями.</li>
  </ul>
  <hr />
  <h2 id="IvPi">15.1 — Работа с временем: <code>wait()</code></h2>
  <p id="Htny"><code>wait()</code> — это функция, которая приостанавливает выполнение кода на определённое время.</p>
  <h3 id="1qxj">Пример:</h3>
  <p id="nOg4"><code>print(&quot;Старт&quot;)</code></p>
  <p id="ioTb"><code>wait(3)</code></p>
  <p id="wZUX"><code>print(&quot;Прошло 3 секунды&quot;)</code></p>
  <blockquote id="7XPg">⚠️ <code>wait()</code> можно использовать только внутри корутин или циклов.</blockquote>
  <hr />
  <h2 id="wlFY">15.2 — Циклы с задержкой</h2>
  <p id="TYYQ">Создание повторяющихся действий:</p>
  <p id="XpAo"><code>while true do<br />    print(&quot;Тик!&quot;)<br />    wait(1) — раз в секунду<br />end</code></p>
  <hr />
  <h2 id="L7CX">15.3 — Параллельное выполнение: <code>spawn()</code></h2>
  <p id="RuBJ">Иногда нужно запускать несколько задач одновременно. Для этого используется <code>spawn()</code>.</p>
  <h3 id="EBSo">Пример:</h3>
  <p id="qjSE"><code>spawn(function()<br />    while true do<br />        print(&quot;Задача 1&quot;)<br />        wait(2)<br />    end<br />end)</code></p>
  <p id="jQUS"><code>spawn(function()<br />    while true do<br />        print(&quot;Задача 2&quot;)<br />        wait(3)<br />    end<br />end)</code></p>
  <hr />
  <h2 id="wu69">15.4 — Корутины: управление потоками</h2>
  <p id="q0Dm">Корутины позволяют управлять выполнением кода вручную.</p>
  <h3 id="9bjf">Создание корутины:</h3>
  <p id="FriS"><code>local co = coroutine.create(function()<br />    for i = 1, 5 do<br />        print(&quot;Корутина:&quot;, i)<br />        wait(1)<br />    end<br />end)</code></p>
  <p id="mzCB"><code>coroutine.resume(co) — запускает корутину</code></p>
  <h3 id="KuQs">Проверка состояния:</h3>
  <p id="Js0U"><code>print(coroutine.status(co)) -- &quot;running&quot;, &quot;dead&quot;, &quot;suspended&quot;</code></p>
  <hr />
  <h2 id="TTHL">15.5 — Использование <code>delay()</code> для отложенного вызова</h2>
  <p id="Q5IL">Можно выполнить функцию через определённое время:</p>
  <p id="LNIb"><code>delay(5, function()<br />    print(&quot;Прошло 5 секунд&quot;)<br />end)</code></p>
  <hr />
  <h2 id="69jR">15.6 — Проект: Система спавна врагов с задержкой</h2>
  <p id="wF46">Создадим систему, которая создаёт новых врагов каждые 5 секунд.</p>
  <h3 id="eSd7">Шаг 1: Создай врага</h3>
  <p id="yN0M"><code>function spawnEnemy()<br />    local enemy = Instance.new(&quot;Model&quot;)<br />    enemy.Name = &quot;Enemy&quot;</code></p>
  <p id="dfP2"><code>    local root = Instance.new(&quot;Part&quot;)<br />    root.Anchored = false<br />    root.Name = &quot;HumanoidRootPart&quot;<br />    root.Parent = enemy</code></p>
  <p id="ali6"><code>    local humanoid = Instance.new(&quot;Humanoid&quot;)<br />    humanoid.Health = 50<br />    humanoid.Parent = enemy</code></p>
  <p id="BOto"><code>    enemy.Parent = workspace<br />    root.CFrame = CFrame.new(math.random(-20, 20), 5, math.random(-20, 20))<br />end</code></p>
  <h3 id="2ZSg">Шаг 2: Запуск с задержкой</h3>
  <p id="oyII"><code>spawn(function()<br />    while true do<br />        spawnEnemy()<br />        wait(5) -- каждые 5 секунд<br />    end<br />end)</code></p>
  <hr />
  <h2 id="HBHo">15.7 — Советы по работе с таймерами</h2>
  <ul id="Vu98">
    <li id="CjeA">Не используй <code>wait()</code> вне корутин или циклов.</li>
    <li id="AKWw">Используй <code>spawn()</code> для параллельного выполнения.</li>
    <li id="MDQ6">Ограничивай количество активных задач.</li>
    <li id="sale">Не забывай остановить циклы при удалении объектов.</li>
    <li id="7zOI">Для точных таймеров используй <code>RunService</code>.</li>
  </ul>
  <hr />
  <h2 id="H2vG">15.8 — Использование RunService для точного контроля времени</h2>
  <p id="YTiu"><code>RunService</code> позволяет запускать код на каждом кадре или через определённое количество времени.</p>
  <p id="Rt5k"><code>local runService = game:GetService(&quot;RunService&quot;)</code></p>
  <p id="8oxl"><code>-- Выполняется каждый кадр<br />runService.RenderStepped:Connect(function()<br />    -- здесь можно обновлять позиции, анимации и т.д.<br />end)</code></p>
  <p id="0tKZ"><code>— Выполняется каждую секунду<br />local lastTime = tick()<br />runService.RenderStepped:Connect(function()<br />    if tick() - lastTime &gt;= 1 then<br />        print(&quot;Прошла 1 секунда&quot;)<br />        lastTime = tick()<br />    end<br />end)</code></p>
  <hr />
  <h2 id="oTf2">15.9 — Ключевые термины</h2>
  <p id="sUA2">Термин - Описание</p>
  <p id="wSKY">wait() - Приостанавливает выполнение</p>
  <p id="wVRn">spawn() - Запускает задачу параллельно</p>
  <p id="BpPK">coroutine - Объект для управления выполнением</p>
  <p id="rAQ7">delay() - Откладывает выполнение</p>
  <p id="ZWvF">RenderStepped - Событие каждого кадра</p>
  <p id="UUO5">Heartbeat - Событие с частотой ~60 FPS</p>
  <p id="nYyw">RunService - Сервис для работы с временем</p>
  <p id="1Vna"></p>
  <h1 id="EnaE">🔹 Глава 16: Обработка ошибок и отладка.</h1>
  <hr />
  <h2 id="XxTB">Введение</h2>
  <p id="Xv0p">В этой главе ты узнаешь:</p>
  <ul id="QxXo">
    <li id="4p0M">Как обрабатывать ошибки с помощью <code>pcall()</code> и <code>xpcall()</code>.</li>
    <li id="r9KO">Как использовать <code>warn()</code>, <code>error()</code> и <code>assert()</code> для диагностики.</li>
    <li id="pUV1">Как читать стек-трейсы и находить проблемные места в коде.</li>
    <li id="Njto">Как проверять типы данных и избегать крашей.</li>
    <li id="dMOl">Как делать безопасные вызовы функций и методов.</li>
  </ul>
  <hr />
  <h2 id="LBA8">16.1 — Что такое ошибка в программировании?</h2>
  <p id="64bd">Ошибка (или исключение) — это ситуация, при которой выполнение программы невозможно продолжить по какой-то причине:</p>
  <ul id="Wums">
    <li id="KmEd">Несуществующий объект</li>
    <li id="cWZ6">Деление на ноль</li>
    <li id="g7sS">Ошибка в синтаксисе</li>
    <li id="auwA">Неверный тип данных</li>
  </ul>
  <h3 id="hk6Q">Пример простой ошибки:</h3>
  <p id="VTWl"><code>local x = 5 / &quot;текст&quot;</code></p>
  <p id="sEWK"><code>-- Выдаст: attempt to perform arithmetic on a string value</code></p>
  <hr />
  <h2 id="PxTq">16.2 — Использование <code>pcall()</code> для безопасных вызовов</h2>
  <p id="g7ZR"><code>pcall()</code> (protected call) позволяет вызвать функцию и поймать любые ошибки внутри неё.</p>
  <h3 id="07pf">Пример:</h3>
  <p id="2waK"><code>local success, result = pcall(function()<br />    return 5 / 0<br />end)</code></p>
  <p id="6MIj"><code>if not success then<br />    print(&quot;Произошла ошибка:&quot;, result)<br />else<br />    print(&quot;Результат:&quot;, result)<br />end</code></p>
  <blockquote id="STHx">💡 <code>pcall()</code> возвращает два значения: успешность выполнения и результат или сообщение об ошибке.</blockquote>
  <hr />
  <h2 id="NpBM">16.3 — Использование <code>xpcall()</code> с пользовательским обработчиком</h2>
  <p id="5Eog"><code>xpcall()</code> работает как <code>pcall()</code>, но позволяет указать свою функцию для форматирования ошибок.</p>
  <p id="D8Zt"><code>local function errorHandler(err)<br />    return &quot;Критическая ошибка: &quot; .. err<br />end</code></p>
  <p id="Q2u7"><code>local success, result = xpcall(function()<br />    local x = 5 / &quot;текст&quot;<br />end, errorHandler)</code></p>
  <p id="IxIF"><code>print(result) -- Критическая ошибка: attempt to perform arithmetic on a string value</code></p>
  <hr />
  <h2 id="wEs2">16.4 — Использование <code>warn()</code> и <code>error()</code> для отладки</h2>
  <h3 id="N6op"><code>warn()</code> — вывод предупреждений</h3>
  <p id="Igfr"><code>warn(&quot;Эта функция устарела!&quot;)</code></p>
  <blockquote id="t3Fi">Предупреждения не останавливают выполнение скрипта.</blockquote>
  <h3 id="zjHk"><code>error()</code> — генерация ошибки</h3>
  <p id="6sbl"><code>if x == nil then<br />    error(&quot;Переменная x не определена&quot;)<br />end</code></p>
  <blockquote id="ux1u">При вызове <code>error()</code> выполнение останавливается, и ошибка передаётся выше.</blockquote>
  <hr />
  <h2 id="8y0q">16.5 — Проверка типов с помощью <code>type()</code> и <code>typeof()</code></h2>
  <p id="WlRF">Иногда ошибка возникает из-за неверного типа данных. Лучше проверять заранее.</p>
  <p id="YNMf"><code>local function add(a, b)<br />    if type(a) ~= &quot;number&quot; or type(b) ~= &quot;number&quot; then<br />        error(&quot;Ожидаются числа&quot;, 2)<br />    end<br />    return a + b<br />end</code></p>
  <p id="it9m"><code>add(5, &quot;текст&quot;) -- выдаст ошибку</code></p>
  <p id="LHOK">Функция - Описание</p>
  <p id="GUts"><code>type()</code> - Возвращает тип значения (<code>nil</code>,<code>number</code>,<code>string</code>,<code>boolean</code>,<code>table</code>,<code>function</code>)</p>
  <p id="J43k"><code>typeof()</code> - Возвращает тип объекта Roblox (например,<code>Part</code>,<code>Sound</code>,<code>Humanoid</code>)</p>
  <hr />
  <h2 id="D5J0">16.6 — Использование <code>assert()</code> для проверки условий</h2>
  <p id="xCNL"><code>assert()</code> — удобный способ проверить условие и выдать ошибку, если оно не выполнено.</p>
  <p id="ufXB"><code>local player = game.Players.LocalPlayer<br />assert(player, &quot;Игрок не найден&quot;)</code></p>
  <p id="feBP"><code>local character = player.Character or player.CharacterAdded:Wait()<br />assert(character, &quot;Персонаж не загружен&quot;)</code></p>
  <hr />
  <h2 id="3Icj">16.7 — Чтение стек-трейсов</h2>
  <p id="0fqa">Когда происходит ошибка, Roblox выводит <strong>стек-трейс </strong>— список всех функций, которые привели к ошибке.</p>
  <h3 id="81zZ">Пример:</h3>
  <p id="R3Ej"><code>Players.Alex.PlayerScripts.Script:5: in function &#x27;add&#x27;</code></p>
  <p id="s3HJ"><code>Players.Alex.PlayerScripts.Script:10: in main chunk</code></p>
  <p id="M6fI">Это значит:</p>
  <ul id="Tw83">
    <li id="GlAe">Ошибка произошла в строке 5 функции <code>add</code></li>
    <li id="N0Uh">Эта функция была вызвана в строке 10 основного скрипта</li>
  </ul>
  <hr />
  <h2 id="5S91">16.8 — Проект: Система защиты от краша</h2>
  <p id="DY42">Создадим систему, которая защищает важную часть кода от краша.</p>
  <h3 id="YYZm">Шаг 1: Защита функции</h3>
  <p id="P37l"><code>local function safeCall(func)<br />    local success, result = pcall(func)<br />    if not success then<br />        warn(&quot;Ошибка в функции:&quot;, result)<br />    else<br />        return result<br />    end<br />end</code></p>
  <h3 id="yBGA">Шаг 2: Использование</h3>
  <p id="Un7B"><code>safeCall(function()<br />    local x = 10 / 0<br />end)</code></p>
  <p id="4wNq"><code>print(&quot;Продолжаем выполнение...&quot;)</code></p>
  <blockquote id="zEdh">✅ Этот код не упадёт, а просто выведет ошибку и продолжит работу.</blockquote>
  <hr />
  <h2 id="5Agd">16.9 — Советы по отладке</h2>
  <ul id="G9sO">
    <li id="oYQt">Используй <code>print()</code> и <code>warn()</code> для логирования.</li>
    <li id="WBt5">Проверяй существование объектов до их использования.</li>
    <li id="4xNM">Не используй глобальные переменные без проверки.</li>
    <li id="nHr2">Используй <code>pcall()</code> для внешних вызовов.</li>
    <li id="J2th">Указывай уровень в <code>error()</code> для точного трейса.</li>
    <li id="RsT3">Тестируй каждую функцию отдельно.</li>
  </ul>
  <hr />
  <h2 id="hWWR">16.10 — Ключевые термины</h2>
  <p id="wUYX">Термин - Описание</p>
  <p id="amWL">pcall - Безопасный вызов функции</p>
  <p id="FYWM">xpcall - Вызов с пользовательским обработчиком ошибок</p>
  <p id="bYWl">warn - Выводит предупреждение</p>
  <p id="FhZn">error - Генерирует ошибку</p>
  <p id="DkE0">assert - Проверяет условие и вызывает ошибку, если оно не выполнено</p>
  <p id="482f">stack trace - Список вызванных функций</p>
  <p id="aBgz">type - Возвращает тип значения</p>
  <p id="605r">typeof - Возвращает тип объекта Roblox</p>
  <p id="dEgB"></p>
  <h1 id="9vOw">🔹 Глава 17: Плагины для Roblox Studio.</h1>
  <hr />
  <h2 id="LpG2">Введение</h2>
  <p id="29Qx">В этой главе ты узнаешь:</p>
  <ul id="l9Eh">
    <li id="uujh">Что такое плагины в Roblox Studio и зачем они нужны.</li>
    <li id="IyDs">Как создавать простые и сложные плагины.</li>
    <li id="ueSB">Как добавлять кнопки, меню, контекстные действия.</li>
    <li id="iuPs">Как использовать API Roblox Studio для автоматизации задач.</li>
    <li id="QbLu">Как сохранять и распространять свои плагины.</li>
  </ul>
  <hr />
  <h2 id="nZw3">17.1 — Что такое плагин?</h2>
  <p id="SZPM">Плагин — это скрипт, который работает внутри Roblox Studio и позволяет улучшать и ускорять процесс разработки.</p>
  <h3 id="KmXF">Основные возможности:</h3>
  <ul id="V4Hx">
    <li id="egNl">Добавление новых инструментов</li>
    <li id="hbjN">Автоматизация рутинных действий</li>
    <li id="ojw2">Работа с деревом объектов</li>
    <li id="jTe9">Расширение возможностей интерфейса</li>
  </ul>
  <hr />
  <h2 id="ykna">17.2 — Создание первого плагина</h2>
  <h3 id="tQA1">Шаг 1: Открой Plugin Editor</h3>
  <ol id="V3MZ">
    <li id="Eijk">Открой Roblox Studio.</li>
    <li id="eX8t">Перейди в <strong>Plugins </strong>→ <strong>Plugin Manager </strong>.</li>
    <li id="gGjq">Нажми <strong>Create Plugin </strong>.</li>
  </ol>
  <h3 id="p1Op">Шаг 2: Добавь код</h3>
  <p id="8Ehj"><code>-- Main Script<br />local plugin = script:FindFirstAncestor(&quot;MyFirstPlugin&quot;)</code></p>
  <p id="ddEI"><code>local toolbar = plugin:CreateToolbar(&quot;Мои инструменты&quot;)<br />local button = toolbar:CreateButton(&quot;Привет&quot;, &quot;Нажми меня&quot;, &quot;&quot;)</code></p>
  <p id="Nvwd"><code>button.Clicked:Connect(function()<br />    print(&quot;Привет от плагина!&quot;)<br />end)</code></p>
  <blockquote id="U71y">✅ Теперь у тебя есть новая кнопка в панели инструментов!</blockquote>
  <hr />
  <h2 id="Y4Kd">17.3 — Структура плагина</h2>
  <p id="agKU">Типичный плагин состоит из:</p>
  <p id="pc29">Элемент - Описание</p>
  <p id="bXQQ"><code>Plugin</code> - Корневой объект плагина</p>
  <p id="HZMz"><code>Toolbar</code> - Панель инструментов</p>
  <p id="ztJa"><code>Button</code> - Кнопка на панели</p>
  <p id="excA"><code>Menu</code> - Выпадающее меню</p>
  <p id="7qMn"><code>Context Menu</code> - ПКМ-меню на объектах</p>
  <hr />
  <h2 id="O19S">17.4 — Работа с деревом объектов через API</h2>
  <p id="lKOZ">Плагины имеют доступ к полному API Roblox Studio и могут изменять объекты напрямую.</p>
  <h3 id="ZV7r">Пример: Создай Part при нажатии</h3>
  <p id="StVf"><code>button.Clicked:Connect(function()<br />    local part = Instance.new(&quot;Part&quot;)<br />    part.Size = Vector3.new(2, 2, 2)<br />    part.Position = Vector3.new(0, 5, 0)<br />    part.Anchored = true<br />    part.Parent = workspace<br />end)</code></p>
  <hr />
  <h2 id="devO">17.5 — Добавление контекстного меню</h2>
  <p id="TGdo">Контекстное меню появляется при правом клике на объекте.</p>
  <p id="rG60"><code>plugin:CreateContextMenu(&quot;Увеличить размер&quot;, function(objects)<br />    for _, obj in ipairs(objects) do<br />        if obj:IsA(&quot;BasePart&quot;) then<br />            obj.Size += Vector3.new(1, 1, 1)<br />        end<br />    end<br />end)</code></p>
  <hr />
  <h2 id="Q6av">17.6 — Сохранение и загрузка данных плагина</h2>
  <p id="ayJQ">Плагины могут хранить данные локально (в пределах сессии):</p>
  <p id="3HXl"><code>local storage = require(game:GetService(&quot;ReplicatedStorage&quot;).PluginStorage)</code></p>
  <p id="APer"><code>button.Clicked:Connect(function()<br />    storage.LastAction = &quot;Кнопка нажата&quot;<br />    print(&quot;Сохранено:&quot;, storage.LastAction)<br />end)</code></p>
  <hr />
  <h2 id="wduf">17.7 — Проект: Плагин для быстрого создания дверей</h2>
  <p id="qH3K">Создадим плагин, который создаёт дверь с функцией открытия/закрытия.</p>
  <h3 id="9fxZ">Шаг 1: Добавь кнопку</h3>
  <p id="xPFA"><code>local plugin = script:FindFirstAncestor(&quot;DoorTool&quot;)</code></p>
  <p id="y9YT"><code>local toolbar = plugin:CreateToolbar(&quot;Инструменты&quot;)</code></p>
  <p id="ub5P"><code>local createButton = toolbar:CreateButton(&quot;Создать дверь&quot;, &quot;Создаёт новую дверь&quot;, &quot;&quot;)</code></p>
  <h3 id="zjfL">Шаг 2: Логика двери</h3>
  <p id="IWkn"><code>createButton.Clicked:Connect(function()<br />    local door = Instance.new(&quot;Model&quot;)<br />    door.Name = &quot;Door&quot;</code></p>
  <p id="dVhl"><code>    local frame = Instance.new(&quot;Part&quot;)<br />    frame.Size = Vector3.new(2, 5, 0.5)<br />    frame.BrickColor = BrickColor.Brown()<br />    frame.Anchored = true<br />    frame.Locked = true<br />    frame.Parent = door</code></p>
  <p id="T85b"><code>    local hinge = Instance.new(&quot;HingeConstraint&quot;)<br />    hinge.Attachment0 = Instance.new(&quot;Attachment&quot;, frame)<br />    hinge.Attachment0.Position = Vector3.new(-1, 0, 0)<br />    hinge.LimitsEnabled = true<br />    hinge.LowerAngle = -90<br />    hinge.UpperAngle = 0<br />    hinge.Parent = frame</code></p>
  <p id="L7Zi"><code>    frame.CFrame = CFrame.new(0, 5, 10)<br />    door.Parent = workspace<br />end)</code></p>
  <h3 id="fJnE">Шаг 3: Добавь интерактивность</h3>
  <p id="ol1R"><code>local openButton = toolbar:CreateButton(&quot;Открыть дверь&quot;, &quot;&quot;, &quot;&quot;)</code></p>
  <p id="OUcZ"><code>openButton.Clicked:Connect(function()<br />    for _, door in ipairs(workspace:GetChildren()) do<br />        if door.Name == &quot;Door&quot; then<br />            local hinge = door.HingeConstraint<br />            hinge.UpperAngle = 90<br />        end<br />    end<br />end)</code></p>
  <hr />
  <h2 id="y4Ah">17.8 — Советы по созданию плагинов</h2>
  <ul id="l8qR">
    <li id="Z9xh">Используй понятные названия для кнопок и панелей.</li>
    <li id="ekYM">Не изменяй чужие объекты без подтверждения.</li>
    <li id="DohS">Тестируй плагины перед публикацией.</li>
    <li id="Jj7c">Документируй функционал и параметры.</li>
    <li id="097K">Публикуй плагины на <a href="https://www.roblox.com/library" target="_blank">https://www.roblox.com/library </a>.</li>
  </ul>
  <hr />
  <h2 id="UaIU">17.9 — Ключевые термины</h2>
  <p id="xwWk">Термин - Описание</p>
  <p id="ViM2">Plugin - Объект, представляющий плагин</p>
  <p id="qiag">Toolbar - Панель инструментов</p>
  <p id="watD">Button - Кнопка на панели</p>
  <p id="Iid5">Context Menu - Меню при правом клике</p>
  <p id="hMFW">HingeConstraint - Шарнир для движения</p>
  <p id="hVsF">Attachment - Точка привязки</p>
  <p id="63RC">PluginStorage - Хранилище данных плагина</p>
  <p id="qv98">CreateButton - Создаёт кнопку в интерфейсе</p>
  <p id="uJUq">CreateContextMenu - Добавляет пункт в контекстное меню</p>
  <p id="81gP"></p>
  <h1 id="kF6T">🔹 Глава 18: Мультиплеер и работа с командами.</h1>
  <hr />
  <h2 id="676E">Введение</h2>
  <p id="mg8F">В этой главе ты узнаешь:</p>
  <ul id="zzqW">
    <li id="5eur">Как работает мультиплеер в Roblox.</li>
    <li id="7Ka0">Как взаимодействовать с другими игроками.</li>
    <li id="rB6c">Как создавать команды (Teams) и управлять ими.</li>
    <li id="pndM">Как реализовать систему битвы, чата и рейтинга.</li>
    <li id="zHMO">Как использовать серверные данные для всех игроков.</li>
  </ul>
  <hr />
  <h2 id="18lQ">18.1 — Что такое мультиплеер?</h2>
  <p id="4izJ">Roblox изначально поддерживает <strong>мультиплеер </strong>, то есть возможность одновременной игры нескольких игроков в одном мире.</p>
  <h3 id="UjTB">Основные особенности:</h3>
  <ul id="IX3j">
    <li id="vn8A">Каждый игрок имеет своего персонажа.</li>
    <li id="pZkX">Все действия отслеживаются на сервере.</li>
    <li id="jHlp">Можно взаимодействовать с другими игроками.</li>
    <li id="k3FS">Поддержка команд, лидербордов, чата и т.д.</li>
  </ul>
  <hr />
  <h2 id="vkrv">18.2 — Работа с игроками</h2>
  <p id="vQiZ"><code>Roblox предоставляет доступ ко всем игрокам через сервис Players.</code></p>
  <p id="JgT9"><code>local players = game:GetService(&quot;Players&quot;)</code></p>
  <p id="bDL1"><code>players.PlayerAdded:Connect(function(player)<br />    print(player.Name .. &quot; зашёл в игру&quot;)<br />end)</code></p>
  <p id="DLnu"><code>players.PlayerRemoving:Connect(function(player)<br />    print(player.Name .. &quot; вышел из игры&quot;)<br />end)</code></p>
  <hr />
  <h2 id="WVF9">18.3 — Использование команд (Teams)</h2>
  <p id="p0hQ">Команды позволяют группировать игроков и управлять их взаимодействием.</p>
  <h3 id="7Bn3">Создание команд:</h3>
  <p id="AVAC"><code>local team1 = Instance.new(&quot;Team&quot;)</code></p>
  <p id="R6IP"><code>team1.Name = &quot;Красные&quot;</code></p>
  <p id="sAgo"><code>team1.TeamColor = BrickColor.Red()</code></p>
  <p id="L6LW"><code>team1.Parent = game.Teams</code></p>
  <p id="ibRt"><code>local team2 = Instance.new(&quot;Team&quot;)</code></p>
  <p id="7uWI"><code>team2.Name = &quot;Синие&quot;</code></p>
  <p id="fbMx"><code>team2.TeamColor = BrickColor.Blue()</code></p>
  <p id="QI98"><code>team2.Parent = game.Teams</code></p>
  <h3 id="6F55">Назначение игрока в команду:</h3>
  <p id="zqP6"><code>game.Players.PlayerAdded:Connect(function(player)<br />    if player.UserId % 2 == 0 then<br />        player.Team = team1<br />    else<br />        player.Team = team2<br />    end<br />end)</code></p>
  <hr />
  <h2 id="w39P">18.4 — Управление взаимодействием между игроками</h2>
  <p id="4NXF">По умолчанию игроки могут взаимодействовать друг с другом. Но можно изменить поведение, например, чтобы игроки одной команды не наносили урон друг другу.</p>
  <h3 id="clwc">Отключение дружеского огня:</h3>
  <p id="wkVt"><code>workspace:SetRealPhysicsCollisionAsync(true)</code></p>
  <p id="8N3b"><code>game.Players.PlayerAdded:Connect(function(player)<br />    player.Damaged:Connect(function(hit)<br />        local otherPlayer = game.Players:GetPlayerFromCharacter(hit.Parent)<br />        if otherPlayer and otherPlayer.Team == player.Team then<br />            hit.Parent.Humanoid.Health = hit.Parent.Humanoid.MaxHealth<br />        end<br />    end)<br />end)</code></p>
  <hr />
  <h2 id="uZIi">18.5 — Проект: Система команд и битва</h2>
  <p id="461B">Создадим простую систему, где игроки делятся на две команды и получают бонус при убийстве игрока из другой команды.</p>
  <h3 id="JiWu">Шаг 1: Настройка команд</h3>
  <p id="C9Ew"><code>-- ServerScriptService</code></p>
  <p id="BF98"><code>local redTeam = Instance.new(&quot;Team&quot;)</code></p>
  <p id="aT5C"><code>redTeam.Name = &quot;Красные&quot;</code></p>
  <p id="ICnq"><code>redTeam.TeamColor = BrickColor.Red()</code></p>
  <p id="WSYP"><code>redTeam.Parent = game:GetService(&quot;Teams&quot;)</code></p>
  <p id="aw4g"><code>local blueTeam = Instance.new(&quot;Team&quot;)</code></p>
  <p id="1SXv"><code>blueTeam.Name = &quot;Синие&quot;</code></p>
  <p id="PlJX"><code>blueTeam.TeamColor = BrickColor.Blue()</code></p>
  <p id="KeDC"><code>blueTeam.Parent = game:GetService(&quot;Teams&quot;)</code></p>
  <h3 id="DHDu">Шаг 2: Распределение игроков</h3>
  <p id="vpLB"><code>game.Players.PlayerAdded:Connect(function(player)<br />    if #redTeam:GetPlayers() &lt;= #blueTeam:GetPlayers() then<br />        player.Team = redTeam<br />    else<br />        player.Team = blueTeam<br />    end<br />end)</code></p>
  <h3 id="4q9l">Шаг 3: Система очков за убийства</h3>
  <p id="vIxH"><code>-- Добавим лидерборд<br />game.Players.PlayerAdded:Connect(function(player)<br />    local leaderstats = Instance.new(&quot;Folder&quot;)<br />    leaderstats.Name = &quot;leaderstats&quot;<br />    leaderstats.Parent = player</code></p>
  <p id="A76i"><code>    local kills = Instance.new(&quot;IntValue&quot;)<br />    kills.Name = &quot;Убийства&quot;<br />    kills.Value = 0<br />    kills.Parent = leaderstats<br />end)</code></p>
  <p id="hWdV"><code>— Обработка убийств<br />workspace.Debris.ItemSpawned:Connect(function(part)<br />    if part:IsA(&quot;Humanoid&quot;) then<br />        part.Died:Connect(function()<br />            local killer = part.Killer<br />            if killer then<br />                local value = killer:FindFirstChild(&quot;leaderstats&quot;) and killer.leaderstats:FindFirstChild(&quot;Убийства&quot;)<br />                if value then<br />                    value.Value += 1<br />                end<br />            end<br />        end)<br />    end<br />end)</code></p>
  <hr />
  <h2 id="ritQ">18.6 — Чат и сообщения между игроками</h2>
  <p id="iPXY">Roblox имеет встроенный чат. Также можно добавлять свои функции, например, команды в чате.</p>
  <h3 id="ynaM">Пример: команда <code>/team</code></h3>
  <p id="iBMn"><code>game.Players.PlayerAdded:Connect(function(player)<br />    player.Chatted:Connect(function(message)<br />        if message:sub(1, 6) == &quot;/team&quot; then<br />            local teamName = message:sub(7)<br />            local team = game.Teams:FindFirstChild(teamName)<br />            if team then<br />                player.Team = team<br />                print(player.Name .. &quot; присоединился к команде &quot; .. team.Name)<br />            else<br />                print(&quot;Команда не найдена.&quot;)<br />            end<br />        end<br />    end)<br />end)</code></p>
  <hr />
  <h2 id="s6DO">18.7 — Работа с таблицами игроков</h2>
  <p id="bRJV">Иногда нужно хранить данные о всех игроках.</p>
  <p id="9gJB"><code>local activePlayers = {}</code></p>
  <p id="04vq"><code>game.Players.PlayerAdded:Connect(function(player)<br />    activePlayers[player] = true<br />    print(&quot;Текущие игроки:&quot;, table.count(activePlayers))<br />end)</code></p>
  <p id="xKl3"><code>game.Players.PlayerRemoving:Connect(function(player)<br />    activePlayers[player] = nil<br />    print(&quot;Текущие игроки:&quot;, table.count(activePlayers))<br />end)</code></p>
  <hr />
  <h2 id="BrVJ">18.8 — Советы по работе с мультиплеером</h2>
  <ul id="JtWg">
    <li id="hKZp">Используй <code>RemoteEvent</code> для связи между клиентом и сервером.</li>
    <li id="JeJp">Не доверяй данным от клиента — всегда проверяй их на сервере.</li>
    <li id="TPtv">Используй <code>leaderstats</code> для отображения данных.</li>
    <li id="3iYN">Тестируй игру с несколькими аккаунтами.</li>
    <li id="pjfa">Используй <code>DataStore</code> для сохранения прогресса.</li>
  </ul>
  <hr />
  <h2 id="aWbW">18.9 — Ключевые термины</h2>
  <p id="ZXVO">Термин - Описание</p>
  <p id="OEdT">Players - Сервис для работы с игроками</p>
  <p id="VFPc">Team - Команда, к которой относится игрок</p>
  <p id="nMmb">Chatted - Событие при вводе сообщения в чате</p>
  <p id="MrQ3">RemoteEvent - Передача данных от клиента к серверу</p>
  <p id="YkhF">leaderstats - Отображение статистики игрока</p>
  <p id="68hQ">Humanoid - Управление здоровьем и смертью</p>
  <p id="y0dE">Died - Событие смерти персонажа</p>
  <p id="VitB">Killer - Игрок, который нанёс финальный урон</p>
  <p id="rYDa"></p>
  <h1 id="5Ghl">🔹 Глава 19: Оптимизация и производительность.</h1>
  <hr />
  <h2 id="v3Tz">Введение</h2>
  <p id="LYJq">В этой главе ты узнаешь:</p>
  <ul id="6bcJ">
    <li id="mq6r">Как улучшить производительность игры.</li>
    <li id="2jTC">Что влияет на FPS и загрузку сервера.</li>
    <li id="tpkk">Как правильно управлять объектами, событиями и памятью.</li>
    <li id="jiuk">Как использовать инструменты Roblox для анализа.</li>
    <li id="Gre3">Как избежать лагов, вылетов и багов при большом количестве игроков.</li>
  </ul>
  <hr />
  <h2 id="c3qw">19.1 — Почему важна оптимизация?</h2>
  <p id="a5Fu">Когда игра становится популярной, она может одновременно запускаться у сотен или тысяч игроков. Без оптимизации это приведёт к:</p>
  <ul id="DsWn">
    <li id="6q9M">Падению FPS</li>
    <li id="eJSx">Задержкам</li>
    <li id="ax0F">Крахам сервера</li>
    <li id="6iHs">Плохому опыту игрока</li>
  </ul>
  <h3 id="oL1b">Цели оптимизации:</h3>
  <ul id="Yln4">
    <li id="AK5R">Увеличение FPS</li>
    <li id="QmCn">Снижение нагрузки на сервер</li>
    <li id="PEy1">Более стабильная работа</li>
    <li id="Mart">Меньше потребление ресурсов</li>
  </ul>
  <hr />
  <h2 id="uqv1">19.2 — Использование инструментов диагностики</h2>
  <p id="vfry">Roblox Studio предоставляет мощные инструменты для отладки:</p>
  <h3 id="WR33">🔍 Performance Stats</h3>
  <ul id="M2lc">
    <li id="1mVa">Открой <strong>View → Output</strong></li>
    <li id="0kKn">Перейди в <strong>Performance </strong>(вкладка)</li>
    <li id="FJKd">Следи за:</li>
    <ul id="bT8E">
      <li id="VKUl">Physics Heartbeat</li>
      <li id="hJDI">Network Heartbeat</li>
      <li id="ZZwk">Garbage Collection Time</li>
    </ul>
  </ul>
  <h3 id="tssJ">📈 Memory Usage</h3>
  <ul id="m50y">
    <li id="mbmC">Открой <strong>Script Editor → Tools → Memory Usage</strong></li>
    <li id="Vt0c">Проверяй, не происходит ли утечки памяти.</li>
  </ul>
  <hr />
  <h2 id="NzUk">19.3 — Управление объектами</h2>
  <p id="KIVk">Создание и удаление объектов — дорогостоящая операция. Вот как сделать это эффективнее:</p>
  <h3 id="97FT">❌ Плохо: Создание объекта каждый раз</h3>
  <p id="38g6"><code>while true do<br />    local part = Instance.new(&quot;Part&quot;)<br />    part.Parent = workspace<br />    wait(0.1)<br />    part:Destroy()<br />end</code></p>
  <h3 id="VHgR">✅ Хорошо: Переиспользование объекта</h3>
  <p id="iNUp"><code>local part = Instance.new(&quot;Part&quot;)<br />part.Anchored = true<br />part.Parent = workspace</code></p>
  <p id="zksz"><code>while true do<br />    part.Position = Vector3.new(math.random(-10, 10), 5, math.random(-10, 10))<br />    wait(0.1)<br />end</code></p>
  <hr />
  <h2 id="fVx6">19.4 — Оптимизация скриптов</h2>
  <h3 id="oSy6">Не используй бесконечные циклы без <code>wait()</code></h3>
  <p id="kaO4">Бесконечный цикл без задержки может заблокировать игру.</p>
  <p id="DLoT"><code>-- ❌ НЕПРАВИЛЬНО<br />while true do<br />    -- делаем что-то<br />end</code></p>
  <p id="tmDv"><code>--✅ ПРАВИЛЬНО<br />while true do<br />    -- делаем что-то<br />    wait(0.1)<br />end</code></p>
  <h3 id="Xl8L">Избегай частых вызовов <code>GetService()</code> и <code>FindFirstChild()</code></h3>
  <p id="kXv0"><code>-- ❌ Вызов внутри цикла — медленно<br />for _, player in ipairs(game:GetService(&quot;Players&quot;):GetPlayers()) do<br />    -- ...<br />end</code></p>
  <p id="g9hF"><code>-- ✅ Вызов один раз — быстро<br />local players = game:GetService(&quot;Players&quot;):GetPlayers()<br />for _, player in ipairs(players) do<br />    -- ...<br />end</code></p>
  <hr />
  <h2 id="Kfh3">19.5 — Работа с событиями</h2>
  <p id="lz3K">Подписка на события — полезная, но опасная вещь, если делать это бездумно.</p>
  <h3 id="i0XX">Подписывайся только когда нужно</h3>
  <p id="e8lu"><code>player.CharacterAdded:Connect(function(char)<br />    char.Humanoid.Died:Connect(onPlayerDied)<br />end)</code></p>
  <h3 id="JTz1">Удаляй обработчики, когда они больше не нужны</h3>
  <p id="b993"><code>local connection = game.Players.PlayerAdded:Connect(function(player)<br />    print(player.Name .. &quot; зашёл&quot;)<br />    connection:Disconnect()<br />end)</code></p>
  <hr />
  <h2 id="9sRp">19.6 — Оптимизация физики и движений</h2>
  <p id="eBKS">Физика — одна из самых тяжёлых частей игры.</p>
  <h3 id="ugsX">Используй <code>BodyMovers</code> с умом</h3>
  <p id="DWnB"><code>-- Лучше уничтожать BodyMover после использования</code></p>
  <p id="Ig7o"><code>local bodyPos = Instance.new(&quot;BodyPosition&quot;)</code></p>
  <p id="g96X"><code>bodyPos.Parent = part</code></p>
  <p id="aaYJ"><code>-- ... выполняем действие ...</code></p>
  <p id="n7ZE"><code>bodyPos:Destroy()</code></p>
  <h3 id="Pa6h">Избегай множества <code>Touched</code> событий</h3>
  <p id="fBlI"><code>-- ❌ Для каждой части отдельное событие<br />part.Touched:Connect(function(hit) end)</code></p>
  <p id="C2cL"><code>-- ✅ Используй один детектор столкновений<br />workspace.Changed:Connect(function(part)<br />    if part:IsA(&quot;BasePart&quot;) then<br />        part.Touched:Connect(function(hit) end)<br />    end<br />end)</code></p>
  <hr />
  <h2 id="PZI0">19.7 — Проект: Система пулов объектов</h2>
  <p id="laxN">Создадим систему пула объектов — механизм, который переиспользует объекты вместо постоянного создания новых.</p>
  <p id="r08R"><code>-- PoolManager.lua<br />local pool = {}</code></p>
  <p id="WHTR"><code>function createPoolItem()<br />    local part = Instance.new(&quot;Part&quot;)<br />    part.Anchored = true<br />    part.Size = Vector3.new(1, 1, 1)<br />    part.Transparency = 0.5<br />    return part<br />end</code></p>
  <p id="EIlQ"><code>function spawnFromPool()<br />    for i, part in ipairs(pool) do<br />        if not part.Parent then<br />            part.Parent = workspace<br />            return part<br />        end<br />    end</code></p>
  <p id="EBxZ"><code>    local newPart = createPoolItem()<br />    newPart.Parent = workspace<br />    table.insert(pool, newPart)<br />    return newPart<br />end</code></p>
  <p id="Dile"><code>— Пример использования<br />while true do<br />    local part = spawnFromPool()<br />    part.CFrame = CFrame.new(math.random(-10, 10), 5, math.random(-10, 10))<br />    wait(1)<br />    part.Parent = nil<br />end</code></p>
  <hr />
  <h2 id="RK19">19.8 — Советы по оптимизации</h2>
  <p id="HTuW">Тема - Совет</p>
  <p id="ohpM">Объекты - Используй пулы, а не создание/удаление</p>
  <p id="JlVZ">События - Подписывайся только тогда, когда нужно</p>
  <p id="SpcQ">Физика - Минимизируй использование<code>Touched</code>,<code>BodyMovers</code></p>
  <p id="zYcv">Память - Удаляй лишние объекты и таблицы</p>
  <p id="2lsc">GUI - Используй<code>GuiObject.Visible</code>вместо удаления</p>
  <p id="iN0o">DataStore - Не делай слишком много запросов за короткий срок</p>
  <p id="yD0W">RemoteEvents - Фильтруй данные, проверяй доступ</p>
  <p id="vH5F">Анимации - Используй кэшированные треки</p>
  <hr />
  <h2 id="WH1M">19.9 — Ключевые термины</h2>
  <p id="BCJK">Термин - Описание</p>
  <p id="ubB5">FPS - Кадры в секунду</p>
  <p id="J2zy">Garbage Collector - Сборщик мусора Lua</p>
  <p id="Ikm5">Pool - Пул объектов для повторного использования</p>
  <p id="txX7">Touched - Событие прикосновения</p>
  <p id="eAlw">Changed - Событие изменения свойства</p>
  <p id="g0e9">BodyMovers - Объекты для физического движения</p>
  <p id="YHlw">RemoteEvent - Событие между клиентом и сервером</p>
  <p id="GvmZ">Memory Leak - Утечка памяти</p>
  <p id="asjw">Event Connection - Подписка на событие</p>
  <p id="Ajr1"></p>
  <h1 id="p9Z1">📘 Заключение</h1>
  <h2 id="lhzi">Ты прошёл(а) долгий путь</h2>
  <p id="OUT2">Поздравляем с завершением этой книги — ты не просто изучил(а) основы программирования на Lua в Roblox, но и углубился(ась) в реальные практические задачи:</p>
  <ul id="SCiJ">
    <li id="lWdY">Создавал(а) интерфейс (GUI)</li>
    <li id="UbJt">Работал(а) с событиями, игроками и персонажами</li>
    <li id="yKNh">Управлял(а) анимацией, физикой и звуком</li>
    <li id="lzrZ">Писал(а) клиент-серверный код</li>
    <li id="C0Z1">Сохранял(а) данные с помощью DataStore</li>
    <li id="8jsL">Изучил работу с JSON и HTTP</li>
    <li id="hwyy">Создавал(а) свои плагины для Roblox Studio</li>
    <li id="iaHC">Оптимизировал(а) игру и повышал(а) её производительность</li>
  </ul>
  <p id="POJG">Ты уже не новичок — ты полноценный разработчик игр на платформе Roblox.</p>
  <hr />
  <h2 id="R9qc">Игра — это лишь начало</h2>
  <p id="dCDi">Создание игры — это первый шаг. За этим следует:</p>
  <ul id="2fl4">
    <li id="ZVQc"><strong>Тестирование и отладка</strong></li>
    <li id="QqRr"><strong>Публикация и продвижение</strong></li>
    <li id="hSij"><strong>Обратная связь от игроков</strong></li>
    <li id="leec"><strong>Развитие и обновления</strong></li>
  </ul>
  <p id="YoZy">Все великие игры начинались с простых идей. Возможно, именно ты создашь следующую хитовую игру, которую оценят миллионы игроков.</p>
  <hr />
  <h2 id="uy47">Что делать дальше?</h2>
  <p id="fed3">Ты можешь: ✅ Продолжить развиваться как разработчик: создавать всё более сложные механики и системы<br />✅ Сделать открытый проект и собрать сообщество вокруг своей игры<br />✅ Начать зарабатывать внутри Roblox через Robux и Premium<br />✅ Создать свой плагин или инструмент для других разработчиков</p>
  <hr />
  <h2 id="3Wuz">Благодарность</h2>
  <p id="9B9i">Большое спасибо, что выбрал(а) эту книгу для изучения программирования в Roblox.<br />Ты не просто читатель — ты <strong>разработчик будущего</strong>.<br />Платформа Roblox — это не просто место для игр, это целая вселенная возможностей, где ты можешь:</p>
  <p id="mRkn">🎮 Играть<br />🛠 Создавать<br />💡 Вдохновлять<br />📈 Развиваться<br />💰 Зарабатывать</p>
  <hr />
  <h2 id="Bb28">Давай создадим что-то великое!</h2>
  <p id="ezi5">Теперь у тебя есть знания, чтобы сделать свою первую полноценную игру. Не бойся ошибок — они часть пути. Не бойся экспериментировать — именно так рождаются шедевры.</p>
  <p id="MG01"><strong>Твой первый успех уже рядом.</strong><br /><strong>Твоя первая игра ждёт тебя.</strong><br /><strong>История начинается с тебя.</strong></p>
  <hr />
  <p id="VF2k">🎉 <strong>Удачи тебе в мире разработки игр!</strong></p>

]]></content:encoded></item></channel></rss>