protected override void Awake() { base.Awake(); var version = new IntReactiveProperty(0); var sentVersion = -1; responses.Observe() .Subscribe(ignored => { version.Value = version.Value + 1; }) .AddTo(this); for (var i = 0; i < m_ChatBoxViews.Length; i++) { var j = i; var view = m_ChatBoxViews[i]; view.button.OnPointerClickAsObservable() .Where(ignored => view.button.interactable) .Subscribe(v => { if (m_PostOwnMessages) { m_ConversationController.Add(new ChatMessage[] { new ChatMessage() { self = true, message = view.data } }); } SetChatBoxesInteractive(false); sentVersion = version.Value; m_Choices.OnNext(new ChatBoxChoice() { index = j, text = view.data }); }) .AddTo(view); } m_InputBox.OnPointerClickAsObservable() .Where(ignored => !m_IsRequestingTextInput) .Subscribe(ignored => { m_Open.Value = !m_Open.Value; m_ConversationController.ThrottledScrollToBottom(); }) .AddTo(this); Observable.Merge( responses.Observe().AsUnitObservable(), m_Open.StartWith(false).AsUnitObservable()) .BatchFrame(1, FrameCountType.Update) .Subscribe(ignored => { var count = responses.Count; var isOpen = m_Open.Value; if (count == 0) { isOpen = false; } else { if (m_Open.Value) { m_ConversationController.StartTyping(true); } else { m_ConversationController.StopTyping(); } } for (var i = 0; i < m_ChatBoxViews.Length; i++) { if (i < count) { m_ChatBoxViews[i].data = responses[i]; } else { m_ChatBoxViews[i].data = null; } m_ChatBoxViews[i].gameObject.SetActive(isOpen && i < count); } m_InputBox.interactable = count > 0; SetChatBoxesInteractive(version.Value != sentVersion); }) .AddTo(this); // The input text that this has is only enabled when the user actually has to type something in. m_SpacerForKeyboard.gameObject.SetActive(false); m_KeyboardConnector.enabled = false; }