How to setup 4 Canvas/UIs.

Announcements, support questions, and discussion for the Dialogue System.
funcookergames
Posts: 12
Joined: Tue May 21, 2019 9:36 pm

Re: How to setup 4 Canvas/UIs.

Post by funcookergames »

Yes, like Escape. I think it makes more sense to have the general skip entry function be something like Enter, and the the entire skip conversation be Esc.
funcookergames
Posts: 12
Joined: Tue May 21, 2019 9:36 pm

Re: How to setup 4 Canvas/UIs.

Post by funcookergames »

Hey Tony, have you had a chance to think about this?
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to setup 4 Canvas/UIs.

Post by Tony Li »

Yes. I'm sorry, I forgot to post the example scene. When I get back into the office later today I'll post it here. Thanks for the reminder.
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to setup 4 Canvas/UIs.

Post by Tony Li »

I thought of a potential issue with SetContinueMode. I'll resolve it tomorrow morning and post the example as soon as I can.
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to setup 4 Canvas/UIs.

Post by Tony Li »

Sorry again for the delay. Just before I was about to post yesterday, an idea occurred to me that makes the setup much simpler and cleaner.

Here's an example:

WallsExample2_2019-05-29.unitypackage

This example doesn't use SetContinueMode(). Instead of coordinating lots of SetContinueMode() commands in your dialogue entry nodes' Sequence fields, it simply uses a custom dialogue entry field named "Skippable". If this field is true, the dialogue entry is skippable. Otherwise it can't be skipped.

I also added a similar custom field named "Cancelable" to conversations. If this field is true, the entire conversation is cancelable.

To set it up, I added the fields to the Templates section and selected Menu > Apply Template To Assets:

Image

I also ticked the Main checkboxes so they'd appear in the main inspector section:

Image

The walls use a small subclass of StandardDialogueUI that adds two methods: one to skip the current subtitle if allowed, another to cancel the conversation if allowed.

For the example, I wrote some short example scripts for the cube, rooms, and MrSceneManager. You'll use your own scripts for those of course, but you can copy the few lines of code in the example Cube script that skip and cancel.

The scripts are in the package above, but I'll also paste them here for reference:
WallDialogueUI.cs

Code: Select all

using PixelCrushers.DialogueSystem;

namespace WallsExample
{

    /// <summary>
    /// This is a version of StandardDialogueUI that adds methods to skip the
    /// current dialogue entry (if its custom Skippable field is true) or
    /// cancel the conversation (if the conversation's Cancelable field is true).
    /// </summary>
    public class WallDialogueUI : StandardDialogueUI
    {
        private Subtitle currentSubtitle;

        public override void ShowSubtitle(Subtitle subtitle)
        {
            currentSubtitle = subtitle;
            base.ShowSubtitle(subtitle);
        }

        public void SkipCurrentDialogueEntry()
        {
            if (isOpen && currentSubtitle != null)
            {
                var isSkippable = Field.LookupBool(currentSubtitle.dialogueEntry.fields, "Skippable");
                if (isSkippable)
                {
                    OnContinueConversation();
                }
            }
        }

        public void CancelCurrentConversation()
        {
            if (isOpen && currentSubtitle != null)
            {
                var conversationID = currentSubtitle.dialogueEntry.conversationID;
                var isCancelable = DialogueManager.masterDatabase.GetConversation(conversationID).LookupBool("Cancelable");
                if (isCancelable)
                {
                    OnClick(null);
                }
            }
        }
    }
}
Cube.cs

Code: Select all

using PixelCrushers.DialogueSystem;
using UnityEngine;

namespace WallsExample
{

    public class Cube : MonoBehaviour
    {
        public bool allowJump = false;
        public bool allowMove = false;
        public bool allowLook = false;

        public Room room;

        private Rigidbody rb;
        private float nextTimeAllowedToRotate;

        private void Awake()
        {
            rb = GetComponent<Rigidbody>();
        }

        private void OnCollisionEnter(Collision collision)
        {
            Sequencer.Message("CubeLanded");
        }

        // Handles jump, look, and move. Also handles skip and cancel conversation.
        private void Update()
        {
            var horizontal = Input.GetAxis("Horizontal");
            var vertical = Input.GetAxis("Vertical");
            var isArrowKeyPressed = (Mathf.Abs(horizontal) + Mathf.Abs(vertical)) > 0.1;
            var isShiftPressed = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
            if (allowJump && Input.GetKeyDown(KeyCode.Space))
            {
                // Jump:
                rb.AddForce(Vector3.up * 500);
                Sequencer.Message("CubeJumped");
            }
            if (allowLook && isShiftPressed && isArrowKeyPressed && Time.time >= nextTimeAllowedToRotate)
            {
                // Look:
                var angle = (horizontal < 0.1 || vertical < 0.1) ? -90 : 90;
                room.Rotate(angle);
                nextTimeAllowedToRotate = Time.time + 1; // Wait 1 second between rotations.
                Sequencer.Message("CubeLooked");
            }
            else if (allowMove && isArrowKeyPressed)
            {
                // Move:
                rb.MovePosition(transform.position - new Vector3(horizontal * Time.deltaTime, 0, vertical * Time.deltaTime));
                Sequencer.Message("CubeMoved");
            }
            else if (Input.GetKeyDown(KeyCode.Return) && DialogueManager.isConversationActive)
            {
                foreach (var dialogueUI in FindObjectsOfType<WallDialogueUI>())
                {
                    dialogueUI.SkipCurrentDialogueEntry();
                }
            }
            else if (Input.GetKeyDown(KeyCode.Escape) && DialogueManager.isConversationActive)
            {
                foreach (var dialogueUI in FindObjectsOfType<WallDialogueUI>())
                {
                    dialogueUI.CancelCurrentConversation();
                }
            }
        }

        // Show help text:
        private void OnGUI()
        {
            GUILayout.Label("Enter=skip, Escape=cancel");
        }

    }
}
Room.cs

Code: Select all

using UnityEngine;

namespace WallsExample
{
    public class Room : MonoBehaviour
    {
        public GameObject[] walls;

        private void Start()
        {
            CheckWallVisibility();
        }

        public void Rotate(float angle)
        {
            transform.Rotate(new Vector3(0, angle, 0));
            CheckWallVisibility();
        }

        private void CheckWallVisibility()
        {
            // Use dot product to decide if front of each wall is visible:
            foreach (var wall in walls)
            {
                var forward = wall.transform.forward;
                var toCamera = Camera.main.transform.position - wall.transform.position;
                var isFrontVisible = Vector3.Dot(forward, toCamera) >= 0;
                wall.SetActive(isFrontVisible);
            }
        }
    }
}
MrSceneManager.cs

Code: Select all

using UnityEngine;

namespace WallsExample
{
    public class MrSceneManager : MonoBehaviour
    {
        private Cube cube;

        private void Awake()
        {
            cube = FindObjectOfType<Cube>();
        }

        public void CubeDrop()
        {
            cube.GetComponent<Rigidbody>().useGravity = true;
        }

        public void CubeCanJump()
        {
            cube.allowJump = true;
        }

        public void CubeCanMove()
        {
            cube.allowMove = true;
        }

        public void CubeCanLook()
        {
            cube.allowLook = true;
        }
    }
}
In the example conversations, I removed all the SetContinueMode() commands from the dialogue entry nodes' Sequence fields. They're much cleaner now because they only contain the commands that are relevant for each node, such as which message to wait for.

p.s. - To change a dialogue UI's script from StandardDialogueUI to WallDialogueUI without losing references to its UI elements, use the triple-bar menu in the upper right of the inspector to switch to Debug mode. Then drag WallDialogueUI.cs into the dialogue UI's Script field.
funcookergames
Posts: 12
Joined: Tue May 21, 2019 9:36 pm

Re: How to setup 4 Canvas/UIs.

Post by funcookergames »

Image

My goodness. Thank you so much... your example and scripts are extremely helpful in better understanding the tool and this particular use case. We are in the middle of ripping apart our scripts, but as soon as we re-rig the Dialogue System, I will let you know how it goes.

Thank you very much again. Best part of buying the product has been the support. :)
User avatar
Tony Li
Posts: 22056
Joined: Thu Jul 18, 2013 1:27 pm

Re: How to setup 4 Canvas/UIs.

Post by Tony Li »

Glad to help!
Post Reply