MegaBookInputController

MegaBookInputController



Unity C# Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;

namespace MegaBook
{
    public class MegaBookInputController : MonoBehaviour
    {
        [System.Serializable]
        public class PageAudioSetting
        {
            [Header("頁數")]
            public int pageIndex = 0;

            [Header("此頁語音")]
            public AudioClip pageAudio;

            [Header("語音播完後是否自動下一頁")]
            public bool autoNextAfterAudio = false;
        }

        [Header("指定原本的 MegaBookControl")]
        public MegaBookControl bookControl;

        [Header("頁面語音設定")]
        public AudioSource pageVoiceAudioSource;

        [Tooltip("進入有設定語音的頁面時,是否自動播放該頁語音")]
        public bool autoPlayPageVoice = true;

        [Tooltip("語音播放期間是否禁止下一頁")]
        public bool lockNextPageWhileVoicePlaying = true;

        [Tooltip("手動按下一頁時,是否允許中斷目前頁面的語音並翻到下一頁")]
        public bool allowManualNextPageInterruptVoice = true;

        [Tooltip("如果目前頁面沒有指定語音,是否允許直接下一頁")]
        public bool allowNextPageIfNoVoice = true;

        public List<PageAudioSetting> pageAudioSettings = new List<PageAudioSetting>();

        [Header("鍵盤設定")]
        public KeyCode keyboardPrevPageKey = KeyCode.LeftArrow;
        public KeyCode keyboardNextPageKey = KeyCode.RightArrow;

        [Header("XBOX 搖桿設定")]
        public KeyCode xboxNextPageKey = KeyCode.JoystickButton0; // A:下一頁
        public KeyCode xboxPrevPageKey = KeyCode.JoystickButton1; // B:上一頁

        [Header("Quest 手把設定")]
        public bool enableQuestController = true;

        private bool canGoNextPage = true;
        private Coroutine pageVoiceCoroutine;

        private bool lastQuestAState = false;
        private bool lastQuestBState = false;

        void Start()
        {
            StartCurrentPageVoice();
        }

        void Update()
        {
            if (bookControl == null)
                return;

            CheckKeyboardInput();
            CheckXboxInput();
            CheckQuestInput();
        }

        void CheckKeyboardInput()
        {
            if (Input.GetKeyDown(keyboardPrevPageKey))
            {
                PrevPage();
            }

            if (Input.GetKeyDown(keyboardNextPageKey))
            {
                TryNextPage();
            }
        }

        void CheckXboxInput()
        {
            if (Input.GetKeyDown(xboxNextPageKey))
            {
                TryNextPage();
            }

            if (Input.GetKeyDown(xboxPrevPageKey))
            {
                PrevPage();
            }
        }

        void CheckQuestInput()
        {
            if (!enableQuestController)
                return;

            InputDevice rightHand = InputDevices.GetDeviceAtXRNode(XRNode.RightHand);

            if (!rightHand.isValid)
                return;

            bool questAState = false;
            bool questBState = false;

            // Quest 右手 A 鍵:下一頁
            if (rightHand.TryGetFeatureValue(CommonUsages.primaryButton, out questAState))
            {
                if (questAState && !lastQuestAState)
                {
                    TryNextPage();
                }

                lastQuestAState = questAState;
            }

            // Quest 右手 B 鍵:上一頁
            if (rightHand.TryGetFeatureValue(CommonUsages.secondaryButton, out questBState))
            {
                if (questBState && !lastQuestBState)
                {
                    PrevPage();
                }

                lastQuestBState = questBState;
            }
        }

        public void TryNextPage()
        {
            if (!canGoNextPage)
            {
                if (allowManualNextPageInterruptVoice)
                {
                    Debug.Log("手動翻到下一頁,停止目前頁面語音。");
                    NextPage();
                    return;
                }

                Debug.Log("目前頁面語音尚未播放完畢,暫時不能翻到下一頁。");
                return;
            }

            NextPage();
        }

        public void NextPage()
        {
            if (bookControl == null)
                return;

            // 先停止目前頁面的語音
            StopCurrentPageVoice();

            // 翻到下一頁
            bookControl.NextPage();

            // 播放新頁面的語音
            StartCurrentPageVoice();
        }

        public void PrevPage()
        {
            if (bookControl == null)
                return;

            // 先停止目前頁面的語音
            StopCurrentPageVoice();

            // 翻到上一頁
            bookControl.PrevPage();

            // 播放新頁面的語音
            StartCurrentPageVoice();
        }

        void StartCurrentPageVoice()
        {
            if (!autoPlayPageVoice)
            {
                canGoNextPage = true;
                return;
            }

            if (pageVoiceCoroutine != null)
            {
                StopCoroutine(pageVoiceCoroutine);
                pageVoiceCoroutine = null;
            }

            pageVoiceCoroutine = StartCoroutine(CurrentPageVoiceRoutine());
        }

        IEnumerator CurrentPageVoiceRoutine()
        {
            PageAudioSetting setting = GetCurrentPageAudioSetting();

            if (setting == null || setting.pageAudio == null)
            {
                canGoNextPage = allowNextPageIfNoVoice;
                yield break;
            }

            if (pageVoiceAudioSource == null)
            {
                Debug.LogWarning("尚未指定 Page Voice Audio Source,無法播放頁面語音。");
                canGoNextPage = true;
                yield break;
            }

            if (lockNextPageWhileVoicePlaying)
            {
                canGoNextPage = false;
            }
            else
            {
                canGoNextPage = true;
            }

            pageVoiceAudioSource.Stop();
            pageVoiceAudioSource.clip = setting.pageAudio;
            pageVoiceAudioSource.Play();

            yield return new WaitWhile(() => pageVoiceAudioSource != null && pageVoiceAudioSource.isPlaying);

            canGoNextPage = true;

            if (setting.autoNextAfterAudio)
            {
                NextPage();
            }
        }

        void StopCurrentPageVoice()
        {
            if (pageVoiceCoroutine != null)
            {
                StopCoroutine(pageVoiceCoroutine);
                pageVoiceCoroutine = null;
            }

            if (pageVoiceAudioSource != null && pageVoiceAudioSource.isPlaying)
            {
                pageVoiceAudioSource.Stop();
            }

            canGoNextPage = true;
        }

        PageAudioSetting GetCurrentPageAudioSetting()
        {
            if (bookControl == null || bookControl.book == null)
                return null;

            int currentPage = Mathf.RoundToInt(bookControl.book.page);

            for (int i = 0; i < pageAudioSettings.Count; i++)
            {
                if (pageAudioSettings[i].pageIndex == currentPage)
                {
                    return pageAudioSettings[i];
                }
            }

            return null;
        }

        public int GetCurrentPageIndex()
        {
            if (bookControl == null || bookControl.book == null)
                return -1;

            return Mathf.RoundToInt(bookControl.book.page);
        }
    }
}