Dialogue system

I am trying to find a Dialogue system that does the next:

  • each conversation has an Image that shall be in the background
  • each conversation has a name and an image of the state that the character that is talking has
  • after each conversation there is the option for the player too choose an answer and each answer will lead to another outcome and will influence the game
  • also there are some conversations depends on other decisions that were made before

And to be as cheep as possible.
Thanks.

This isn’t google, if you want to find a system like this, go ahead and search for it.
This forum is for people to ask for help, so if you’re making a system like this, and you can’t get it to work, you come here and ask a question, not for lazy people, who want others to do the search for them
If you want a system like this, but you can’t find it on asset store, you can go to the paid section of the site and request one

It’s not about laziness. I searched and didn’t find any. And I didn’t want to buy something that probably didn’t do what I wanted and I was wondering if someone knew one. I didn’t asked them to search for me. So basically I was stucked. And about the paid section I didn’t know about that. But thank you anyway for your “help”

Sorry, don’t know of any off hand as I’d just write my own when I need it. I seldom like code assets because I usually want something specifically unique to my own, and might as well just write it myself.

I can show you the one I’m using for my current game:

using UnityEngine;
using System.Collections.Generic;

using com.spacepuppy;
using com.spacepuppy.Tween;
using com.spacepuppy.Tween.Curves;
using com.spacepuppy.UI;
using com.spacepuppy.UserInput;

using com.mansion.UserInput;

namespace com.mansion.Entities.UI
{

    public class MessageBox : SPComponent
    {

        public const float CLOSE_DUR = 0.05f;

        public enum StateType
        {
            Closing = -1,
            Closed = 0,
            Opening = 1,
            Open = 2
        }

        public enum FormatOption
        {
            Custom = -1,
            Standard = 0,
            Script = 1,
        }

        #region Fields

        [SerializeField()]
        [DefaultFromSelf()]
        private UnityEngine.UI.Text _textBox;

        [SerializeField()]
        private float _openDur = 1f;
        [SerializeField()]
        [MinRange(1f)]
        private float _charactersPerSecond = 10f;
        [SerializeField()]
        private float _closeDur = 1f;
        [SerializeField()]
        private StringTweenStyle _textTweenStyle;


        [SerializeField]
        private TextSettings _scriptFormat;
        [System.NonSerialized()]
        private TextSettings _standardFormat;


        [System.NonSerialized()]
        private StateType _state;
        [System.NonSerialized()]
        private RadicalCoroutine _currentMessage;

        #endregion

        #region CONSTRUCTOR

        protected override void Awake()
        {
            base.Awake();

            _standardFormat = TextSettings.FromText(_textBox);
        }

        #endregion

        #region Properties

        public StateType State
        {
            get { return _state; }
            set { _state = value; }
        }

        public UnityEngine.UI.Text TextBox
        {
            get { return _textBox; }
            set { _textBox = value; }
        }

        public bool IsShowing
        {
            get { return _currentMessage != null; }
        }

        #endregion

        #region Methods

        public TextSettings GetFormat(FormatOption option)
        {
            switch(option)
            {
                case FormatOption.Script:
                    return _scriptFormat;
                default:
                    return _standardFormat;
            }
        }

        public IRadicalWaitHandle Close(float dur, bool hideOnFinish)
        {
            switch(_state)
            {
                case StateType.Closing:
                case StateType.Open:
                case StateType.Opening:
                    if (dur > 0f)
                    {
                        return SPTween.Tween((RectTransform)this.transform)
                                            .To("sizeDelta", Vector2.zero, dur)
                                            .OnFinish((s, e) =>
                                            {
                                                _state = StateType.Closed;
                                                _currentMessage = null;
                                                if (hideOnFinish) this.gameObject.SetActive(false);
                                                IEntity.BroadcastStallStateChangedGlobally();
                                            })
                                            .Play(true);
                    }
                    else
                    {
                        var trans = (RectTransform)this.transform;
                        trans.sizeDelta = Vector2.zero;

                        _state = StateType.Closed;
                        _currentMessage = null;
                        if (hideOnFinish) this.gameObject.SetActive(false);
                        IEntity.BroadcastStallStateChangedGlobally();
                        return RadicalWaitHandle.Null;
                    }
                default:
                    _state = StateType.Closed;
                    _currentMessage = null;
                    if (hideOnFinish) this.gameObject.SetActive(false);
                    IEntity.BroadcastStallStateChangedGlobally();
                    return RadicalWaitHandle.Null;
            }
        }

        public void ShowMessage(string msg, TextSettings format, System.Action callback = null)
        {
            if (!this.gameObject.activeSelf) this.gameObject.SetActive(true);

            if (_currentMessage != null)
            {
                _currentMessage.Stop();
                _currentMessage = null;
            }
            _currentMessage = this.StartRadicalCoroutine(this.ShowRoutine(msg, format, callback, true));

            IEntity.BroadcastStallStateChangedGlobally();
        }

        public void ShowMessageSequence(string[] msgs, TextSettings format, System.Action callback = null)
        {
            if (msgs == null) throw new System.ArgumentNullException("msgs");
            if (!this.gameObject.activeSelf) this.gameObject.SetActive(true);

            if (_currentMessage != null)
            {
                _currentMessage.Stop();
                _currentMessage = null;
            }
            _currentMessage = this.StartRadicalCoroutine(this.ShowSequenceRoutine(msgs, format, callback));

            IEntity.BroadcastStallStateChangedGlobally();
        }

        private System.Collections.IEnumerator ShowRoutine(string msg, TextSettings format, System.Action callback, bool deactivateOnComplete)
        {
            var trans = (RectTransform)this.transform;

            if(_state != StateType.Closed)
            {
                yield return this.Close(CLOSE_DUR, false);
            }

            _textBox.text = string.Empty;
            trans.sizeDelta = Vector2.zero;

            //open
            _state = StateType.Opening;

            var w = 768f;
            var h = 180f;//_textBox.cachedTextGenerator.GetPreferredHeight(msg, _textBox.GetGenerationSettings(new Vector2(w, float.PositiveInfinity)));
            var sz = new Vector2(w, h);
            yield return SPTween.Tween(trans)
                                .To("sizeDelta", sz, _openDur)
                                .Play(true);

            _state = StateType.Open;
           
            while(true)
            {
                //reset for new pass
                _textBox.text = string.Empty;
                format.Apply(_textBox);

                bool lastLoop = false;
                var str = msg;
                var t = _textBox.cachedTextGenerator;
                t.Populate(str, _textBox.GetGenerationSettings(sz));
                if(str.Length > t.characterCountVisible)
                {
                    msg = "..." + str.Substring(t.characterCountVisible);
                    str = str.Substring(0, t.characterCountVisible);
                }
                else
                {
                    lastLoop = true;
                }

                //show text
                var textTween = SPTween.Tween(_textBox)
                                       .UseCurve(new StringCurve("text", str.Length / _charactersPerSecond, string.Empty, str, _textTweenStyle))
                                       .Play(true);

                var input = Game.InputManager.GetDevice<MansionInputDevice>(Game.MAIN_INPUT);
                while (!textTween.IsComplete)
                {
                    if (input.GetCurrentButtonState(MansionInputs.Run) == ButtonState.Down ||
                        input.GetCurrentButtonState(MansionInputs.Action) == ButtonState.Down ||
                        input.GetCurrentButtonState(MansionInputs.UICancel) == ButtonState.Down)
                    {
                        textTween.Stop();
                        _textBox.text = str;
                        yield return null;
                        break;
                    }

                    yield return null;
                }

                while (!(input.GetCurrentButtonState(MansionInputs.Run) == ButtonState.Down ||
                        input.GetCurrentButtonState(MansionInputs.Action) == ButtonState.Down ||
                        input.GetCurrentButtonState(MansionInputs.UICancel) == ButtonState.Down))
                {
                    yield return null;
                }

                if (lastLoop) break;
            }
           
            //close
            _state = StateType.Closing;

            _textBox.text = string.Empty;
            yield return SPTween.Tween(trans)
                                .To("sizeDelta", Vector2.zero, _closeDur)
                                .Play(true);

            _state = StateType.Closed;

            if (deactivateOnComplete)
            {
                _currentMessage = null;
                this.gameObject.SetActive(false);
            }
            if (callback != null) callback();

            IEntity.BroadcastStallStateChangedGlobally();
        }

        private System.Collections.IEnumerator ShowSequenceRoutine(string[] msgs, TextSettings format, System.Action callback)
        {
            for(int i = 0; i < msgs.Length; i++)
            {
                yield return ShowRoutine(msgs[i], format, null, false);
            }

            _currentMessage = null;
            this.gameObject.SetActive(false);
            if (callback != null) callback();
        }

        #endregion

    }

}

It works with a simple TextBox, you can shape and size the TextBox and put a background and whatever you want on it. Mine looks like this:

Very simple.

You could easily add an Image, and a Sprite parameter to include a portrait with it.

Of course, my implementation relies on my spacepuppy framework for SPTween and what not.

But it’s fairly generic tween engine, any tween engine would do.

You could use it as a starting point for your own…

I’ve been experimenting with VIDE lately. It’s pretty neat, gives you a node-based way to define conversation trees, and is free. Give it a go!