// This sets up the variables we need when entering dialogue public void StartDialogue() { // Set the interaction state m_interactionState = InteractionState.Talking; // Unlock the cursor Cursor.lockState = CursorLockMode.None; // Deactivate the crosshair m_crosshair.gameObject.SetActive(false); // Deactivate the hover image m_hoverImage.gameObject.SetActive(false); // Set the look point m_lookPoint = hitInRange.transform.gameObject.GetComponent <DialogueNode>().LookPoint; UpdateDialogueName(); // Reset the text m_dialogueText.text = ""; // Get the dialogue we beed m_dialogue = hitInRange.collider.GetComponent <DialogueNode>().Dialogue[0]; // Creating a new stack for the previous dialogues m_dialoguePrev = new Stack <DNode>(); // Getting the outline width m_interactObjectOutlineBeforeDialogue = GetObjectMaterialFloat(hitInRange.collider.gameObject, "_OutlineWidth"); // Setting this enum so that we move into the setup // IEnumerator after this function m_dialogueEnum = dialogueEnumerator.Setup; }
// This method gets called when a button is pressed through a script on the buttons that // sends its sibling index public void OptionsButtonClick(int a_buttonIndex) { // Set the GUI objects to start displaying dialogue text and // stop displaying dialogue options m_dialogueText.gameObject.SetActive(true); m_dialogueButtonsContainer.transform.parent.transform.parent.gameObject.SetActive(false); // If the button that has been pressed is last in the list then it is the exit // dialogue button so this just exits the dialogue if (a_buttonIndex == m_dialogueButtonsContainer.transform.childCount - 1) { m_dialogueEnum = dialogueEnumerator.Exit; m_dialogueIEnumRunning = false; return; } // We can do the same for the back button here if this is not the // first dialogue if (!m_dialogue.FirstDialogue && a_buttonIndex == m_dialogueButtonsContainer.transform.childCount - 2) { m_dialogue = m_dialoguePrev.Pop(); m_dialogueEnum = dialogueEnumerator.Options; m_dialogueIEnumRunning = false; return; } // Set the dialogue options so it has been read/selected m_dialogue.options[a_buttonIndex].hasBeenRead = true; // Invoke the events that are set to this dialogue option m_AfterDialogueActions = m_dialogue.options[a_buttonIndex].eventsOnDialogueFinish; // If we don't need to return to the dialogue once an option is read then set the next dialogue option if (!m_dialogue.options[a_buttonIndex].ReturnOnceRead) { // We have a stack of dialogues so that we can go back, we add the current one // here before it is set to something else m_dialoguePrev.Push(m_dialogue); // Set the dialogue to the net dialogue foreach (DNode dialogue in hitInRange.collider.GetComponent <DialogueNode>().Dialogue) { if (dialogue._ID == m_dialogue.options[a_buttonIndex].nextID) { m_dialogue = dialogue; break; } } } // Else set the dialogue text overwrite else { foreach (DNode dialogue in hitInRange.collider.GetComponent <DialogueNode>().Dialogue) { if (dialogue._ID == m_dialogue.options[a_buttonIndex].nextID) { m_dialogueTextOverwrite = dialogue.dialogueText; break; } } } // Set the variables m_dialogueEnum = dialogueEnumerator.Talking; m_dialogueIEnumRunning = false; }
// Displaying dialogue text slowly, can be interupted by pressing the interaction key private IEnumerator DisplayDialogue() { UpdateDialogueName(); // A variable used for tracking time, // I could use // yield return new WaitForSeconds(time) // however I want to check for button presses while waiting float t = 0f; // Set the sentances to be displayed. // This should just be the current dialogue text List <string> sentancesToBeDisplayed = m_dialogue.dialogueText; // However if the dialogue overwrite is not null then display that instead if (m_dialogueTextOverwrite != null) { sentancesToBeDisplayed = m_dialogueTextOverwrite; } // For each sentance that we need to display foreach (string sentance in sentancesToBeDisplayed) { // Reset the text m_dialogueText.text = ""; // For each letter in that sentance foreach (char letter in sentance) { // If we have pressed the interaction key this will be true if (m_skipSentance) { // Load all the text m_dialogueText.text = sentance; // Reset the variable m_skipSentance = false; // Break out of the loop since we don't need to load any more letters break; } // Add a letter to the dialogue text m_dialogueText.text = m_dialogueText.text + letter; // Player audio for the letters m_aSrc.pitch = UnityEngine.Random.Range(hitInRange.collider.gameObject.GetComponent <DialogueNode>().VoicePitch.x, hitInRange.collider.gameObject.GetComponent <DialogueNode>().VoicePitch.y); m_aSrc.PlayOneShot(hitInRange.collider.gameObject.GetComponent <DialogueNode>().VoiceSound); // Wait for the amount of time between // For this we could use // yield return new WaitForSeconds(time) // but I don't think it really matters, // they have the same effect and probably do the same thing t = Time.time + m_textDelay; while (Time.time < t) { yield return(null); } } // Waiting for time in between sentances // This one does actually need to be like this // and not a WaitForSeconds as we need to check // if we need to move to the next sentance. // The delay on this is pretty small (probably 0.25 seconds) // however I wanted to make sure there is enough time // for the m_skipSentance variable to be reset so // the player doesn't accidentally skip any dialogue t = Time.time + m_timeBetweenSentances; while (Time.time < t || !m_skipSentance) { yield return(null); } m_skipSentance = false; } // Reset the dialogue sentances overwrite m_dialogueTextOverwrite = null; // Invoke after dialogue actions and reset the variable if (m_AfterDialogueActions != null) { m_AfterDialogueActions.Invoke(); m_AfterDialogueActions = null; } // Set the variables m_dialogueEnum = dialogueEnumerator.Options; m_dialogueIEnumRunning = false; }
// Setting up dialogue // This just tweens the alpha of all the GUI we need, Lerps the player // camera direction towards to the look point position, and Lerps the // outline of the target private IEnumerator SetupDialogue() { float t = Time.time; // For lerping where the player is looking Vector3 directionFromCamera = m_lookPoint.position - m_playerCamera.position; Quaternion cameraRotation = Quaternion.LookRotation(directionFromCamera); float cameraDot = Vector3.Dot(directionFromCamera.normalized, m_playerCamera.forward); // For lerping FOV m_FOV = Camera.main.fieldOfView; // For lerping the GUI alpha float alpha = 0f; // For lerping the target outline float m_interactObjectOutlineBeforeDialogue = GetObjectMaterialFloat(hitInRange.collider.gameObject, "_OutlineWidth"); float outln = m_interactObjectOutlineBeforeDialogue; yield return(null); while (cameraDot < 0.9f || alpha < 0.9f || Camera.main.fieldOfView > m_lookTowardsFOV || outln > m_interactObjectOutlineBeforeDialogue * 0.25f) { // Using the constant 0.015f for lerping replaces the need for Time.deltatime // I would prefer to use deltatime however that produces some anomalies // in the transition // Look rotation m_playerCamera.rotation = Quaternion.Slerp(m_playerCamera.rotation, cameraRotation, 0.015f * m_lookTowardsSpeed * 2); cameraDot = Vector3.Dot(directionFromCamera.normalized, m_playerCamera.forward); float lerp_t = (Time.time - t) * 0.015f * m_dialogueTransitionSpeed; // FOV Camera.main.fieldOfView = Mathf.Lerp(m_FOV, m_lookTowardsFOV, lerp_t); // GUI alpha alpha = Mathf.Lerp(0f, 1f, lerp_t); Color lerpColorBG = m_dialogueBackground.color; lerpColorBG.a = alpha; m_dialogueBackground.color = lerpColorBG; Color lerpColorName = m_dialogueName.color; lerpColorName.a = alpha; // These colours are the same so why not save some processing time and use the same one m_dialogueName.color = lerpColorName; m_dialogueText.color = lerpColorName; // Target outline SetObjectMaterialFloat(hitInRange.collider.gameObject, "_OutlineWidth", Mathf.Lerp(outln, m_interactObjectOutlineBeforeDialogue * 0.25f, lerp_t)); //hitInRange.collider.gameObject.GetComponent<Renderer>().material.SetFloat("_OutlineWidth", Mathf.Lerp(outln, m_interactObjectOutlineBeforeDialogue * 0.25f, lerp_t)); outln = GetObjectMaterialFloat(hitInRange.collider.gameObject, "_OutlineWidth"); //outln = hitInRange.collider.gameObject.GetComponent<Renderer>().material.GetFloat("_OutlineWidth"); yield return(null); } // Set these variables m_dialogueEnum = dialogueEnumerator.Talking; m_dialogueIEnumRunning = false; }