ในคู่มือนี้ คุณจะได้เรียนรู้วิธีปรับเกมให้ทำงานในอุปกรณ์ Android รูปแบบต่างๆ
ก่อนเริ่มต้น โปรดอ่านรองรับความสามารถในการปรับขนาดหน้าจอขนาดใหญ่ เกมสมัยใหม่บน Android ควรปรับให้เข้ากับหน้าจอทุกขนาดโดยไม่ต้องอาศัยเลเยอร์ความเข้ากันได้ของระบบ วิธีนี้ช่วยให้คุณควบคุมวิธีแสดงเกมได้เสมอ และเกมจะมอบประสบการณ์การเล่นระดับพรีเมียม แม้ในรูปแบบอุปกรณ์อย่าง XR หรืออุปกรณ์ที่หมุนหน้าจอไม่ได้
โดยทำตามขั้นตอนต่อไปนี้
- ปิดใช้การทำ Letterbox ของระบบและใช้การทำ Letterbox ในเครื่องมือของคุณเอง
- ทำให้พื้นที่ Letterbox ใช้งานได้และมีธีมที่เหมาะสม
- พิจารณาการออกแบบที่จำเป็นเพื่อให้เกมปรับขนาดได้ตั้งแต่ 21:9 ไปจนถึง 1:1 และ 9:21
คำสั่งสำหรับการทดสอบ
เมื่อสร้างและทดสอบเกม ให้ตรวจสอบว่าเกมแสดงผลแถบสีดำเอง นอกจากนี้ คุณควรบังคับให้เกมแสดงผลทั้งในแนวตั้งและแนวนอน เนื่องจากอุปกรณ์อย่างทีวีและจอแสดงผลในรถยนต์ไม่สามารถหมุนจากแนวตั้งหรือแนวนอนเริ่มต้นได้
หากต้องการตรวจสอบว่าเกมเอนจินใช้การแสดงผลแบบ Letterbox ของระบบหรือไม่ ให้ใช้คำสั่ง adb shell cmd window set-letterbox-style ตัวอย่างเช่น คำสั่งต่อไปนี้จะทำให้แถบสีดำของระบบเป็นสีเขียวสว่างและเพิ่มรัศมีมุมให้กับเกม ทำให้เห็นได้ชัดเจนหากเกมกลับไปใช้โหมดความเข้ากันได้ของระบบปฏิบัติการ
adb shell "cmd window set-letterbox-style --backgroundType solid_color --backgroundColor '#00FF00' --cornerRadius 30 --isEducationEnabled false"
หากต้องการบังคับการวางแนวเพื่อทดสอบ ให้ใช้ adb shell cmd window user-rotation lock ซึ่งจะช่วยให้คุณจำลองลักษณะการทำงานของเกมในอุปกรณ์ที่ไม่รองรับการลบล้างแอปสำหรับการวางแนว หรือทำความเข้าใจสิ่งที่ผู้ใช้เห็นในอุปกรณ์ XR หรืออุปกรณ์ที่คล้ายกับ PC ซึ่งหน้าต่างสามารถปรากฏในแนวตั้งหรือแนวนอนโดยไม่ขึ้นอยู่กับการวางแนวของอุปกรณ์
ก่อนอื่น ให้อุปกรณ์อยู่ในสถานะที่คุณลบล้างการวางแนวของแอปได้ โดยทำดังนี้
adb shell cmd window set-ignore-orientation-request true
adb shell cmd window fixed-to-user-rotation enabled
ถัดไป ให้ทดสอบการเปลี่ยนเกมเป็นแนวนอนโดยทำดังนี้
adb shell cmd window user-rotation lock 1
จากนั้นทดสอบการเปลี่ยนเกมเป็นแนวตั้งโดยทำดังนี้
adb shell cmd window user-rotation lock 0
รีเซ็ตอุปกรณ์เป็นการกำหนดค่า OEM โดยการรีบูตหรือเรียกใช้คำสั่งต่อไปนี้
adb shell cmd window reset-letterbox-style
adb shell cmd window fixed-to-user-rotation default
adb shell cmd window user-rotation free
adb shell cmd window set-ignore-orientation-request reset
เหตุใดจึงควรปิดใช้การแสดงผลแบบ Letterbox ของระบบ
ระบบจะควบคุมการทำ Letterbox ของระบบเสมอ การตรวจหาขนาดหน้าจอและจัดการพื้นที่แสดงผลด้วยตนเองจะช่วยลดปัญหาต่างๆ เช่น การป้อนข้อมูลที่หายไป ซึ่งเกิดขึ้นเมื่อการป้อนข้อมูลอยู่นอกพื้นที่เกม นอกจากนี้ คุณยังขยายองค์ประกอบที่ไม่ใช่เกมเพลย์ไปยังขอบหน้าจอได้ แม้ว่าเนื้อหาเกมจะยังคงอยู่ตรงกลางก็ตาม โหมดความเข้ากันได้ของระบบช่วยให้เกมพร้อมใช้งานได้ แต่ก็ขึ้นอยู่กับคุณในฐานะนักพัฒนาเกมที่จะทำให้เกมยอดเยี่ยมสำหรับผู้เล่น
ตัวอย่างการใช้งาน Letterbox
เกมเอนจินส่วนใหญ่ช่วยให้คุณควบคุมตำแหน่งที่กล้องแสดงผลบนหน้าจอได้ หากต้องการใช้ Letterbox ของคุณเอง ให้วัดสัดส่วนภาพของพื้นที่ที่แสดงผลและปรับสี่เหลี่ยมผืนผ้าที่ตัดสำหรับพื้นที่ที่ไม่ได้ใช้ แทนที่จะปล่อยให้ระบบแสดงเกมแบบ Letterbox ตัวอย่างต่อไปนี้จำกัดกล้อง 1 ตัวให้แสดงผลในสัดส่วนภาพที่จำกัด ขณะที่อนุญาตให้กล้อง UI หรือการส่งผ่านขยายเป็นขนาดหน้าจอเชิงตรรกะแบบเต็ม
Unity
[SerializeField] private float minAspectRatio = 4f / 3f; [SerializeField] private float maxAspectRatio = 21f / 9f; private Camera _camera; private void Awake() { _camera = GetComponent<Camera>(); } public void MaintainAspectRatio() { int viewWidth = Screen.width; int viewHeight = Screen.height; // 1. Calculate screen aspect ratio float scaleScreen = viewWidth / (float)viewHeight; Rect rect = _camera.pixelRect; // 2. Scale to the fullest of the lower between width or height if (scaleScreen > maxAspectRatio) { // use height, lock width to max at aspect scale rect.width = viewHeight * maxAspectRatio; rect.height = viewHeight; } else if (scaleScreen < minAspectRatio) { // use width, lock height to min at aspect scale rect.width = viewWidth; rect.height = viewWidth / minAspectRatio; } else { // within allowed aspect ratio range, use full screen rect.width = viewWidth; rect.height = viewHeight; } rect.x = Mathf.Floor((viewWidth - rect.width) * 0.5f); rect.y = Mathf.Floor((viewHeight - rect.height) * 0.5f); Debug.Log("camera view width = " + rect.width + " height = " + rect.height + " x = " + rect.x + " y = " + rect.y); // 3. Commit the new size to the camera so that it takes effect _camera.pixelRect = rect; }
C++ (Vulkan)
/** * @brief Calculates a bounded-aspect-ratio gameplay viewport and scissor * rectangle and records them directly into a Vulkan command buffer. * * @note Requires `VK_DYNAMIC_STATE_VIEWPORT` and `VK_DYNAMIC_STATE_SCISSOR` to * be enabled on the bound graphics `VkPipeline`. * * @param command_buffer Active `VkCommandBuffer` in the recording state. * @param window_width Full physical window or swapchain width in pixels. * @param window_height Full physical window or swapchain height in pixels. * @param min_aspect_ratio Minimum allowed aspect ratio (`width / height`). * @param max_aspect_ratio Maximum allowed aspect ratio (`width / height`). */ void MaintainAspectRatio(VkCommandBuffer command_buffer, uint32_t window_width, uint32_t window_height, float min_aspect_ratio, float max_aspect_ratio) { if (command_buffer == VK_NULL_HANDLE || window_width == 0 || window_height == 0 || min_aspect_ratio <= 0.0f || max_aspect_ratio < min_aspect_ratio) { return; } // 1. Calculate screen aspect ratio. const float view_width = static_cast<float>(window_width); const float view_height = static_cast<float>(window_height); const float scale_screen = view_width / view_height; // 2. Scale to the fullest of the lower between width or height. float rect_width = view_width; float rect_height = view_height; if (scale_screen > max_aspect_ratio) { // Use height, lock width to max at aspect scale (pillarbox). rect_width = std::floor(view_height * max_aspect_ratio); rect_height = view_height; } else if (scale_screen < min_aspect_ratio) { // Use width, lock height to min at aspect scale (letterbox). rect_width = view_width; rect_height = std::floor(view_width / min_aspect_ratio); } else { // Within allowed aspect ratio range, use full screen. rect_width = view_width; rect_height = view_height; } const float rect_x = std::floor((view_width - rect_width) * 0.5f); const float rect_y = std::floor((view_height - rect_height) * 0.5f); // 3. Commit the new viewport and scissor to the command buffer so that // subsequent gameplay draw calls are transformed and clipped to this region. const VkViewport viewport = { .x = rect_x, .y = rect_y, .width = rect_width, .height = rect_height, .minDepth = 0.0f, .maxDepth = 1.0f, }; const VkRect2D scissor = { .offset = { .x = static_cast<int32_t>(rect_x), .y = static_cast<int32_t>(rect_y), }, .extent = { .width = static_cast<uint32_t>(rect_width), .height = static_cast<uint32_t>(rect_height), }, }; vkCmdSetViewport(command_buffer, 0, 1, &viewport); vkCmdSetScissor(command_buffer, 0, 1, &scissor); }
ดูคำแนะนำทีละขั้นตอนใน Unity ได้ที่ Codelab การเพิ่มประสิทธิภาพเกม Unity สำหรับหน้าจอขนาดใหญ่และอุปกรณ์แบบพับได้
จัดการหน้าจอขนาดใหญ่และขนาดเล็ก
ในหน้าจอขนาดเล็ก เช่น โทรศัพท์และจอแสดงผลด้านนอกของอุปกรณ์แบบพับได้ ประสบการณ์ของผู้ใช้ที่ดีที่สุดอาจเป็นเกมที่ล็อกแนวตั้งหรือแนวนอน เมื่อหน้าจอมีขนาดใหญ่ขึ้น เช่น แท็บเล็ต, Chromebook, จอแสดงผลในรถยนต์ หรือจอแสดงผลด้านในของอุปกรณ์แบบพับได้ การหมุนอุปกรณ์จึงไม่เป็นที่ต้องการหรือเป็นไปไม่ได้เลย ในขณะที่จอแสดงผลขนาดใหญ่ขึ้นช่วยให้เล่นเกมในสัดส่วนภาพที่ไม่ได้อยู่ในแนวแกนได้
เพื่อให้ผู้เล่นได้รับประสบการณ์ที่ดีที่สุด ให้ตรวจหาขนาดหน้าจอขณะรันไทม์และจำกัดการหมุนเมื่อจำเป็น พร้อมทั้งให้ผู้เล่นมีความยืดหยุ่นมากขึ้นเมื่อขนาดหน้าจอเพิ่มขึ้น Android ถือว่าจุดตัดที่เหมาะสมคือ sw600dp ซึ่งมีความกว้างที่เล็กที่สุดเท่ากับ 600 ความหนาแน่นของพิกเซลอิสระ (600dp)
ซึ่งสอดคล้องกับ WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND ใช้ computeMaximumWindowMetrics เพื่อตรวจสอบขนาดหน้าจอที่ใช้ได้ในการกำหนดค่าแบบหลายจอแสดงผล
หากต้องการรองรับฟีเจอร์นี้ในเกม ให้รองรับการวางแนวทั้งหมดในไฟล์ Manifest จากนั้นประเมินความกว้างที่เล็กที่สุดทั้งใน onCreate() และ onConfigurationChanged() แล้วตั้งค่าการล็อกการวางแนวอย่างเหมาะสม ดังนี้
นำการล็อกการวางแนวแบบคงที่ในไฟล์ Manifest ออกและประกาศการจัดการการเปลี่ยนแปลงการกำหนดค่า ดังนี้
<activity android:name=".MainActivity" android:resizeableActivity="true" android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|density|keyboard|keyboardHidden" />เพิ่มการนําเข้าที่จําเป็น ดังนี้
import android.content.pm.ActivityInfo import android.content.res.Configuration import android.os.Bundle import androidx.activity.enableEdgeToEdge import androidx.window.core.layout.WindowSizeClass import androidx.window.layout.WindowMetricsCalculator import kotlin.math.minจัดการทั้ง
onCreateและonConfigurationChanged:override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) applyAdaptiveOrientationPolicy() // ... } override fun onConfigurationChanged(newConfig: Configuration) { super.onConfigurationChanged(newConfig) applyAdaptiveOrientationPolicy() // ... }อัปเดตการวางแนวที่ขอตามความกว้างของหน้าจอที่เล็กที่สุด โดยล็อกหน้าจอขนาดกะทัดรัดให้เป็นแนวการออกแบบที่ต้องการของเกม ดังนี้
private fun applyAdaptiveOrientationPolicy() { // compute the smallest screen bound in dp val maxMetrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this) val minDimensionPx = min(maxMetrics.bounds.width(), maxMetrics.bounds.height()) val displaySmallestWidthDp = minDimensionPx / maxMetrics.density val targetOrientation = if (displaySmallestWidthDp >= WindowSizeClass.WIDTH_DP_MEDIUM_LOWER_BOUND) { // Large display (>= 600dp): allow free rotation in any orientation ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED } else { // Compact display (< 600dp): lock to your game's preferred orientation // (use SCREEN_ORIENTATION_SENSOR_LANDSCAPE for landscape-first games) ActivityInfo.SCREEN_ORIENTATION_PORTRAIT } // Guard against redundant setter calls to avoid configuration change loops if (requestedOrientation != targetOrientation) { requestedOrientation = targetOrientation } }
ออกแบบโดยคำนึงถึงปัญหาที่พบได้ทั่วไป
การรองรับสัดส่วนภาพและการวางแนวที่หลากหลายจะช่วยให้ผู้เล่นได้รับประสบการณ์การใช้งานที่ดีที่สุด จอแสดงผลขนาดใหญ่มักจะได้รับการแก้ไขในแนวนอนหรือแนวตั้ง ซึ่งต่างจากโทรศัพท์ และในบางกรณีหน้าจอเกือบจะเป็นสี่เหลี่ยมจัตุรัส ในอุปกรณ์ขนาดใหญ่เหล่านี้ ผู้เล่นมักจะทำงานหลายอย่างพร้อมกันเมื่อเล่นเกมของคุณ การใช้พื้นที่หน้าจอให้เกิดประโยชน์สูงสุดจะช่วยให้คุณดึงดูดผู้เล่นได้มากขึ้น บ่อยขึ้น และเล่นเกมได้นานขึ้น
ส่วนต่อไปนี้จะแสดงโซลูชันที่ทำให้เกมของคุณให้ความรู้สึกเหมือนเป็นประสบการณ์ระดับพรีเมียมในรูปแบบของอุปกรณ์ต่างๆ แทนที่จะเป็นเกมโทรศัพท์ที่ฝังอยู่ในหน้าจอที่ไม่ใช่โทรศัพท์
กล้องที่รองรับสัดส่วนภาพ
ในเกม 3 มิติ หากหน้าจอสูงเกินไป ผู้เล่นอาจรู้สึกเหมือนกำลังดูเกมผ่านช่องแคบๆ และหากหน้าจอกว้างเกินไป ผู้เล่นอาจพลาดการโต้ตอบที่ออกแบบไว้ คุณสามารถทำให้ "พื้นที่ปลอดภัย" ปรากฏอยู่เสมอได้เช่นเดียวกับในเกม 2 มิติ โค้ดต่อไปนี้จะสลับกล้องระหว่างขอบเขตการมองเห็นแนวนอนกับขอบเขตการมองเห็นแนวตั้ง โดยอิงตามการเปรียบเทียบสัดส่วนภาพที่ใช้งานอยู่กับสัดส่วนภาพอ้างอิงที่ 1920x1080 วิธีนี้ช่วยให้นักออกแบบสามารถสร้างเกมสำหรับจอแสดงผล 1080p และทราบว่าทุกอย่างที่ออกแบบภายในเฟรมอ้างอิงนั้นจะยังคงมองเห็นได้ ดังนี้
Unity
[SerializeField] private Camera _camera; [SerializeField] private float _referenceWidth = 1920f; [SerializeField] private float _referenceHeight = 1080f; [SerializeField] private float _referenceVerticalFov = 60f; public float ReferenceAspectRatio => _referenceWidth / Mathf.Max(0.0001f, _referenceHeight); private void Awake() { if (_camera == null) { _camera = GetComponent<Camera>(); } } // Built-in Render Pipeline callback. In URP, subscribe to // RenderPipelineManager.beginCameraRendering or call UpdateFov() on resize. private void OnPreCull() { UpdateFov(); } public void UpdateFov() { if (_camera == null || _camera.orthographic) { return; } float referenceAspect = ReferenceAspectRatio; float currentAspect = _camera.aspect; if (currentAspect <= 0.0001f) { return; } float targetVerticalFov; if (currentAspect >= referenceAspect) { // Viewport is wider than (or equal to) the reference safe area targetVerticalFov = _referenceVerticalFov; } else { // Viewport is skinnier than the reference safe area float referenceHorizontalFov = Camera.VerticalToHorizontalFieldOfView(_referenceVerticalFov, referenceAspect); targetVerticalFov = Camera.HorizontalToVerticalFieldOfView(referenceHorizontalFov, currentAspect); targetVerticalFov = Mathf.Clamp(targetVerticalFov, 1f, 179f); } if (!Mathf.Approximately(_camera.fieldOfView, targetVerticalFov)) { _camera.fieldOfView = targetVerticalFov; } }
C++ (Vulkan)
/** * @brief Calculates an aspect-aware Vulkan perspective projection matrix using * GLM that keeps a reference safe area (e.g., 1920x1080) visible across * aspect ratios. * * @note Uses `glm::perspectiveZO` for Vulkan's `[0, 1]` depth range and * inverts `projection[1][1]` for Vulkan's top-left (`+Y` down) clip space. * * @param viewport_width Active gameplay viewport width in pixels. * @param viewport_height Active gameplay viewport height in pixels. * @param reference_width Authored safe-area reference width in pixels. * @param reference_height Authored safe-area reference height in pixels. * @param reference_vertical_fov Authored vertical FOV in degrees (e.g., 60.0f). * @param near_plane Near clipping plane distance (`zNear > 0.0f`). * @param far_plane Far clipping plane distance (`zFar > zNear`). * @return Aspect-aware `glm::mat4` perspective projection matrix for Vulkan. */ glm::mat4 CalculateAspectAwareProjectionMatrix( float viewport_width, float viewport_height, float reference_width = 1920.0f, float reference_height = 1080.0f, float reference_vertical_fov = 60.0f, float near_plane = 0.1f, float far_plane = 100.0f) { if (viewport_width <= 0.0001f || viewport_height <= 0.0001f) { return glm::mat4(1.0f); } // 1. Compare the active viewport aspect ratio against the reference safe // area. const float reference_aspect = reference_width / std::max(0.0001f, reference_height); const float current_aspect = viewport_width / viewport_height; float target_vertical_fov_rad = glm::radians(reference_vertical_fov); if (current_aspect >= reference_aspect) { // Viewport is wider than (or equal to) the reference safe area (Hor+). target_vertical_fov_rad = glm::radians(reference_vertical_fov); } else { // Viewport is skinnier than the reference safe area (Vert+): // Convert reference vertical FOV -> reference horizontal FOV -> new // vertical FOV at current_aspect so the safe area is never cropped. const float tan_half_horiz = std::tan(target_vertical_fov_rad * 0.5f) * reference_aspect; target_vertical_fov_rad = 2.0f * std::atan(tan_half_horiz / current_aspect); target_vertical_fov_rad = std::clamp( target_vertical_fov_rad, glm::radians(1.0f), glm::radians(179.0f)); } // 2. Build the Vulkan [0, 1] depth perspective matrix and flip +Y clip space. glm::mat4 projection = glm::perspectiveZO( target_vertical_fov_rad, current_aspect, near_plane, far_plane); projection[1][1] *= -1.0f; return projection; }
Letterbox แบบอินเทอร์แอกทีฟเต็มรูปแบบ
เกมบางเกมมีพื้นที่การเล่นที่คงที่ตามการออกแบบ ซึ่งมักจะตรงกับการพิจารณาการออกแบบตามประเภท เช่น สนามคงที่ของเกมยิงแนวตั้งหรือการเลื่อนหน้าจอแบบพลิกที่ใช้เพื่อความสวยงามแบบย้อนยุค
สำหรับเกมเหล่านี้ ให้ปรับขนาดพื้นที่เกมเพลย์ให้พอดีเพื่อให้แกนหนึ่งของเกมขยายใหญ่สุดเพื่อเติมเต็มพื้นที่เกมเพลย์เสมอ แกนที่ขยายใหญ่สุดอาจเปลี่ยนแปลงได้ตามสัดส่วนภาพสัมพัทธ์ของเกมและขอบเขตการแสดงผล
ยึด HUD และองค์ประกอบ UI ทั้งหมดไว้ที่ขอบที่ปลอดภัยของหน้าจอ โดยหลีกเลี่ยงส่วนที่ถูกตัดออก แต่ให้วางองค์ประกอบแบบอินเทอร์แอกทีฟ เช่น ตัวควบคุมเสมือน แถบพลังชีวิต และแผนที่ย่อ ให้อยู่นอกพื้นที่เกมเพลย์ให้มากที่สุด วิธีนี้จะทำให้ส่วนอินเทอร์แอกทีฟของเกมใช้ทั้งหน้าจอ และผู้เล่นในอุปกรณ์รูปแบบต่างๆ เช่น แท็บเล็ตและอุปกรณ์แบบพับได้ จะเล่นเกมของคุณได้อย่างสะดวกสบายโดยไม่ต้องยืดนิ้วมากเกินไป
สุดท้าย ให้สร้างพื้นที่ Letterbox ที่มีธีมหรือเรื่องราวที่เหมาะสม ลองใช้ขอบที่เข้ากับจานสีหรือชุดไทล์บนหน้าจอ โต๊ะหรือหน้าจอเสมือนจริงสำหรับเกมกระดานหรือเกมย้อนยุค หรือแผนที่ย่อแบบขยายและภาพตกแต่ง
ในตัวอย่างต่อไปนี้ เกมจะแสดงผลแบบเต็มขนาดสำหรับสัดส่วนภาพส่วนใหญ่ เมื่อสัดส่วนภาพแคบกว่า 4:3 ระบบจะแสดงผลสกายบ็อกซ์ที่มีสีตามธีมในขณะที่ยังคงวางองค์ประกอบ UI เช่น ตัวควบคุม ไว้ที่ขอบหน้าจอ
|
|
หมอกแห่งสงคราม
นักพัฒนาเกมหลายรายกังวลว่าผู้เล่นอาจได้รับข้อได้เปรียบที่ไม่เป็นธรรมจากสัดส่วนภาพแนวตั้งหรือแนวนอนที่มากเกินไป ตัวอย่างเช่น ผู้เล่นในเกมที่มีการแข่งขันสูงอย่างสนามประลองออนไลน์ที่มีผู้เล่นหลายคน (MOBA) อาจใช้หน้าจอแนวตั้งมากๆ เพื่อให้มองเห็นเลนของคู่ต่อสู้ได้ลึกขึ้น
สำหรับเกมกลยุทธ์และเกมจำลองสถานการณ์แบบมุมมองจากบนลงล่าง ให้พิจารณาแสดงผลหมอกแห่งสงคราม ดังนี้
- อย่าแสดงผลเรขาคณิตเลยจนกว่าผู้เล่นจะดูได้
- แสดงผลเรขาคณิตที่ตัวละครของผู้เล่นมองไม่เห็นอย่างชัดเจนเป็นสีหม่น โดยไม่มีองค์ประกอบแบบไดนามิก
- แสดงผลเฉพาะคู่ต่อสู้ ของสะสม และวัตถุแบบไดนามิกอื่นๆ ที่ตัวละครของผู้เล่นสามารถมองเห็นได้อย่างชัดเจนในโลกของเกม
หากคุณใช้เทคนิคนี้ร่วมกับแถบสีดำแบบอินเทอร์แอกทีฟเต็มรูปแบบและแสดงผล UI ที่ขอบหน้าจอ ผู้เล่นจะได้รับประสบการณ์ที่ทั้งดูดีและตั้งใจโดยที่คุณไม่ต้องออกแบบโครงสร้างระดับหรือความสมดุลของทีมใหม่
การขยายเกมนี้ให้เต็มหน้าจอขนาดใหญ่ขึ้นโดยไม่มีหมอกแห่งสงครามจะเผยให้เห็นส่วนต่างๆ ของแผนที่ที่ผู้เล่นไม่ควรเห็น ดังนี้
|
|
การแสดงผลหมอกแห่งสงครามและซ่อนองค์ประกอบแบบไดนามิก เช่น ศัตรูและไอเทม จะช่วยรักษาความยุติธรรมในเกมขณะใช้เฟรมเต็มรูปแบบที่เกมมีให้ ดังนี้
|
|
เรขาคณิตค่อยๆ จางหายไป
เกมจำนวนมาก โดยเฉพาะในพื้นที่กลยุทธ์แบบผลัดกันเล่น ใช้เทคนิคที่คล้ายกับหมอกแห่งสงครามที่อธิบายไว้ในส่วนก่อนหน้า และไม่แสดงผลเรขาคณิตที่ผู้เล่นยังไม่ได้ค้นพบหรือที่ผู้เล่นไม่สามารถโต้ตอบด้วยได้ในระหว่างฉากหนึ่งๆ
หากขอบเขตการมองเห็นที่ขยายออกจะเผยให้เห็นส่วนต่างๆ ของฉากหรือภาพยนตร์ที่ผู้เล่นไม่ควรเห็น การมาสก์บางส่วนของฉากด้วยวิธีที่ออกแบบมาอย่างเรียบร้อยจะให้ผลลัพธ์ที่เหมือนกับการใช้แถบดำโดยไม่มีการรับรู้ถึงขอบเขตที่คงที่
ในตัวอย่างต่อไปนี้ การขยายเกมให้มีสัดส่วนภาพที่ใหญ่ขึ้นจะเผยให้เห็นฝูงซอมบี้นอกกำแพงปราสาท
|
|
แต่คุณสามารถละเว้นการแสดงผลเรขาคณิตของระดับที่อยู่นอกขอบเขตของพื้นที่เล่นปัจจุบันได้ ดังนี้
|
|
ขอบเขตที่สอดคล้องกับเนื้อเรื่อง
ในเกม 3 มิติที่สมจริงซึ่งขอบเขตการมองเห็นที่กว้างขึ้นอาจทำให้ได้เปรียบในการแข่งขันในเกมแบบผู้เล่นหลายคนในมุมมองบุคคลที่หนึ่งหรือบุคคลที่สาม หรือเปิดเผยพื้นที่ที่ไม่ได้สร้างขึ้นในเกมแบบฉากคงที่ ให้พิจารณาสร้างองค์ประกอบที่สมจริงในเกมเพื่อจำกัดขอบเขตการมองเห็นแทนที่จะใช้แถบสีดำสี่เหลี่ยมผืนผ้า ตัวอย่างเช่น
- ห้องคนขับภายในยานพาหนะ เช่น รถยนต์หรือเครื่องบิน
- ด้านในของหมวกกันน็อก
- ขอบภาพมืดที่แสดงขอบเขตการมองเห็นของผู้เล่น
องค์ประกอบ UI และ HUD ควรขยายไปจนถึงขอบหน้าจอหรือรวมไว้ในขอบเขตของเรื่องราว และควรทำให้เป็นแบบไดนามิก องค์ประกอบในเรื่องเหล่านี้ยังช่วยผู้เล่นที่รู้สึกเวียนศีรษะได้ด้วย โดยเฉพาะในรูปแบบของอุปกรณ์ XR ซึ่งจะช่วยเพิ่มการช่วยเหลือพิเศษนอกเหนือจากการช่วยลดความซับซ้อนของสัดส่วนภาพใหม่ๆ
หลีกเลี่ยงการแสดงผลเกมบนพื้นผิวภายในฉากนิ่งที่ไม่ใช่แบบอินเทอร์แอกทีฟ แม้ว่าแนวทางดังกล่าวจะดีกว่าการแสดงผลแถบสีดำสำหรับ Letterbox และ Pillarbox แต่ผู้เล่นจะสังเกตเห็นขอบที่คงที่ได้อย่างรวดเร็ว และอาจรู้สึกหงุดหงิดหากเกมโปรดแสดงผลเป็นแพตช์หน้าจอขนาดโทรศัพท์ในรูปแบบที่ไม่ใช่โทรศัพท์
|
ในตัวอย่างนี้ เกมที่ออกแบบมาสำหรับหน้าจอโทรศัพท์มาตรฐานจะแสดงผลภายในโทรศัพท์จำลองที่มีเกมแพดแบบเสมือนจริงเพื่อรองรับสัดส่วนภาพสี่เหลี่ยมจัตุรัสที่พบได้ทั่วไปในจอแสดงผลด้านในของอุปกรณ์แบบพับได้
|
เกม 3 มิติบางเกมอาจต้องจำกัดขอบเขตการมองเห็นเพื่อความยุติธรรมในการแข่งขันหรือเพื่อพิจารณาการออกแบบ การใช้ห้องนักบิน หมวกนิรภัย หรืออุปมาอุปไมยอื่นๆ ที่เป็นส่วนหนึ่งของเรื่องราวเพื่อจำกัดขอบเขตการมองเห็นนั้นดีกว่าการใช้แถบสีดำ
|
แหล่งข้อมูลเพิ่มเติม
- ทำให้เกม Unity ของคุณทำงานได้ดีในอุปกรณ์ทุกรูปแบบ
- ทำให้เกมของคุณเข้ากันได้กับอุปกรณ์ทุกรูปแบบ
- เปิดใช้การป้อนข้อมูลที่เป็นธรรมชาติในอุปกรณ์ทุกรูปแบบ
- จัดการการวางแนวอุปกรณ์ด้วยการหมุนล่วงหน้าของ Vulkan