Roblox — Создание машины — make car.

Автор: | 9 марта, 2025
Поделиться...

Как недавно оказалось, что столь интересной задачи как создание транспорта, я в личном блоге не отразил.

Автомобили тема интересная и надо будет её сюда перенести. Чем и займусь…

Актуальность — Сентябрь 2023

Поступила мне задачка — сделать гонки на картингах. Но есть проблема, последний раз я занимался созданием авто года два-три назад. Много воды утекло и… теперь авто создаются совсем по другому.

Посмотрев разные гайды и видосы, пришёл к не утешительному выводу — они морально устарели и не соответствуют текущим реалиям. Единственное, что почти сразу удалось адаптировать, с небольшими изменениями, это данное видео 5. Человек хорошо рассказывает, разбирает большинство возникающих проблем. Т.е. разжёвывает что и почему делается. На основе данного видео и будет этот гайд.

Сперва, сделаем почти так же, возьмём из тулбокса модель авто у которой цельный корпус, но можно оторвать колёса. Или просто найдите мэш авто без колёс. На худой конец — обычный парт нужного размера тоже сойдёт.

Как выяснилось, я взял проблемную модель. на скриншоте можно видеть что стало, после того как я его разместил в позиции 0,0,0 с ориентацией 0,0,0. Так получилось, потому что в 3Д редакторе его забыли сориентировать перед экспортом.

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

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

Немного посмотрев на оставшееся, я пришёл к выводу, что нам ещё можно немного поколдовать над моделью, чтобы осталось минимум деталей.

В итоге у нас остались модели корпуса и колёс. Заодно и проверю на модельках вместо партов.

Задаём PrimaryPart для модели авто на MESH корпуса и ориентируем авто по оси Z. Собственно ориентация не особо важна, это просто чтобы было легче копировать.

Переименую колёса чтобы не было пробелов и было легче писать и можно сказать, что наша моделька подготовлена к оживлению.
Но запустив игру на исполнение, обнаружился нежданчик. И даже два.

  1. У машины отключены столкновения
  2. Размер авто не рассчитан на размер RTHRO персонажа.

Так что растягиваем модель и включаем у всех мешей CanCollide:

Берём наши колёса и выдвигаем их в стороны. Сейчас мы будем их крепить к модели.

Нам нужно создать аттачи на корпусе. Но как выяснилось это не возможно на модели. Так что переименовываем наш PrimaryPart и задаём в нём четыре Attachment и их так же переименовываем под наши колёса.

Тут нам и пригодится то, что у нас машина отцентрирована по нулям. Располагаем аттачи чуть выше места крепления колёс.
FL — Front Left — перед лево
BR — Back Right — зад право
А чтобы их было видно, то на вкладке Model нужно включить Constraint Details

На этом шаге выяснилось что у моделей колёс уже установлен PrimaryPart. Но вот только в одном колесе меши имели собственное название. Так что изначально переименовываем их в одинаковый набор. И только потом в указанный PrimaryPart (у меня это Tire) добавляем ещё аттачи. Но вот их то как раз переименовывать не будем. И менять их положение тоже не будем, пусть будут в центре модели. Если понадобится подвинуть колёса, мы это сделает предыдущими аттачами.

Ну что же. Пришла пора их соединить. Для этого добавляем CylindricalConstraint в пару к новым аттачам. И в нём указываем первым аттачем тот что в шасси, а вторым тот что тут же находится.

Запускаем и… ничего не происходит. Потому что модель закреплена. Отключаем все Ancored. Можно просто выделить модель и нажать Anchor.

О боже! Наша моделька рассыпалась. Всё просто. После того как мы сняли якорь, то в режиме исполнения все части подвергаются физике по отдельности, а не как нечто цельное. Чтобы это исправить, нужно их сцепить. В этом нам поможет Weld:

То же делаем и с остальными осыпающимися частями. Предварительно можно поднять модель повыше и заякорить шасси.

Проделав всё это и запустив игру видим интересную картинку:

Из неё следует вывод — надо сделать чтобы колёса и шасси не сталкивались друг с другом. Потому что это ещё и будет мешать рулить!

Опять же на вкладке Model открываем Collision Group, переводим в Table View и добавляем 2 группы — Car и Wheel. После отключаем их столкновение между собой. Ну и добавляем Body в Car, а Wheel в Wheel. Целиком моделями — выделяем нужную модель и жмём плюсик у названия группы.

После запуска видим, что колёса болтаются, и даже куда-то двигаются… Только не туда, куда нам надо.

Для начала сменим направление движения, повернув главные аттачи на 90 градусов.

Теперь ограничим разбег, установив границы от -2 до -1. Это будет играль роль… амортизаторов.

Теперь у нас колёса не падают и никуда не улетают. Но… крутятся не по той оси.

Поигравшись с ориентацией аттачей, таки получил нужный результат. Колёса стоят как надо и крутятся тоже куда надо.

AttachmentFL = 0,90,90
Attachment = 0,0,90

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

Можно бы переходить к скриптам. И начнём с банального — нам надо сесть за руль! Поэтому добавим сиденью промпт, который за это и будет отвечать.

local seat = script.Parent	-- указатель на сиденье водителя

-- сигнал что кто-то сел или встал с сиденья
seat:GetPropertyChangedSignal("Occupant"):Connect(function()
	if seat.Occupant == nil then
		seat.ProximityPrompt.Enabled = true
	else
		seat.ProximityPrompt.Enabled = false
	end
end)

-- активация промпта
seat.ProximityPrompt.Triggered:Connect(function(player)
	seat:Sit(player.Character.Humanoid)
end)

И настроем сам промпт, чтобы он соответствовал нашим запросам:

Запустив мы ничего не увидим, потому как забыли прицепить сиденья к корпусу. Делаем для них Weld и…вот мы уже и в кабине!

Добавим Attachment в кресло и вытащим его за пределы авто. Это будет место, куда мы будем выпрыгивать из машины.

У кресла водителя нас будут интересовать лишь несколько значений.
MaxSpeed — максимальная скорость.
Torque — крутящий момент
TurnSpeed — угловая скорость
Для примера выставляем указанные параметры:

Steer и SteerFloat — это усилие для поворота руля
Throtle и ThrotleFloat — это усиление для изменения скорости (газ/тормоз)

Добавляем в модель скрипт.

-- для ровного поворота руля
local TS = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(0.4)

-- рулевые направляющие
local BR = script.Parent.Body.Chassee.AttachmentBR
local BL = script.Parent.Body.Chassee.AttachmentBL
local FR = script.Parent.Body.Chassee.AttachmentFR
local FL = script.Parent.Body.Chassee.AttachmentFL

-- колёса
local WBR = script.Parent.Wheels.BR.Tire.CylindricalConstraint
local WFR = script.Parent.Wheels.FR.Tire.CylindricalConstraint
local WBL = script.Parent.Wheels.BL.Tire.CylindricalConstraint
local WFL = script.Parent.Wheels.FL.Tire.CylindricalConstraint

-- сиденье
local seat = script.Parent.DriveSeat
-- кто сидит
local ocupant = nil
-- выход
local exit = nil

local maxAngular = seat.MaxSpeed / (WBR.Parent.Size.Y / 2)
connect = seat.Changed:Connect(function(param)
--	print(seat.Occupant)
	if param == "Occupant" then
		if seat.Occupant ~= nil then
			ocupant = seat.Occupant
			exit = seat:FindFirstChildOfClass("Attachment")
			if ocupant then	-- передача преимущества управления сетью игроку
				local player = game.Players:GetPlayerFromCharacter(ocupant.Parent)
				if player then
					seat:SetNetworkOwner(player)
				end
			else
				seat:SetNetworkOwnershipAuto()
			end
		end
		if seat.Occupant == nil and ocupant ~= nil and ocupant.Parent ~= nil then
			if exit == nil then return end
			seat:SetNetworkOwnershipAuto()		-- отмена приоритета
			local character = ocupant.Parent	-- 
			task.wait()							-- дать возможность отцепиться персу от сиденья
			character:PivotTo(exit.WorldCFrame)	-- выкинуть перса из машины
			exit = nil
			return
		end
	end
	-- поворот
	if param == "SteerFloat" then		
		-- ориентация от FL
		local orient = Vector3.new(0, -seat.SteerFloat * seat.TurnSpeed +90, 90)
		TS:Create(FL, tweenInfo, {Orientation = orient}):Play()
		TS:Create(FR, tweenInfo, {Orientation = orient}):Play()
	end
	-- газ
	if param == "ThrottleFloat" then
		local torque = math.abs(seat.ThrottleFloat) * seat.Torque
		if torque == 0 then
			torque = 2000
		end
		-- ведущий мост задний 
		local angular = math.sign(seat.ThrottleFloat) * maxAngular
		WBL.MotorMaxTorque = torque
		WBR.MotorMaxTorque = torque
		WBL.AngularVelocity = angular
		WBR.AngularVelocity = angular
	end
end)

Всё хорошо, вроде бы. Руль поворачивается, но машина не едет… Я просто забыл добавить движитель…

Немножко можно поднастроить физику. Активируем CustomFisicalProperties, раскроем:
Density — коэффициент веса. Поставим там значение поменьше и увидим что Mass внизу уменьшился.

На колёсах можно изменить жёсткость сцепления Elasticity.

Запускаем и катаемся!

Ещё много чего можно сделать… Например добавить ресоры, озвучку, освещение, приборы, первую помощь от переворотов, посадку пассажиров и т.д. и т.п.

А раз принцип понятен — едем в рассвет!

https://www.youtube.com/watch?v=JgBhFG4TILQ&list=PLGGdAUTrNbI9rMOBX9yzc_jot2oHxPwc6&index=14


Поделиться...

Roblox — Создание машины — make car.: 1 комментарий

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *