พัฒนาโลกที่เคลื่อนไหว

*เนื้อหานี้แปลโดยใช้ AI (เวอร์ชัน Beta) และอาจมีข้อผิดพลาด หากต้องการดูหน้านี้เป็นภาษาอังกฤษ ให้คลิกที่นี่

การสร้างการเคลื่อนไหวในสภาพแวดล้อมใดๆ ภายในประสบการณ์ช่วยให้รู้สึกเหมือนจริงและสมจริงมากขึ้นในโลกของเราทันที ไม่ว่าจะเป็นจากการเคลื่อนไหวของต้นไม้ในสภาพแวดล้อม ประตูที่ตอบสนองจากการโต้ตอบของผู้เล่น หรือแม้แต่กล่องที่เคลื่อนที่เมื่อชนกับพวกมันสตูดิโอมีวิธีการที่ไม่ซ้ำกันมากมายในการสร้างการเคลื่อนไหวเพื่อช่วยให้โลกรู้สึกมีชีวิตมากขึ้น รวมถึงระบบฟิสิกส์ TweenService และแอนิเมชัน และการวิเคราะห์ความต้องการเฉพาะของประสบการณ์ของคุณสามารถช่วยคุณกำหนดได้ว่าควรใช้อันไหนในส่วนนี้เราจะแสดงวิธีที่เรากำหนดประเภทการเคลื่อนไหวที่เราต้องการสร้างใน Studio และเครื่องมือที่เราใช้เพื่อบรรลุเป้าหมายที่แตกต่างกัน

สร้างพายุ

พายุผ่านหลายรอบก่อนที่เราจะตกลงกับสิ่งที่มีอยู่ในความลับของ Duvall Driveตอนแรกเราคิดเกี่ยวกับพายุเป็นเสาหินออบซิเดียนยักษ์ และในการเลือกรุ่นต่อมาเราคิดว่ามันเป็นพอร์ทัลยักษ์ไปยังพื้นที่ที่เสียหายหลังจากทดลองกับพายุหลายแบบที่มีลักษณะและความรู้สึกที่แตกต่างกันมาก เราตกลงกับพายุที่มี "ดวงตา" กลางเล็กกว่าเพราะ:

  • พายุควรให้ผู้เล่นรู้สึกถึงผลกระทบของเหตุการณ์นี้ต่อโลก รวมถึงต้นไม้ที่พัดและเศษซากบินไปรอบๆ * กระแสวายุหมุนของเมฆเองควรให้ผู้เล่นมองดูที่พอร์ทัลกลาง โดยไม่เปิดเผยทุกอย่าง สิ่งนี้จะส่งเสริมให้ผู้เล่นสำรวจใกล้ชิดเพื่อดูสิ่งที่เกิดขึ้น
  • จุดที่แคบกว่าของแสงจะช่วยให้เราสามารถ โฟกัสไปที่การจัดวางของบ้าน ซึ่งเป็นทั้งตัวละครหลักและสถานที่ที่เกมส่วนใหญ่อยู่

เพื่อทำให้พายุรู้สึกมีพลัง ก้าวร้าว และเปลี่ยนแปลงตลอดเวลาภายในสภาพแวดล้อมของมัน เราใช้ระบบและคุณลักษณะต่อไปนี้:

  1. TweenService - สำหรับการเคลื่อนย้ายบนคลาวด์
  2. การเปลี่ยนแปลงแสง - สำหรับการสร้างเมฆสู่สายฟ้าความเร็วสูง
  3. ลําแสง - สําหรับ "แสงภูมิศาสตร์" และสายฟ้า
  4. ตัวปล่อยอนุภาค - สำหรับเศษซากที่บินขึ้นไปยังพอร์ทัลและบินไปรอบๆ เนื่องจากลมพัด
  5. แอนิเมชั่น - สำหรับต้นไม้ที่พัดในลม

เพิ่มเมฆด้วยเทกเจอร์

ในขณะที่ เมฆไดนามิก เหมาะสำหรับเมฆที่เป็นจริงในระดับความสูงปกติและสูง เราต้องการบางอย่างที่รู้สึกดราม่าและที่เราสามารถเน้นและปรับแต่งได้มากขึ้นเพื่อทำเช่นนี้ เราใช้วัตถุ ปรากฏบนพื้นผิว ที่มีความโปร่งใสเล็กน้อยกับชุดเมชของเมฆที่ซ้อนทับและซ้อนกันหลายชั้นเพื่อสร้างการปกคลุมเมฆปลอมทำไมเราถึงซ้อนพวกเขาและวางพวกเขาอย่างหนัก? เพราะเมื่อเมชของเมฆแต่ละอันเคลื่อนที่ด้วยความเร็วที่แตกต่างกันพวกเขาจะสัมผัสและสร้างรูปแบบเมฆที่ไปภายในและออกจากกันกระบวนการนี้ทำให้เมฆรู้สึกเป็นไปได้มากขึ้นและเป็นธรรมชาติมากขึ้น แม้ว่าจะเป็นแผ่นหมุนเพียงเล็กน้อยก็ตามสิ่งสำคัญคือเมฆต้องมีความโปร่งใส ครึ่งหนึ่ง เพราะเราต้องการให้ผู้เล่นสามารถมองเห็นสิ่งที่สดใสอยู่ในศูนย์กลางก่อนที่จะมาถึงบ้าน!

เมทช์เมฆเดียว
เมชคลาวด์หลายชั้นโดยไม่มีเทกเจอร์ของพวกเขา!

เนื่องจากแต่ละเมทริกซ์เมฆจำเป็นต้องมีขนาดใหญ่เพื่อล้อมรอบบ้านและสื่อสารถึงความยิ่งใหญ่ของพายุที่เกิดขึ้น เราจึงรู้ว่าเราจำเป็นต้องปูพื้นเมทริกซ์ที่เราต้องการใช้บนเมทริกซ์เมฆแต่ละอันเพื่อให้มันทำซ้ำอย่างหนักทั่วพื้นผิวของเมทริกซ์เราทดสอบวัสดุที่เราสร้างสําหรับเมฆบนชิ้นส่วนง่ายๆเหล่านี้แล้วนําไปใช้กับ vortex!

ไม่เหมือนกับตัวปล่อยอนุภาคหรือลําแสง เราสามารถส่งแสงกระเด้งออกจากแต่ละเมชได้ ซึ่งเป็นสิ่งสําคัญเมื่อเราต้องการใช้การสายฟ้าแลบระหว่างเมฆเรายังโมเดลในการหมุนเพื่อให้แสงเด้งออกจากมันดูเหมือนว่ามันมีความลึก! ซึ่งเป็นสิ่งสำคัญโดยเฉพาะอย่างยิ่งในสถานการณ์ที่ความต้องการด้านประสิทธิภาพของประสบการณ์ทำให้ระดับคุณภาพของรูปลักษณ์พื้นผิวของเราลดลง

เมื่อเราเริ่มเพิ่มแสงให้กับมันแล้ว เราจำเป็นต้องเพิ่มรายละเอียดให้กับเมชเพื่อให้พวกเขาตอบสนองต่อแสงได้ดีขึ้น!

หมุนเมชคลาวด์

หลังจากที่เราพอใจกับรูปลักษณ์ทั่วไปของเมฆแล้ว เราต้องการให้มันเคลื่อนไหว! เรามีรูปร่างทั่วไปของแต่ละชั้นเมฆอยู่แล้ว แต่ต้องใช้การทดลองและผิดพลาดเพื่อให้แน่ใจว่าเอฟเฟกต์การหมุนดูดีในการใช้งานเราพยายามใช้ ข้อจํากัด ในตอนแรกเพื่อแนะนำความเร็วที่จะขับเคลื่อนเมฆได้กายภาพนี่ยากกว่าที่เราต้องการให้มันทำซ้ำในภายหลังและผู้เล่นจะไม่มีวันโต้ตอบกับมันดังนั้นเราจึงไม่จำเป็นต้องให้มันถูกต้องในการเคลื่อนที่

เราต้องการวิธีที่ใช้งานง่ายในการหมุนติดต่อระหว่างตัวอย่างที่อยู่ไกลเกินไปที่จะโต้ตอบได้ เช่น เมฆ หรือเล็กเกินไปที่จะเป็นสิ่งสำคัญสำหรับเกม/ฟิสิกส์ เช่น เฟอร์นิเจอร์ภายในบ้านเช่นโคมไฟขนาดเล็กเราตัดสินใจที่จะใช้ LocalScript เพื่อลดความถี่ของการสื่อสารระหว่างไคลเอนต์และเซิร์ฟเวอร์ อนุญาตให้มีการเคลื่อนไหวที่ราบรื่นขึ้น และให้แต่ละเมชของเมฆมีอัตราการหมุนและความล่าช้าที่แตกต่างกันเพื่อให้มันเป็นทั่วไปมากขึ้น เรายังทำให้เป็นไปได้ที่จะระบุแกนการหมุนมันเป็นไปได้ที่จะใช้ 3 คุณสมบัติ แต่สำหรับกรณีของเราเราใช้ 3 ค่า: Axis , Delay และ Speed

เช่นเดียวกับในหลายกรณีในการสาธิต เราใช้แท็ก LocalSpaceRotation เพื่อให้เราสามารถจัดการตัวอย่างที่ได้รับผลกระทบใน Studio โดยใช้ปลั๊กอินการจัดประเภทตัวอย่างเราใช้เพียงหนึ่ง LocalScript ที่จัดการกับตัวอย่างทั้งหมดที่มีป้ายกำกับโดยใช้ CollectionService ดังนั้นเราจึงไม่มีสคริปต์จํานวนมากที่ต้องรักษาตลอดกระบวนการพัฒนา

ในการสาธิตของเราส่วนต่างๆของโลกจะถูกโคลนจาก ServerStorage ในพื้นที่ทำงานตามที่จำเป็นดังนั้นเราจึงต้องจัดการกรณีที่วัตถุที่มีป้ายชื่อถูกสร้างและทำลายด้วย LocalScripts เรายังต้องตระหนักถึงการสตรีมที่เมชและมูลค่าลูกของพวกเขาอาจถูกสตรีมเข้าและออกเราประมวลผลวัตถุที่วางไว้เดิมในฟังก์ชัน Init() และเชื่อมต่อกับ CollectionService.GetInstanceAddedSignal และ CollectionService.GetInstanceRemovedSignal สำหรับวัตถุที่มีแท็กเพื่อจัดการวัตถุที่สร้างขึ้นใหม่/ถูกทำลายฟังก์ชันเดียวกัน SetupObj ถูกใช้เพื่อเริ่มต้นวัตถุใหม่ใน Init() และใน CollectionService.GetInstanceAddedSignal


local function Init()
for _, obj in CollectionService:GetTagged("LocalSpaceRotation") do
if obj:IsDescendantOf(workspace) then
SetupObj(obj)
end
end
end
CollectionService:GetInstanceAddedSignal("LocalSpaceRotation"):Connect(function(obj)
objInfoQueue[obj] = true
end)
CollectionService:GetInstanceRemovedSignal("LocalSpaceRotation"):Connect(function(obj)
if objInfo[obj] then
objInfo[obj] = nil
if objInfoQueue[obj] then
objInfoQueue[obj] = nil
end
end
end)
Init()

objInfo เป็นแผนที่ที่มีข้อมูลสำหรับวัตถุทั้งหมดที่เกี่ยวข้อง เช่น ความเร็วในการหมุนและแกนโปรดทราบว่าเราไม่ได้เรียก SetupObj จาก CollectionService.GetInstanceAddedSignal ทันที แต่เราเพิ่มวัตถุลงใน objInfoQueueเมื่อเรียกวัตถุสตรีมและโคลนบนเซิร์ฟเวอร์แล้ว เมื่อ CollectionService.GetInstanceAddedSignal ถูกเรียก เราอาจยังไม่มีค่า Axis และ Delay และ Speed ของเรา ดังนั้นเราจึงเพิ่มวัตถุลงในคิวและเรียก SetupObj ในเฟรมต่อไปจากฟังก์ชัน Update จนกว่าค่าจะอยู่และเราสามารถอ่านค่าไปยังโครงสร้าง "ข้อมูล" ของแต่ละวัตถุได้

เราหมุนตัวอย่างในฟังก์ชัน Update ที่เชื่อมต่อกับการเต้นของหัวใจเราได้รับพาร์ทเนอร์ทรานสฟอร์ม (parentTransform) สะสมมุมหมุนใหม่ ( curObjInfo.curAngle ) ขึ้นอยู่กับความเร็วในการหมุนของวัตถุนี้ คำนวณการเปลี่ยนแปลงท้องถิ่น ( rotatedLocalCFrame) ) และสุดท้ายตั้งไว้ที่ CFrameโปรดทราบว่าทั้งพ่อและวัตถุสามารถเป็น Model หรือ MeshPart ดังนั้นเราจึงต้องตรวจสอบ IsA("รูปแบบ") และใช้ PrimaryPart.CFrame หรือ CFrame


local parentTransform
if parentObj:IsA("Model") then
if not parentObj.PrimaryPart then
-- ส่วนหลักอาจไม่ถูกสตรีมในตอนนี้
continue -- รอให้ส่วนหลักซ้ำ
end
parentTransform = parentObj.PrimaryPart.CFrame
else
parentTransform = parentObj.CFrame
end
curObjInfo.curAngle += dT * curObjInfo.timeToAngle
local rotatedLocalCFrame = curObjInfo.origLocalCFrame * CFrame.Angles( curObjInfo.axisMask.X * curObjInfo.curAngle, curObjInfo.axisMask.Y * curObjInfo.curAngle, curObjInfo.axisMask.Z * curObjInfo.curAngle )
if obj:IsA("Model") then
obj.PrimaryPart.CFrame = parentTransform * rotatedLocalCFrame
else
obj.CFrame = parentTransform * rotatedLocalCFrame
end

เราตรวจสอบสําหรับ Model.PrimaryPart ที่ถูกต้องเพื่อตั้งค่าการสตรีมหากการอัปเดตถูกเรียกในวัตถุของเราในขณะที่ Model.PrimaryPart (ที่สามารถชี้ไปที่เมชลูก) ยังไม่ถูกสตรีม เราจะข้ามการอัปเดตระบบปัจจุบันเป็นรอบที่สองของการหมุนวัตถุและระบบก่อนหน้านี้ทำงานแตกต่างกัน: ค่ามีความแตกต่าง 12 เท่า! เพื่อรักษาข้อมูลเดียวกันเราแปลงเป็นสคริปต์ของเราเช่น "12 * obj.Speed.Value"

ออกแบบการโจมตีสายฟ้า

เนื่องจาก Studio ไม่เสนอตัวสร้างสายฟ้าแลบนอกกล่องและระบบอนุภาคมีข้อจำกัดบางอย่างที่จะไม่ทำงานสำหรับการโจมตีสายฟ้าของฮีโร่ เราจึงต้องคิดสร้างสรรค์ด้วยทางออกสำหรับการโจมตีสายฟ้าฮีโร่เราตัดสินใจเลือกระบบหลักสองระบบเพื่อสร้างสายฟ้า: ลำแสงที่มีพื้นผิวสำหรับการโจมตีสายฟ้าของฮีโร่ที่มาจากดวงตาของพายุเป็นลำแสงที่มีพื้นผิวซึ่งเปิดเผยและซิงค์กับเอฟเฟกต์เสียงและเอฟเฟกต์การประมวลผลหลังการบันทึก และเอฟเฟกต์อนุภาคง่ายๆสำหรับสายฟ้าระหว่างเมฆไกล

ลำแสงเทกเจอร์

โดยปกติเราจะใช้เครื่องมือเซเวอร์หรือเครื่องมือเวลาเพื่อขับเคลื่อนเวลาของเอฟเฟกต์การโจมตีของลำแสงไฟเช่นนี้ แต่เนื่องจาก Studio ยังไม่เสนอฟังก์ชันนี้ เราจึงตัดสินใจที่จะเขียนสคริปต์ที่จะควบคุมเวลาของลำแสงไฟการเขียนสคริปต์ของเอฟเฟกต์นี้ค่อนข้างง่าย แต่มันบรรลุเป้าหมายสำคัญต่อไปนี้:

  1. องค์ประกอบของสายฟ้าฟาด เช่น เทกเจอร์ ความสว่าง และความล่าช้า จะถูกสุ่มกับทุกการโจมตี
  2. การเปลี่ยนแปลงเสียงและโพสต์ FX สอดคล้องกับการโจมตี FX
  3. ผู้เล่นที่อยู่ทั้งในร่มหรือในพื้นที่ที่เสียหายจะไม่สามารถมองเห็นหรือได้ยินพวกเขาได้

เรามีส่วนของเซิร์ฟเวอร์ Script ที่คำนวณพารามิเตอร์และเวลาต่างๆ ส่งไปยังลูกค้าทั้งหมด และรอระยะเวลาสุ่ม:


local function LightningUpdate()
while true do
task.wait(rand:NextNumber(3.0, 10.0))
local info = CreateFXData()
lightningEvent:FireAllClients(info)
end
end

ภายใน CreateFXData , เรากรอกโครงสร้างข้อมูลเพื่อให้ลูกค้าทั้งหมดได้รับพารามิเตอร์เดียวกัน

ในด้านไคลเอนต์ ( LightningVFXClient ) เราตรวจสอบว่าไคลเอนต์นี้ควรใช้ FX หรือไม่:


local function LightningFunc(info)
-- ไม่มี FX เมื่ออยู่ในร่ม
if inVolumesCheckerFunc:Invoke() then
return
end
-- ไม่มี FX เมื่อไม่ได้อยู่ในโลก "ปกติ"
if not gameStateInfoFunc:Invoke("IsInNormal") then
return
end

นอกจากนี้เรายังเรียกลำดับเพื่อตั้งเทกเจอร์ตำแหน่งและความสว่าง, วิ่งวัยรุ่น, และใช้ task.wait(number)พารามิเตอร์สุ่มมาจากโครงสร้างข้อมูลที่เราได้รับจากเซิร์ฟเวอร์และตัวเลขบางตัวถูกกำหนดไว้แล้ว


beam.Texture = textures[info.textIdx]
beamPart.Position = Vector3.new(info.center.X + og_center.X, og_center.Y, info.center.Y + og_center.Z)
-- ลบ
beam.Brightness = 10
ppCC.Brightness = maxPPBrightness
ppBloom.Intensity = 1.1
bottom.Position = top.Position
tweenBrightness:Play()
tweenPPBrightness:Play()
tweenPPBrightness:Play()
tweenBottomPos:Play()
tweenBrightness.Completed:Wait()
-- เสียง
if audioFolder and audioPart then
if audioFolder.Value and audioPart.Value then
audioUtils.PlayOneShot(audioObj, audioFolder.Value, audioPart.Value)
end
end
task.wait(info.waitTillFlashes)
-- and so on

เพื่อตรวจสอบว่าผู้เล่นอยู่ภายในหรือไม่ เราใช้ฟังก์ชันผู้ช่วย inVolumesCheckerFunc ซึ่งไปผ่านปริมาณที่วางไว้ล่วงหน้าที่ใกล้กับพื้นที่ภายใน และตรวจสอบว่าตำแหน่งผู้เล่นอยู่ภายในพวกเขาใดก็ได้ (PointInABox)เราอาจใช้การตรวจจับแบบสัมผัส แต่เราพบว่าเมื่อผู้เล่นนั่งอยู่ภายในระดับเสียง พวกเขาจะไม่ "สัมผัส" ระดับเสียงอีกต่อไปการทดสอบจุดในไม่กี่กล่องง่ายกว่า และเราทำเพียงเมื่อผู้เล่นย้ายไกลพอจากตำแหน่งที่ทดสอบไปแล้ว

เพื่อตรวจสอบว่าผู้เล่นอยู่ในพื้นที่ที่เสียหายหรือไม่ เราจะเรียกใช้ฟังก์ชันช่วยเหลือ gameStateInfoFunc ซึ่งตรวจสอบสถานะเกมปัจจุบันเพื่อเล่นเสียงสุ่มจากโฟลเดอร์เรายังใช้ฟังก์ชันช่วยเหลือ PlayOneShotสำหรับลูกสายฟ้าเอง สิ่งเหล่านี้สร้างได้ง่ายมากใน Photoshop; เราวาดเส้นขดตัว จากนั้นเพิ่มเอฟเฟกต์ชั้น "แสงภายนอก"

ใช้ระบบปล่อยอนุภาค

การโจมตีสายฟ้าของฮีโร่ได้รับการสนับสนุนโดยระบบอนุภาคที่แนะนำสายฟ้าที่ไกลออกไปโดยสร้างความประทับใจของชั้นเมฆในพื้นหลังที่จับแสงจากการโจมตีไกลหรือการส่องแสงระหว่างเมฆเราบรรลุผลนี้ผ่านระบบอนุภาคที่เรียบง่ายมากซึ่งแฟลชบิลบอร์ดเมฆบนขอบของเมฆพายุหลักระบบปล่อยอนุภาคเมฆเป็นระยะๆด้วยเส้นโค้งความโปร่งใสแบบสุ่ม:

ทำให้ต้นไม้พัดในสายลม

หลังจากที่เรามีเมฆและสายฟ้าทำงานตามที่เราต้องการแล้ว เราจำเป็นต้องเพิ่มอีกสองส่วนประกอบหลักของพายุ: ลมและฝน! องค์ประกอบเหล่านี้มีความท้าทายบางอย่าง รวมถึงความจำเป็นในการทำงานภายในข้อจำกัดปัจจุบันของระบบฟิสิกส์และเอฟเฟกต์พิเศษของ Studioตัวอย่างเช่น การทำให้ต้นไม้เคลื่อนที่ไปตามลมจริงไม่เป็นไปได้ในเครื่องยนต์ในปัจจุบัน ดังนั้นเราจึงใช้เอฟเฟกต์ ตัวปล่อยอนุภาค และ ภาพเคลื่อนไหวตัวละครที่กำหนดเอง สำหรับต้นไม้

เรารู้ว่าจะขายผลกระทบของลมและฝนจริงๆ เราต้องการให้ต้นไม้เคลื่อนที่เองมีหลายวิธีที่คุณสามารถทำได้ภายในเครื่องยนต์ รวมถึงการเคลื่อนย้ายชิ้นส่วนโดยใช้ ปลั๊กอิน ที่สามารถใช้งานได้สาธารณะโดยใช้ TweenService หรือแอนิเมชั่นโมเดลโดยตรงสำหรับวัตถุประสงค์ของเราแอนิเมชั่นให้ความสามารถในการควบคุมการเคลื่อนไหวที่เราต้องการออกจากต้นไม้ของเราและสามารถให้เราใช้แอนิเมชั่นเดียวที่เราสามารถแบ่งปันระหว่างต้นไม้ทั้งหมดภายในประสบการณ์ได้

เราเริ่มต้นด้วยการขูดเนื้อไม้หลายต้นจาก แพ็ครูปแบบการสนับสนุน - ทรัพยากรป่าไม้เนื่องจากต้นไม้เหล่านี้มีอยู่แล้ว และประสบการณ์ของเราเกิดขึ้นในภาคเหนือตะวันตกของแปซิฟิก มันช่วยประหยัดเวลาให้เราได้บางส่วนตั้งแต่เนิ่นๆ จากการต้องสร้างแต่ละรูปแบบต้นไม้

แพ็คป่าประกอบด้วยหลายประเภทต้นไม้ซึ่งสามารถประหยัดเวลาในประสบการณ์ของคุณเองได้

หลังจากที่เราเลือกต้นไม้ของเราแล้ว เรารู้ว่าเราต้องสกัดพวกมันสกินเนตเวิร์กเมช คือการเพิ่มข้อต่อ (หรือกระดูก) ให้กับเมชในแอปพลิเคชันการโมเดลลิ่ง 3D อื่น ๆ เช่น Blender หรือ Maya จากนั้นใช้อิทธิพลกับข้อต่อ/กระดูกเหล่านั้นเพื่อย้ายเมชนี่เป็นที่ใช้บ่อยที่สุดใน ตัวละครหุ่นยนต์ แต่ด้วย ตัวละครที่กําหนดเอง คุณสามารถสร้างสกินได้เกือบทุกอย่าง

เรารู้ว่าเราต้องการประหยัดเวลาและนำภาพเคลื่อนไหวเดียวกันกลับมาใช้อีกครั้งดังนั้นเราจึงสร้างคอนโซลต้นไม้แรกของเราและตรวจสอบให้แน่ใจว่าชื่อร่วมเป็นทั่วไปเพราะเราต้องการใช้ชื่อเดียวกันในคอนโซลต้นไม้สำหรับต้นไม้อื่นเรายังรู้ว่าเราต้องรวมข้อต่อและกระดูกรองลำดับแรก รองลำดับที่สอง และรองลำดับที่สามสำหรับล็อคที่จะโค้งตามลม กิ่งที่แกว่ง และใบที่ดูเหมือนว่าพวกเขากำลังสั่นตอบสนองสำหรับกระบวนการนี้ เราต้องสร้าง การเคลื่อนไหวรอง ซึ่งเป็นแนวคิดการแอนิเมชั่นที่ทำให้การกระทำใดๆ ทำให้ส่วนอื่นๆ ของวัตถุตอบสนองต่อการกระทำนั้นและดูเหมือนจะแซงไปกับการเคลื่อนไหวเริ่มแรก

ต้นไม้มีข้อต่อระดับหลัก รอง และสามัญ เพื่อให้เราสามารถมีการเคลื่อนไหวที่น่าเชื่อถือได้จากการถูกพัดไปรอบๆ โดยลม

เมื่อเราได้สร้างข้อต่อ/กระดูกของเราแล้ว ถึงเวลาสร้างแอนิเมชันทดสอบเพื่อย้ายไปรอบๆ ข้อต่อและกระดูกทั้งหมดใน Studio เพื่อดูว่ามันเคลื่อนที่ไปตามที่เราต้องการหรือไม่เพื่อทําเช่นนี้ เราต้อง นําต้นไม้ไปยัง Studio ผ่านการตั้งค่า Rig ที่กําหนดเอง ใน เครื่องนําเข้า 3D จากนั้นย้าย/แอนิเมชั่นเมชใช้ เครื่องแก้ไขแอนิเมชั่นเราตั้งค่าวัสดุและเทกเจอร์หลังการทดสอบเหล่านี้ แต่คุณสามารถดูผลลัพธ์ด้านล่างได้

ชั้นเดียวกันภายใน Studio

หลังจากที่เราพอใจกับผลลัพธ์บนต้นไม้นั้นแล้ว ถึงเวลาที่ต้องทดสอบแอนิเมชันเดียวกันบนต้นไม้อื่น! พิมพ์ดังนั้นเราจึงตรวจสอบให้แน่ใจว่าแอนิเมชันของเราดูเหมือนว่าจะเพียงพอที่จะทำงานระหว่าง Redwood สูงและ Beechwood ที่แข็งแกร่ง!

แอนิเมชั่นที่เรานำเข้าบนต้น Redwood

เพื่อทำเช่นนี้ เราได้เอาต้น Beechwood จากแพ็คป่านั้นและสร้างเครื่องปรุงที่คล้ายกันโดยใช้ชื่อเดียวกันสำหรับข้อต่อนี่เป็นวิธีที่แอนิเมชั่นที่เรานำมาในอดีตจะสามารถใช้กับต้นไม้นี้ได้เช่นกันเนื่องจากภาพเคลื่อนไหวทั้งหมดขึ้นอยู่กับข้อต่อหมุน ไม่เป็นไรว่าต้นไม้จะใหญ่ เล็ก สูง หรือกว้างแค่ไหน!

ต้น Beechwood มีชื่อเดียวกันสําหรับข้อต่อของมันเท่านั้น ไม่ใช่จํานวนเงินเดียวกันไม่เป็นไรเนื่องจากระบบแอนิเมชั่นจะใช้แอนิเมชั่นเฉพาะกับข้อต่อที่ตรงกับชื่อในนั้นเท่านั้น! ด้วยเหตุผลนี้เราจึงสามารถใช้แอนิเมชั่นเดียวกันกับสิ่งที่ตรงกับชื่อข้อต่อได้!

หลังจากที่เรา ติดตั้งและผิวหนัง ต้นไม้ Beechwood เราสามารถนำมาใช้และใช้แอนิเมชั่นเดียวกันได้ซึ่งหมายความว่าการเลื่อนและแก้ไขจำเป็นต้องทำเพียงในไฟล์เดียวเท่านั้น และยังบันทึกในประสิทธิภาพด้วยแอนิเมชันน้อยลงเมื่อเรียกใช้ประสบการณ์

โดยใช้เครื่องมือตัดแต่งแอนิเมชัน เราสามารถใช้แอนิเมชันต้นไม้ Redwood เดียวกันกับต้นไม้ Beechwood ได้!

เมื่อเรามีทุกประเภทต้นไม้ที่เราต้องการให้เคลื่อนไหวแล้ว เราทำให้แต่ละอย่างเป็น แพคเกจ เพื่อให้เราสามารถดำเนินการแก้ไขและอัปเดตได้ในขณะที่เล่นภาพเคลื่อนไหวหลายรายการรอบพื้นที่หลักของประสบการณ์เนื่องจากเรารู้ว่าพวกเขามีค่าใช้จ่ายด้านประสิทธิภาพ เราจึงใช้พวกเขาอย่างประหยัดรอบบ้านที่ผลกระทบมีคุณค่ามากที่สุด! ในอนาคตเมื่อสิ่งนี้กลายเป็นที่ปฏิบัติได้มากขึ้น คุณจะสามารถเพิ่มจำนวน instance สกิน mesh ได้มากขึ้นเรื่อยๆ!

เราใช้ต้นไม้เคลื่อนไหวทันทีรอบบ้านที่พายุวิปริตแรงที่สุดและเอฟเฟกต์ภาพจะเป็นที่มีผลกระทบมากที่สุดสำหรับผู้เล่น

ทำขยะพายุ

เราต้องการให้ฝนดูหนักและให้หมอกและเศษซากพัดผ่านต้นไม้เพื่อทําเช่นนี้เราตั้งค่าชิ้นส่วนที่มองไม่เห็นไม่กี่ชิ้นเพื่อกระทําเป็นปริมาณอนุภาคพร้อมกับตัวปล่อยอนุภาคลูก ๆ ทันทีที่อยู่ใต้เมฆพายุขนาดใหญ่เนื่องจากขีดจํากัดจํานวนอนุภาคใน Studio เราไม่สามารถใช้ตัวปล่อยอนุภาคหนึ่งตัวสําหรับพื้นที่ทั้งหมดได้แทนที่เราเพิ่มหลายอย่างที่มีขนาดเดียวกันกับกันในรูปแบบกริดบนพื้นที่เล่นได้เพราะการมีต้นไม้หมายความว่าผู้เล่นจะไม่สามารถมองเห็นได้ไกล

เราใช้หลายระดับเพื่อรับปริมาณฝนและการครอบคลุมฝนที่เฉพาะเจาะจงที่เราต้องการ

อนุภาคฝนใช้ประโยชน์จากคุณสมบัติเอมิตเตอร์อนุภาคใหม่ ParticleEmitter.Squash ที่ช่วยให้คุณสามารถทำให้อนุภาคยาวขึ้นหรือจมลงได้มันมีประโยชน์เป็นพิเศษสำหรับฝนเพราะหมายความว่าเราไม่ต้องการเทกเจอร์ฝนขนาดใหญ่เพียงแค่ยืดเทกเจอร์ที่มีอยู่เพียงรู้ว่าหากคุณเพิ่มมูลค่าของ ParticleEmitter.Squash คุณอาจต้องเพิ่มค่า ParticleEmitter.Size โดยรวมด้วยเพื่อให้มันไม่เพรียวเกินไป! โดยรวมแล้วมันเป็นเพียงเรื่องของการเล่นกับค่าจนกว่าเราจะได้รับฝนหนักพอ แต่ไม่มากเกินไปที่จะบล็อกการมองเห็นประสบการณ์!

มูลค่า Squash ของ 3 เริ่มยืดเนื้อเยื่อได้นานขึ้น
ค่า Squash ของ 20 ยืดอนุภาคได้นานขึ้น แต่เรายังต้องเพิ่มค่าขนาดด้วย

สำหรับหมอกและใบไม้ที่พัดผ่านไปมา มันง่ายมากที่จะเพิ่มปริมาณส่วนเดียวที่ใหญ่กว่าครอบคลุมพื้นที่น้อยลงเพราะเราไม่ต้องการปริมาณอนุภาคจํานวนมากที่วิ่งในครั้งเดียวเราเริ่มต้นโดยการตั้งค่าระดับเสียงและได้รับความถี่ของอนุภาคที่ต้องการ

มีปริมาณอนุภาคสองสามส่วนจบลงดังนั้นเราจึงไม่มีอนุภาคเข้าสู่บ้าน และเพราะเราไม่รู้สึกว่าพวกเขาต้องการเคลื่อนที่ผ่านต้นไม้เหมือนหมอกที่ทำ
ปริมาณของอนุภาคหมอกมีขนาดใหญ่กว่ามากเนื่องจากอนุภาคมีขนาดใหญ่และเราไม่จำเป็นต้องแม่นยำกับตำแหน่ง

หลังจากนั้นเราทำให้ใบพัดและเทกเจอร์ลมของเราและตั้งค่าอนุภาคให้หมุน/เคลื่อนที่ในอัตราที่แตกต่างกันและเริ่มต้นด้วยความเร็วที่แตกต่างกันซึ่งหมายความว่าอนุภาคหมอกขนาดใหญ่จะโต้ตอบได้เป็นธรรมชาติมากขึ้นและไม่ดูเหมือนเทกเจอร์ที่ซ้ำกันมากเกินไป โดยเฉพาะอย่างยิ่งเมื่อพิจารณาถึงขนาดของพวกเขา

อนุภาคหมอก
>

อนุภาคใบ

ผลลัพธ์คือการกระทำที่ยอดเยี่ยมระหว่างต้นไม้ที่เคลื่อนที่ หน้าต่างพัด และสายฟ้าที่สร้างผลกระทบของพายุรอบดวงตากลางของพายุ

ตั้งตาของพายุ

ดวงตาหินแตกที่มีแกนส่องสว่างมีจุดมุ่งหมายเพื่อให้ผู้เล่นได้รับเบาะแสแรกว่ามีบางอย่างน่ากลัวและลึกลับเกิดขึ้นที่บ้านที่พวกเขาควรสำรวจต่อไปเนื่องจากฉากของเรามืดและดวงตาอยู่ไกลบนท้องฟ้าจึงเป็นสิ่งสำคัญที่จะสร้างภาพรอยแตกของหินที่น่าเชื่อถือ แต่ไม่สำคัญที่จะสร้างรายละเอียดพื้นผิวหินที่น่าเชื่อถือเพราะผู้เล่นจะไม่สามารถมองเห็นได้รู้ว่าสิ่งที่เป็นจริงสำหรับผู้เล่นของคุณที่จะเห็นแสงภายในฉากของคุณก่อนที่จะใช้เวลามากมายในรายละเอียดที่ไม่จำเป็นสามารถประหยัดทรัพยากรมากมายในกระบวนการพัฒนาได้

การตั้งค่าแสงสุดท้ายในฉากของคุณตั้งแต่เนิ่นๆ สามารถประหยัดเวลาและงานที่ไม่จำเป็นมากมายได้คุณจะไม่สามารถเห็นรายละเอียดพื้นผิวบนแหวนด้วยแสงสุดท้ายของฉากของเราได้ดังนั้นจึงไม่จำเป็นต้องใช้เวลาในการวางพวกเขาที่นั่น!

ระยะห่างจากผู้เล่นยังหมายความว่าเราสามารถพึ่งพาแผนที่ปกติสำหรับรายละเอียดพื้นผิวของดวงตาได้ทั้งหมดดังนั้นเมชจึงเป็นเพียงเมชที่เรียบง่าย! เราแกะรายละเอียดออกเป็นเมชที่มีความสูงสูงและอบแผนที่ปกติของมันลงบนพื้นที่โพลีที่ต่ำกว่ามากเพื่อให้เราสามารถรับรายละเอียดทั้งหมดที่สวยงามได้โดยไม่ต้องใช้ต้นทุนการประมวลผลมากมาย

สลักโพลีสูง
เมทช์โพลีต่ำ
เมชโพลีต่ำที่มีข้อมูลปกติจากการแกะสลักโพลีสูงที่อบใน

เพื่อเพิ่มความรู้สึกเหนือธรรมชาติให้กับดวงตาและเน้นถึงการมีอยู่ของมัน เราตัดสินใจที่จะสร้างแมกม่าเรืองแสงและนีออนที่จะซึมผ่านรอยแตกของมันในขณะที่ไม่มีช่องส่งสัญญาณสำหรับรูปลักษณ์พื้นผิว เราจะเอาชนะอุปสรรคนี้โดยสร้างดวงตาจาก 2 ลูกบอล: หนึ่งสำหรับพื้นผิวหินภายนอกและอีกหนึ่งที่เล็กกว่าเล็กน้อยสำหรับแมกม่าที่เรืองแสงใน ผู้วาดสีสาร เราสร้างเทกเจอร์สีพื้นฐานสำหรับทรงกลมภายนอกที่มีความโปร่งใสในพื้นที่ที่เราต้องการให้แกนกลางภายในผ่านใน เครื่องปั่น เรา "vertex painted" ทรงกลมภายในในราคาถูกและง่ายต่อการได้รับการเปลี่ยนแปลงสีบางอย่างบนมัน

ภาพเวกเซลบนทรงกลมภายในเราสร้างเฉดสีที่เบาที่สุดรอบดวงตาเพื่อให้รู้สึกถึงความลึกและความสนใจทางสายตามากขึ้น

อีกความท้าทายที่เราพบเมื่อสร้างดวงตาคือถูกบังคับโดยการใช้ สตรีมมิ่ง รวมกับระยะห่างของดวงตาจากผู้เล่นเนื่องจากความสำคัญของโครงสร้างนี้ เราต้องการให้มันเป็นที่มองเห็นเสมอแม้ว่าระยะทาง แต่โดยไม่มีการแฮ็กใดๆ กับเมชของมัน ผู้เล่นไม่สามารถมองเห็นดวงตาได้ เว้นแต่พวกเขาอยู่ในโซลาเรียมเราสามารถบังคับให้มีการปรากฏตัวอย่างต่อเนื่องของดวงตาในฉากโดยการเพิ่มรูปทรงบางอย่างให้กับดวงตาและแหวนของมันรูปร่างนี้ตั้งอยู่ใต้พื้นผิวของพื้นที่และเพียงพอที่จะหลอกล่อให้เครื่องยนต์คิดว่าลูกบอลอยู่ใกล้กับผู้เล่นมากกว่าที่เป็นอยู่และสตรีมมันเสมอแม้ว่าควรทำได้อย่างประหยัด แต่การบังคับให้สตรีมวัตถุขนาดใหญ่เกินไปอาจทำให้ประโยชน์ของการสตรีมถูกปฏิเสธและส่งผลเสียต่อประสิทธิภาพเกม

เราสามารถเพิ่มการเคลื่อนไหวให้กับดวงตาและแหวนของมันได้ด้วยสคริปต์เดียวกับที่เราใช้เพื่อ หมุนเมชภายในเมฆสำหรับการสัมผัสครั้งสุดท้าย เราตัดสินใจที่จะเพิ่มเคล็ดลับถึงการมีอยู่ของโลกอื่นนอกเหนือจากเมฆ แต่เราต้องใช้ทางเลือกที่สร้างสรรค์เพื่อหลีกเลี่ยงการเพิ่มภูมิทัศน์เพิ่มเติมโดยไม่ต้องจัดการกับอุปสรรคที่กล่าวถึงก่อนหน้านี้ที่เกิดจากการเปิดใช้งานการสตรีมเราสร้างฉากที่มีความลึกมากเนื่องจากขนาดและระยะทางของวัตถุ แสดงภาพของฉากนี้ จากนั้นใช้ภาพที่กล่าวถึงเป็นสติกเกอร์ บนส่วนที่วางอยู่ข้างหลังดวงตาของพายุเราใช้วิธีเดียวกันสำหรับการหมุนชิ้นส่วนนี้เช่นเดียวกับที่เราใช้สำหรับดวงตาและแหวน

ภาพที่เราใช้เพื่อสร้างภาพลวงตาของโลกที่อยู่เหนือเมฆเมื่อผู้เล่นอยู่ไกลจากบางสิ่งบางอย่าง ภาพเรียบง่ายอาจเพียงพอที่จะสร้างภาพลวงตาของความลึกและความซับซ้อนมากขึ้นในฉากของคุณ!

ทำให้คลังเก็บขยาย

หนึ่งในสิ่งที่สนุกที่สุดในการผลิตคือพื้นที่ที่เสียหายซึ่งเราสามารถทำลายความคาดหวังของผู้เล่นต่อความเป็นจริงได้โดยการเปลี่ยนแปลงตัวอักษรตรงรอบพวกเขาตัวอย่างเช่น ในปริศนาของพ่อเราต้องการจำลองช่วงเวลาที่คล้ายกับฝันร้ายที่ไม่ว่าคุณจะวิ่งเร็วแค่ไหน ห้องก็รู้สึกเหมือนจะยาวขึ้นเรื่อยๆเราตัดสินใจที่จะทำให้คลังอาหารขยายตัวที่จะหนีจากผู้เล่นเมื่อพวกเขากำลังมองหาส่วนผสมเพื่อเปลี่ยนห้องกลับสู่สภาวะปกติ

เราตั้งค่านี้ขึ้นด้วยการเคลื่อนไหวง่ายๆของผนัง และการจัดวางห้องที่ชาญฉลาดของเราที่จะปรากฏทั้งสองด้านของโรงเรือนในสถานะปกติของห้อง โรงเรือนเป็นทางเดินง่ายๆ แต่ในพื้นที่ที่เสียหายมันเป็นจริงๆ นานกว่าหลายปีด้วยปีกหลายอันและผนังปลอม!

สภาพเสียของตู้ครัว
ผนังปลอมที่เคลื่อนออกไปจากผู้เล่น

กำแพงปลอมเป็นกลุ่มรูปแบบที่เราจะย้อนกลับไปในช่วงเวลาที่ผู้เล่นเข้าสู่ระดับระดับการเรียกร้องซึ่งเป็นส่วนโปร่งใสก่อนหน้านี้ในคลังที่พวกเขาจะเดินผ่านตัวกระตุ้นนั้นยังถูกใช้ในสคริปต์ที่คล้ายกับที่ใช้กับประตูทั้งหมดของเราซึ่งเรียก TweenService เพื่อย้ายจากเป้าหมายหนึ่งไปยังอีกเราใช้ปริมาณส่วนเพื่อบอกการดำเนินการทีวีนที่ตำแหน่งเริ่มต้นและสิ้นสุดสำหรับผนัง

ปริมาณส่วนทำให้เกิดกำแพงปลอมข้างหลังมันเพื่อย้ายไปยังจุดสิ้นสุดของมันมันจะปรากฏชัดในภาพนี้ด้วยสีเหลือง
เป้าหมาย_ปิดเป็นส่วนเป้าหมายทั่วไปที่เราใช้กับประตูทั้งหมดเพื่อให้พวกเขาหมุนได้ที่นี่มันถูกนำไปใช้ใหม่เพื่อบอกผนังทางเดินว่าจะไปที่ไหน

เนื่องจาก TweenService เป็นระบบทั่วไป จึงต้องมีข้อมูลรูปแบบผนังทั้งหมดของเราเป็นส่วนประกอบเดียวกันตัวอย่างเช่น สคริปต์ทั่วไป "Door_Script" เล่นเสียงที่กำหนดโดย "ค่า" ด้านล่างรูปแบบ "Grow_Wall"สคริปต์เดียวกันนั้น, ด้วยการเปลี่ยนแปลงบางอย่างในตัวอย่างโค้ดต่อไปนี้, ยังกระตุ้นเสียงสำหรับการเคลื่อนย้ายของคลังสินค้านี้เพิ่มมากให้กับการเคลื่อนไหว!


local Players = game:GetService("Players")
local TweenService = game:GetService("TweenService")
local model = script.Parent
local sound = model.Sound.Value
local trigger = model.Trigger
local left = model.TargetL_Closed
local right = model.TargetR_Closed
local tweenInfo = TweenInfo.new(
model.Speed.Value, --เวลา/ความเร็วของประตูระหว่าง
Enum.EasingStyle.Quart, --สไตล์การผ่อนคลาย
Enum.EasingDirection.InOut, --ทิศทางการผ่อนคลาย
0, --นับซ้ำ
false, --ย้อนกลับจริง
0 --ความล่าช้า
)
local DoorState = {
["Closed"] = 1,
["Opening"] = 2,
["Open"] = 3,
["Closing"] = 4,
}
local doorState = DoorState.Closed
local playersNear = {}
local tweenL = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Open.CFrame})
local tweenR = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Open.CFrame})
local tweenLClose = TweenService:Create(left, tweenInfo, {CFrame = model.TargetL_Closed.CFrame})
local tweenRClose = TweenService:Create(right, tweenInfo, {CFrame = model.TargetR_Closed.CFrame})
local function StartOpening()
doorState = DoorState.Opening
sound:Play()
tweenL:Play()
tweenR:Play()
end
local function StartClosing()
doorState = DoorState.Closing
--รูปแบบ ["ประตู"]: เล่น()
tweenLClose:Play()
tweenRClose:Play()
end
local function tweenOpenCompleted(playbackState)
if next(playersNear) == nil then
StartClosing()
else
doorState = DoorState.Open
end
end
local function tweenCloseCompleted(playbackState)
if next(playersNear) ~= nil then
StartOpening()
else
doorState = DoorState.Closed
end
end
tweenL.Completed:Connect(tweenOpenCompleted)
tweenLClose.Completed:Connect(tweenCloseCompleted)
local function touched(otherPart)
if otherPart.Name == "HumanoidRootPart" then
local player = Players:GetPlayerFromCharacter(otherPart.Parent)
if player then
--พิมพ์("สัมผัส")
playersNear[player] = 1
if doorState == DoorState.Closed then
StartOpening()
end
end
end
end

เมื่อเรามีผนังปลอมเคลื่อนไปที่ด้านหลังของห้อง เราต้องการให้เนื้อหาส่วนที่เหลือเคลื่อนไปพร้อมกับมันเพื่อทำเช่นนั้น เราต้องการให้ไอเทมทั้งหมดที่หลวมอยู่ในคลังสินค้าถูกเชื่อมต่อกับผนังในขณะที่เคลื่อนที่โดยใช้ ข้อจํากัดการเชื่อม เราสามารถเชื่อมต่อวัตถุทั้งหมดไปยังผนังโรงอาหารได้อย่างรวดเร็วเพื่อย้ายเป็นวัตถุเดียวการทำเช่นนี้หมายความว่าเรามีตัวเลือกในการถอดชิ้นส่วนเหล่านี้ออกเพื่อให้ผู้เล่นชนกับพวกเขาและเตะพวกเขาได้!

สร้างบ้านต้นที่เสียหาย

สตูดิโอเป็นเครื่องยนต์ที่ขับเคลื่อนด้วยพลังงานทางกายภาพที่คุณสามารถใช้เพื่อสร้างทุกอย่างตั้งแต่ประตูสวิงไปจนถึงแพลตฟอร์มหมุนด้วยการสาธิตของเรา เราต้องการใช้ฟิสิกส์เพื่อสร้างความรู้สึกเหมือนจริงในชุดสภาพแวดล้อมที่ไม่สมจริงอย่างอื่นโดยใช้ข้อจำกัดเพียงไม่กี่ ข้อจำกัด คุณสามารถสร้างสนามแข่งอุปสรรคที่สนุกและท้าทายภายในประสบการณ์ของคุณเองได้!

ข้อจํากัด เป็นกลุ่มของมอเตอร์ที่ขับเคลื่อนด้วยร่างกายที่สอดคล้องกับวัตถุและจำกัดพฤติกรรมตัวอย่างเช่น คุณสามารถใช้ข้อจํากัดของแท่ง เพื่อเชื่อมต่อกับวัตถุเพื่อให้พวกมันอยู่ในระยะคงที่จากกัน หรือข้อจํากัดของเชือก เพื่อให้มีโคมไฟแขวนอยู่ที่ปลายของเส้นสำหรับปริศนาของลูกชายที่ผู้เล่นถูกส่งไปยังสถานะที่เสียหายของการศึกษา เราต้องการที่จะกลับโลกให้กลับด้านอย่างตัวอักษรการทำเช่นนี้จะทำลายความคาดหวังของผู้เล่นต่อความเป็นจริงและกฎที่นั่นในขณะที่ยังคงใช้ระบบฟิสิกส์ตามที่ตั้งใจไว้!

ปริศนาของลูกชายเริ่มต้นด้วยผู้เล่นในห้องเดียวกัน แต่ทุกอย่างเป็นแบบข้างๆ

เมื่อผู้เล่นทำงานลงไปยังพื้นที่หลักของปริศนาแล้วพวกเขาถูกต้อนรับด้วยทิวทัศน์ที่คุ้นเคยบน Roblox: สนามแข่งอุปสรรคสนามอุปสรรคโดยเฉพาะนี้ประกอบด้วยแพลตฟอร์มหมุนหลายแห่งและผนังหมุนรวมถึง "พื้นที่ปลอดภัย" ที่คืบหน้าเรื่องราวเราจะมุ่งเน้นไปที่องค์ประกอบที่หมุน/หมุน

รูปลักษณ์ที่ทําให้สมองแตกซ่อนความจริงที่ว่าการเล่นเกมที่นี่ง่ายมาก

ทำไมเราถึงใช้ข้อจํากัดที่นี่? เพราะ TweenService หรือวิธีอื่นจะไม่ย้ายผู้เล่นในขณะที่พวกเขายืนอยู่บนพวกเขาโดยไม่มีวัตถุเคลื่อนย้ายผู้เล่นใครบางคนสามารถกระโดดบนแพลตฟอร์มและมันจะหมุนออกจากใต้พวกเขาแทนที่, เราต้องการให้ผู้เล่นนำทางผ่านแพลตฟอร์มหมุนในขณะที่พยายามทำการกระโดดไปยังอันถัดไปเนื่องจากวิธีนี้ผู้เล่นรู้สึกมีรากฐานที่พวกเขายืนอยู่ในขณะที่ตัดสินใจว่าจะดำเนินการต่อไปอย่างไรผ่านสนามแข่งและเราไม่จำเป็นต้องทำอะไรพิเศษเพื่อให้แน่ใจว่าพวกเขาย้ายไปกับพื้นผิวหมุน!

คุณสามารถดูเพื่อนของคุณหมุนรอบในขณะพยายามนำทางในสนามแข่งอุปสรรคได้เช่นกัน

เพื่อทำเช่นนี้ เราต้องใช้สินทรัพย์จากชุดปัจจุบันของเราก่อนและเพิ่มเนื้อหาใหม่ใดๆ เพื่อให้ได้ผลกระทบทางสายตาเราสร้างผนังและแพลตฟอร์มไม่สมบูรณ์ไม่กี่แห่งพร้อมหลุมในนั้นเพื่อบอกเล่าเรื่องราวของการสร้างบ้านต้นไม้ของยายเนื่องจากเราไม่ต้องการสร้างกลุ่มแพลตฟอร์มที่ไม่ซ้ำกันจำนวนมาก เราจึงสร้างชิ้นฐาน 4 ชิ้นและชิ้นรางแยกต่างหากสิ่งนี้ทำให้เราสามารถผสมผสานชิ้นฐานและรางรถแต่ละชิ้นเพื่อให้มีความหลากหลายมากขึ้น

เรารู้ว่าเนื่องจากเราใช้ข้อจำกัด เราจะไม่สามารถยึดเมชเหล่านี้ได้เพราะพวกมันจะไม่เคลื่อนไหวแม้จะมีข้อจำกัด/มอเตอร์ขับเคลื่อนพวกมันข้อจำกัดที่จำเป็นต้องเป็นลูกของบางสิ่งที่ถูกยึดเพื่อให้แพลตฟอร์มไม่ล้มออกจากโลกเราแก้ปัญหานี้ผ่านส่วนที่เราเรียกว่า Motor_Anchor ซึ่งมี ข้อจำกัดบานพับ เพื่อขับเคลื่อนการเคลื่อนไหวโดยรวมของแพลตฟอร์มหลังจากนั้นเราต้องการให้สองเมชเคลื่อนที่เป็นหนึ่งดังนั้นเราจึงสร้างชิ้นส่วนที่เราตั้งชื่อว่า Motor_Turn จากนั้นเราจึงเชื่อมสองเมชเข้าด้วยกันทางนี้ข้อจํากัดจะสามารถทํางานกับชิ้นส่วนเดียวได้ ซึ่งแตกต่างจากบานพับหลายอันที่ทํางานร่วมกับชิ้นส่วนหลายชิ้น

ตอนนี้ถึงเวลาที่จะตั้งค่าพฤติกรรมที่เกิดขึ้นจริงของข้อจำกัดบานพับเองและเพิ่มสิ่งที่จะทำหน้าที่เป็นจุดศูนย์กลางของชิ้นส่วนและข้อจำกัดด้วยกันเราวางอุปกรณ์หมุนบน Motor_Turn ซึ่งชิ้นส่วนทางเดินถูกเชื่อมต่อกับมัน และอีกอุปกรณ์สำหรับพฤติกรรมของแอนคอร์บน Motor_Anchor เอง เป็นเจ้าของแทนที่จะได้รับอิทธิพลจากผู้เล่น (เช่นบานพับประตู) เราตั้ง HingeConstraint.ActuatorType เป็น เครื่องยนต์ ซึ่งจัดการข้อจำกัดเหมือนเป็นมอเตอร์ที่เคลื่อนที่เองได้

เพื่อให้แพลตฟอร์มหมุนด้วยความเร็วคงที่เราจะตั้งค่าคุณสมบัติ HingeConstraint.AngularVelocity , HingeConstraint.MotorMaxAcceleration และ HingeConstraint.MotorMaxTorque ให้เป็นค่าที่จะอนุญาตให้เคลื่อนที่และป้องกันการหยุดชะงักหากผู้เล่นกระโดดบนมัน

แนบเนียน 0 เป็นหลักฐานสําหรับบานพับและแนบเนียน 1 เป็นบานพับเองเรามีบานพับหมุนอย่างต่อเนื่อง แต่คุณยังสามารถใช้ข้อจํากัดบานพับสําหรับประตูได้เช่นกัน

ตอนนี้เราต้องทำผนังหมุนผนังต้องหมุนบนศูนย์กลางที่ปรากฏ และเรารู้ว่าเราต้องการให้พวกเขาสามารถจัดการกับทิศทางใดก็ได้เมื่อเทียบกับส่วนที่เหลือของระดับเช่นเดียวกับแพลตฟอร์มเราสร้างสิ่งเหล่านี้เพื่อให้ผนังทั้งหมดไม่ได้รับการยึดและเชื่อมต่อกับ Motor_Turn

เราต้องการที่จะใช้ซ้ำเมชของบ้านต้นจริงให้มากที่สุดเพื่อประหยัดประสิทธิภาพดังนั้นเราจึงปฏิบัติตามเส้นทางที่คล้ายกับแพลตฟอร์มมีการสร้างผนังหลายประเภทที่สามารถติดกันได้ในรูปแบบที่แตกต่างกันสําหรับการแปลงบางอย่าง

เราใช้วัตถุ Texture ด้านบนวัตถุ SurfaceAppearance เพื่อเพิ่มความแตกต่างให้กับวัสดุพื้นฐานของเราเทกเจอร์ ที่คล้ายกับภาพวาดช่วยให้คุณสามารถวางภาพบนเครื่องบินของเมชได้นี่อาจมีประโยชน์หากคุณต้องการเพิ่มสิ่งสกปรกให้กับกำแพงอิฐหรือทำให้ไม้ดูเก่าขณะใช้วัสดุฐานเดียวกัน Texture วัตถุมีพฤติกรรมที่แตกต่างเล็กน้อยจาก Decal วัตถุในการที่คุณสามารถจัดเรียงและชดเชยภาพได้ตามที่คุณต้องการซึ่งเป็นประโยชน์มากหากคุณต้องการสามารถปรับขนาดเทกเจอร์โอเวอร์เลย์ของคุณและไม่สนใจว่ามันจะซ้ำไปซ้ำมา!

คุณสามารถดูทั้งพฤติกรรมที่คล้ายกันและตั้งค่าสําหรับข้อจํากัดบานพับ และยังวิธีที่เราใช้วัตถุ Texture ด้วย

เมื่อเราทดสอบแพลตฟอร์มและผนังหมุนไม่กี่แล้ว เราทำการเปลี่ยนแปลงหลายรูปแบบและเล่นกับตำแหน่งของพวกเขาเพื่อให้แน่ใจว่าสนามแข่งอุปสรรคมีความท้าทาย ควบคุมจิตใจ และชัดเจนว่าผู้เล่นจะต้องไปที่ไหน! ใช้เวลาในการปรับแต่งทั้งค่าและตำแหน่งของพวกเขาเพื่อให้พวกเขาทำงานได้ดีเรามีจุดหลายแห่งที่แพลตฟอร์มและผนังกำลังชนกันหรือสิ่งแวดล้อม แต่ด้วยการเคลื่อนที่บางอย่างและการทดสอบบ่อยๆ เราสามารถลงจอดบนการตั้งค่าที่เรามีในการสาธิตได้!

หากคุณไม่แน่ใจว่าวัตถุทางกายภาพที่คุณกําลังโจมตีคืออะไร คุณสามารถเปิดใช้งาน ความน่าเชื่อถือในการชนกัน จากแดชบอร์ด ตัวเลือกการแสดงผล ในมุมขวาบนของหน้าต่าง 3D มุมมอง

A close up view of the 3D viewport with the Visualization Options button indicated in the upper-right corner.
เมื่อการแสดงภาพการชนกันถูกปิดใช้งานคุณสามารถดูการแสดงรูปทรงปกติที่แสดงในเกมได้
เมื่อเปิดใช้งานการแสดงภาพการชนกันแล้ว คุณสามารถเห็นใบไม้ไม่มีการชนกัน ดังนั้นพวกเขาจะไม่รบกวนแพลตฟอร์มหรือผนังหมุนได้

ตามที่คุณเห็นด้านล่างช่องประตู/หน้าต่างมองเห็นได้ แต่รายละเอียดเล็กๆ เช่นการย่อยแผงไม่เห็นเนื่องจากคุณสมบัติ CollisionFidelity สำหรับผนังถูกตั้งค่าเป็น กล่อง เราไม่ต้องการความแม่นยําสําหรับแผงเหล่านี้ดังนั้นเพื่อประหยัดค่าใช้จ่ายในการดําเนินการ, นี่มีรายละเอียดเพียงพอสําหรับผู้เล่นที่จะกระโดดเข้ามาเมื่อแพลตฟอร์มและผนังหมุนเสร็จแล้ว เราเพียงต้องเพิ่มสินทรัพย์รายละเอียดเช่นกล่องและโคมไฟ จากนั้นก็พร้อมที่จะเล่น!