How to make a Simple RPG Textbox in Godot

Поділитися
Вставка
  • Опубліковано 26 жов 2024

КОМЕНТАРІ • 159

  • @onepunchman4719
    @onepunchman4719 9 місяців тому +32

    EDIT: FULL SOLUTION IN REPLIES
    Godot 4.1 Here is how to use Tweening and have that pesky and symbol appear (I used "

    • @onepunchman4719
      @onepunchman4719 9 місяців тому +2

      EDIT: FULL SOLUTION FURTHER DOWN
      Just moved the var tween function to and onready variable as it was messing with the skip feature:
      (at the start of the script with the other onready variables. Also deleted it from the add text function so it only exists as an onready var)
      @onready var tween = get_tree().create_tween()

    • @onepunchman4719
      @onepunchman4719 9 місяців тому +1

      Having the tween variable as an onready statement allows the skip feature to function, but causes the dialog queue to have issues since it does not begin the tweening again after using the first skip. will edit this message if i can fix it
      EDIT: Solved the problem, it's just a couple more messages down in this thread

    • @ballere2003
      @ballere2003 9 місяців тому +1

      hey man, i just got mine working properly. lmk if you need help

    • @onepunchman4719
      @onepunchman4719 9 місяців тому +1

      @@ballere2003 Yes Please! I left it off last night and could definitely use a hand!

    • @ballere2003
      @ballere2003 9 місяців тому +1

      @@onepunchman4719
      Personally, to make a global tween that allowed me to use the skipping, I had to use "@onready var tween = create_tween()" for some reason the get_tree() made it not work.
      - For the skip to work in Godot 4, you have to change "tween.remove_all()" to "tween.kill()"
      [YOU HAVE TO CREATE A NEW TWEEN AGAIN BEFORE TWEEN.TWEEN_PROPERTY] i'm not yelling
      - tween = create_tween()
      to get the tweening to work multiple times, you have to set your variable back to 0.0 (in your case "visible_characters" ).
      - You can do this in the hide show or display functions, anywhere before the tween starts (I set in my display function right before I call show).
      - If you want to use the "percent_visible" how the tutorial does, the new variable name is "visible_ratio" and in the inspector it is right below visible characters
      - tween.tween_property(label, "visible_ratio", 1.0, len(next_text) * CHAR_READ_RATE).set_ease(Tween.EASE_IN_OUT).set_trans(Tween.TRANS_LINEAR)

  • @simpson6700
    @simpson6700 8 місяців тому +35

    in case anyone is wondering, the margins are in theme overrides now. this took me way too long to figure out.

  • @AlekseyLoykuts
    @AlekseyLoykuts 3 роки тому +96

    Jeez, i haven't seen such "straight to the point" tutorials for a long time. Keep it on!

  • @gusyoung82
    @gusyoung82 2 роки тому +37

    Finally, a straight-forward textbox tutorial. Thank you. This taught me a LOT.
    Fun fact: you can move a player while the textboxes are up in this code.
    Simple update: change the pause mode to Process on the CanvasLayer in the editor and simply add this code to the match/State.ready line in func _process:
    get_tree().paused = true
    and then add to the hide_textbox function:
    get_tree().paused = false
    Keep up the good work!

  • @mrkathooloo5711
    @mrkathooloo5711 2 роки тому +5

    This is so helpful, thank you so much! A small issue I ran into was that the margin feature didn't seem to be working, so in case anybody runs into this issue, just make sure that your anchor is set to 1 on the left, right, and bottom (and top if you want it to be perfectly centered), and that you're editing the MarginContainer node, not the Panel node.

  • @glogsi1
    @glogsi1 2 роки тому +3

    i like that you made tutorial without 30 minutes long "hello guys today we are going to make text box in program called godot, so first we need to open the aplication..." and cringy music. HUGE THANK YOU for saving our time, and making this video 13 minutes long, not 50 minute long

  • @MrFeral
    @MrFeral 3 роки тому +12

    You could also add to the finished state to check if it contains text queued up and to not hide the box if so. Great stuff!

  • @smokinpotato
    @smokinpotato 3 роки тому +3

    Wow, I memorized most of this stuff and I don't even have a computer, when it gets fixed I will use this vid as a reference because of how simple and precise it is

  • @Yoroiful
    @Yoroiful 9 місяців тому +5

    In 4.0 you want to do:
    if tween:
    tween.kill()
    tween = get_tree().create_tween()
    tween.tween_property(message, "visible_ratio", 1.0, len(message.text) * CHAR_READ_RATE)
    tween.connect("finished", on_tween_finished)

    • @ballere2003
      @ballere2003 9 місяців тому +2

      damn if i had scrolled like two ticks more i would've seen this two hours ago and it wouldn't be too late for me

    • @lunastifaliamusic
      @lunastifaliamusic 4 місяці тому

      Tried this out. The 1.0 ratio doesn't do anything. Changing it to 0.0 got me somewhere, however, it's counting backwards which I obviously do not want. How on Earth do I fix this? (Godot's updates are ridiculous if they constantly make changes. They should've just kept tweens smh)

  • @drdrub
    @drdrub 3 роки тому +4

    You're so quick, and precise, and all your programming is well explained! This is the dialogue tutorial godot needed. I was looking for this for forever! Subbed! :)

  • @user-xsn5ozskwg
    @user-xsn5ozskwg 9 місяців тому +1

    Nice call with the tweening; I've been using a timer which is a lot more processor-heavy. Only thing I'd change is instead of doing percent visible I'd do characters visible instead, and set the time to be a variable based on the total characters in the string so you get a consistent playback speed for each character. It also lets you set some methods to handle character tags that affect playback speed, which can be really nice to put emphasis on specific dialogue or add pauses with punctuation to mimic speech patterns.

  • @coreybarnett2158
    @coreybarnett2158 3 роки тому +2

    This is awesome! I was about to implement something like this so the timing couldn't be better. Loved the pacing and explanations as you went. Thank you!

  • @Dragon1Freak
    @Dragon1Freak 3 роки тому

    Really appreciate how straight to the point you are with your videos, you don't overexplain but you still get all of the needed info across. Definitely subscribing!

  • @andrewalekseyev2460
    @andrewalekseyev2460 2 роки тому

    Massively helpful! SO easy to understand and came with a lot of helpful features. This is the gold standard for tutorials.

  • @jonathanmaywood4568
    @jonathanmaywood4568 Рік тому +1

    Great tutorial, helped me understand the tween node better. And great dialogue system! Hope you make more tutorials for Godot.

  • @vextronx
    @vextronx 2 роки тому

    This is the most important kind of content for the Godot community, good job! Thank you so much! :)

  • @too_many_fish
    @too_many_fish 3 роки тому +3

    Keep these tutorials coming and your channel will blow up

  • @azuolas5673
    @azuolas5673 3 роки тому +1

    Amaizing straight to the point, clear tutorial , keep it up !

  • @Frostbyte-Game-Studio
    @Frostbyte-Game-Studio 6 місяців тому

    this is the definition of "straight to the fucking point" excellent video

  • @LeoMattMan
    @LeoMattMan Рік тому

    Thanks! This is a really nice tutorial. Just what I was looking for. BTW, you type really fast!😁

  • @LOSFOUFOUP
    @LOSFOUFOUP Рік тому +7

    So is there the exact same video but in godot 4 please ? Just so we know how to make the text appears with tween.

    • @HungaryHQ
      @HungaryHQ 7 місяців тому

      Just use animationplayer. Less code and more easy with animation. The name can be changed like visible_ratio not the other stuff.

  • @patrickjay6434
    @patrickjay6434 2 роки тому

    Great tutorial, simple but does the job perfectly. Thanks for sharing

  • @sweetgokke
    @sweetgokke 2 роки тому

    Amazing tutorial can't stress it enough

  • @untodesu
    @untodesu 2 роки тому

    Ayo that's some good stuff right here. Going to kind of merge my extensive C# typewriter cpde with this! Thanks a lot!

  • @Jorge_super
    @Jorge_super Рік тому +4

    1:00
    When I try to write text in the Label, the margin container reset to its default size.
    Does this happen to anyone else?

  • @AppMaker728
    @AppMaker728 3 місяці тому

    They talk about not enough godot tutorials it's plenty

  • @Gakusangi
    @Gakusangi 3 роки тому +7

    I love Godot for its versatility and how you can change every tiny thing, but the implementation of a basic text box really needs to be streamlined somehow. There are so many moving parts to this for something seemingly simple. It's the only major issue I've had with the engine so far... well, that and having like six different ways to do the same thing depending on what version you have or if it covers the specific needs you have, like... character movement, and how to remember if you've been in a scene or opened a door or emptied a chest.
    I do have a question though. In a top-down game where my camera moves relative to my player's position in the scene, does the textbox keep its position relative to the current camera position?

    • @jontopielski6227
      @jontopielski6227  3 роки тому +4

      There is an open source text box plugin that looks promising called Dialogic. Might be worth looking into: github.com/coppolaemilio/dialogic
      As for the camera movement, since the textbox is a child of a canvaslayer, you can think of it as sitting entirely on a different layer. It is painted above everything else and so won't interfere with camera movement on a layer below it.

    • @Gakusangi
      @Gakusangi 3 роки тому

      @@jontopielski6227 So the camera could be positioned anywhere, and the box will always be in the same spot relative to the player view?

    • @jontopielski6227
      @jontopielski6227  3 роки тому +1

      ​@@Gakusangi Correct

  • @neverknow2474
    @neverknow2474 Рік тому +2

    Nice tutorial!! loved it. Your style of just get to the point is amazing! quick and easy I really appreciate it.
    Two things i changed for the stuttering:
    1: label.percentvisible = 0 before you set the label.text = next_text
    2. Finished state i added an if text_queue.empty(): hide_textbox()

    • @onepunchman4719
      @onepunchman4719 8 місяців тому +1

      for Godot 4 this second point is helpful :D since the first one is required to be included in the tweening line.

    • @neverknow2474
      @neverknow2474 8 місяців тому +1

      @@onepunchman4719thanks im glad i could help!!

  • @maximilianotorres8971
    @maximilianotorres8971 6 місяців тому +1

    I have been fighting with this tutorial the whole day because tweens aren't nodes anymore in Godot 4

    • @robickaguas7612
      @robickaguas7612 6 місяців тому

      me too it's so frustrating. do you find workaround?

  • @per-axelskogsberg3861
    @per-axelskogsberg3861 2 роки тому +1

    The flickering of the textbox. Could it be because of the hide_textbox() in State.FINISHED of _process? If so would adding if queue.empty(): hide_textbox() fix it?

  • @raik1766
    @raik1766 5 місяців тому +4

    Heres my version of your script (gd 4):
    edit to add a signal because why not
    extends CanvasLayer
    signal dialogue_finished
    enum State {
    READY,
    READING,
    FINISHED
    }
    const CHAR_RATE = 0.075
    @onready var label = $Container/TextContainer/Panel/Label
    @onready var bg = $Container/BG
    var tween: Tween
    var state: State
    func _ready():
    _hide()
    state = State.READY
    func _process(delta):
    match state:
    State.READING:
    if Input.is_action_just_pressed("ui_select"):
    _finish()
    State.FINISHED:
    if Input.is_action_just_pressed("ui_select"):
    _hide()
    dialogue_finished.emit()
    state = State.READY
    func _hide():
    label.text = ""
    label.visible_ratio = 0
    bg.visible = false
    func _show():
    bg.visible = true
    tween = create_tween()
    tween.finished.connect(_finish)
    func _finish():
    tween.stop()
    label.visible_ratio = 1
    state = State.FINISHED
    func _display_dialogue(lines):
    if state != State.READY:
    return
    label.text = lines
    _show()
    tween.tween_property(label,"visible_ratio",1,len(lines) * CHAR_RATE)
    state = State.READING

    • @hlo702
      @hlo702 3 місяці тому

      I was struggling to get the text to skip to the end on the newer version of Godot and this helps so thanks!

  • @MoviesSummary2
    @MoviesSummary2 3 роки тому +1

    bro you are awesome .thx for the tutorials

  • @streq9199
    @streq9199 3 роки тому

    You better believe me when I say Thank You Jon!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! god bless

  • @supjay3945
    @supjay3945 7 місяців тому +3

    Well it seems simple enough. But its not beginner friendly. You're creating nodes and editing properties without explaining where to look. I agree with some that say its too fast. But thanks for the vid

  • @MetalRenard
    @MetalRenard 3 роки тому +6

    This is awesome. Thank you so much!
    I'm a total beginner at this so this may be a silly question but how do I now use this in different scenes and inject different text? I replicated this perfectly but don't know how to implement it into different situations. Thanks so much!

    • @jontopielski6227
      @jontopielski6227  3 роки тому +5

      You'll want to make the TextBox.tscn globally accessible by Autoloading it in the project settings (Project -> Project Settings -> AutoLoad -> Add TextBox.tscn (**not TextBox.gd)). Now you can reference it anywhere in the project via TextBox.push_text("Text to display here"). If you want to check out a sample project that uses the autoloaded global TextBox, you can reference this one: github.com/jontopielski/shade

    • @MetalRenard
      @MetalRenard 3 роки тому +1

      @@jontopielski6227 Thank you so much! I'll give it a try.

    • @MetalRenard
      @MetalRenard 3 роки тому +1

      @@jontopielski6227 Just wanted to say thank you, I worked it out thanks to your help. Cheers!

  • @JayJay-ki4mi
    @JayJay-ki4mi Рік тому +3

    Couple of things for GD4:
    1. onready is now @onready
    2. Visible percentage is under "Display Text" -> Visible Ratio

    • @lazy_gravity6088
      @lazy_gravity6088 Рік тому +1

      do you still have to make a tween cuz those seem to not work in godot 4 (at least within context of this tutorial)

    • @BANANAMANA356
      @BANANAMANA356 11 місяців тому

      @@lazy_gravity6088same difficulty

  • @peacy7184
    @peacy7184 2 роки тому

    This was super helpful, cheers! :)

  • @imogiagames
    @imogiagames 3 роки тому

    Hello, thank you so much for this tutorial, that's awesome!

  • @ifandor1
    @ifandor1 Рік тому

    Really cool tutorial!!

  • @crisr.s.5995
    @crisr.s.5995 2 роки тому +1

    One question, how do I interact with the npc so that the text box appears? I don't know if I'm explaining myself clearly

  • @markaven5249
    @markaven5249 9 місяців тому

    I think a good way of doing it would be to start with the state machine, Im not totally familiar woth Godot, but instantiate a new textbox from the actors, so uou put the dialogue into the actors as you place them.

  • @saransrini03
    @saransrini03 2 роки тому +1

    U should make this textbox with options dialog. That would be useful!

  • @wikzzorzthenoob1797
    @wikzzorzthenoob1797 2 роки тому

    Thnx This really helped me out !

  • @Nidhsa
    @Nidhsa Рік тому +28

    WHY SO FAST CHILLLL

    • @markaven5249
      @markaven5249 9 місяців тому +9

      It is admittedly a little annoying and unhelpful and comes out kind of egotistical. Anyone can slow or speed down the video, anyway. With that said, the video is helpful, but a teacher should care about the students/viewers, not showing off how fast they can work. 😕

    • @SilverKojin
      @SilverKojin 8 місяців тому +1

      You got to keep up, my guy

    • @kloa4219
      @kloa4219 8 місяців тому +3

      0.5x gang rise up

    • @supjay3945
      @supjay3945 7 місяців тому +1

      Thats a good idea. But some parts he'll just click through properties and ill miss them still…

  • @slep163
    @slep163 3 роки тому +2

    Really good tutorial, I've got a question, Is there a way to play sound every time a letter appears?

    • @jontopielski6227
      @jontopielski6227  3 роки тому +5

      Yes - you just need to keep track of how many characters you have read so far. You can update the character counter in the tween_step signal and check if a new character has been read and if so, play a sound. Here is what an implementation might look like (assumes that you've setup an audiostreamplayer with the text typed sound and stored the body of your textbox label as the variable `label`):
      ...
      var current_char_count = 0
      func queue_text(next_text):
      current_char_count = 0
      ...
      func _on_Tween_tween_step(object, key, elapsed, value):
      var next_char_count = label.visible_characters
      if next_char_count > current_char_count:
      current_char_count = next_char_count
      $AudioStreamPlayer.play()
      ...
      It should be noted that sometimes you don't want to play the sound for EVERY character that is typed since it might be too many noises, depending on your text speed. In those cases, you'll want to do every other or every 3, but I'll leave it up to you to make those kinds of tweaks.

    • @dungeoncorporation
      @dungeoncorporation 2 роки тому +1

      @@jontopielski6227 thanks for this. is there a way to pitch-shift the played sound randomly, in the vein banjo kazooie ?

    • @jumbledfox2098
      @jumbledfox2098 Рік тому +1

      @@jontopielski6227 for anyone in the future, reset current_char_count in display_text() and not queue_text()!!

  • @Matthew-bd9fq
    @Matthew-bd9fq 2 роки тому +1

    I'm having an issue where if I use enter to skip READING state, next time I don't skip the animation, it makes the end of the text appear and disaper multiple times, this only happens when I skip text rather than waiting for it to finish by itself.

    • @jontopielski6227
      @jontopielski6227  2 роки тому +1

      Make sure you're stopping the tweening when you check for "ui_accept". If you share your code on somewhere like github, I'm happy to take a look.

    • @Matthew-bd9fq
      @Matthew-bd9fq 2 роки тому +2

      @@jontopielski6227 I am not too much of an expert in github but I made a private repository and added your username to access list, is that okay?

  • @cavitycat
    @cavitycat 3 роки тому

    great tutorial, thank you

  • @juanrivas1336
    @juanrivas1336 2 роки тому +1

    Hey this was a great vid! I'd like to know how I can embed multiple dialog boxes in one scene, for example when (in my level) my character reaches interacts with an object I want the dialog box to appear again. However, when I try to embed the dialog box again it does not let me drag it into the position I want, instead it overlaps with the first dialog inside the beginning of my scene. First of all, I'd like to know how I can move the dialog box, or if not is there a way to trigger another dialog box when the next interaction begins. Much appreciated.

    • @jontopielski6227
      @jontopielski6227  2 роки тому +1

      Hi, you shouldn't be moving the dialog box's position. It should stay in one position and so long as it is in its own CanvasLayer, it should rest on top of the other canvases without needing to move its position. You should make the dialog box global and only use 1 dialog box for your whole game. When you interact with an object, it should send the text to the one global dialog box

    • @dungeoncorporation
      @dungeoncorporation 2 роки тому

      @@jontopielski6227 how could i make it so that with a button, the dialogue box’s position can flip to the top of the screen and then back when pressed again, in the vein of chrono trigger text boxes. what would be the easiest way to manage having it spawn at the top instead of the bottom sometimes?

  • @The_Rising_Nova
    @The_Rising_Nova 5 місяців тому

    This is not the latest Godot version right ? Because some things appear to not be the same as in the video ^ ^ (thak you for making it tho)

  • @Plund3rbunny
    @Plund3rbunny Рік тому +1

    Do you have suggestions for how to adapt this for Godot 4 since tweens got reworked and are no longer nodes? I did my best to follow along adapting for the new way to use tweens and I have something that KIND OF works, but then has a bunch of weird behavior (it'd take too long to explain what all's going wrong in this comment that I'm trying to keep short lol) and I'm still a beginner who doesn't know enough about tweens either in Godot 3 or 4 to know what I'm doing wrong 😅 if you'd be willing to take a look at the script I hacked together to check where I went wrong, let me know

    • @Plund3rbunny
      @Plund3rbunny Рік тому +1

      Nevermind I figured out how to do the same thing without using a tween. Thanks for the tutorial!

    • @Sungjinbot
      @Sungjinbot Рік тому

      @@Plund3rbunny how , im struggling to do it can you pls help

    • @Plund3rbunny
      @Plund3rbunny Рік тому +1

      @@Sungjinbot So in a Label, if you look under the inspector under "Displayed Text" there is a setting called "Visible Characters" that says "the number of characters to display. If set to -1, all characters are displayed." Based on that, here's what I have in my display_text() func instead of the tween stuff:
      while label.visible_characters len(next_text[2]) || label.visible_characters == -1:
      end_symbol.text = "v"
      current_state = state.FINISHED
      The await line is how I adjusted character display speed, so you can change that 0.02 to a different number for a different speed. I'm still a Godot newb and coding newb, so there's probably a better way to code all this, but so far this has been working for me without any weird behavior or bugs. Even tho you can't see the adjustments I made to the rest of the code, hopefully this is enough to help and give you a starting place to work from :)

    • @juicebox3495
      @juicebox3495 Рік тому

      @@Plund3rbunny I want to add that if someone uses your solution, make sure to change all Label.visible_ratio = 0 to Label.visible_characters = 0 where necessary.
      Thank you for your solution, I tried figuring it out myself but couldn't exactly get it to work.

  • @keivamp
    @keivamp 3 роки тому +1

    Thank you!

  • @xamdotdot
    @xamdotdot Рік тому

    heya I'm having a hard time trying to write the same code but within a different scene? Is there a way to fix this or make it easier, because when i try to copy and paste the code it just repeats the text instead of writing its own.

  • @justinkamau2317
    @justinkamau2317 2 роки тому +1

    This man is fast

  • @dijjidog
    @dijjidog 3 роки тому +1

    Great tutorial no fr!cking around. Also 69th like

  • @animequeen78
    @animequeen78 3 роки тому

    Thank you for the link to the scripting code you used. I can't see the scripting all too well in the video.

  • @adhityamarya6411
    @adhityamarya6411 3 роки тому +1

    hey dude how you put some sfx when the text moving by tween?

  • @c0ff334dd1ct
    @c0ff334dd1ct 2 роки тому

    I have a question. When i want to add another textbox after the first one finishes do i have to make this all over again or how should i do this?

  • @Kimberliearcher
    @Kimberliearcher 11 місяців тому

    hi jon, I would like to know if theres a way we can make the text to get the content from an external file?

  • @freddy_wabm
    @freddy_wabm 2 роки тому

    I have a camera that follows the player, I don't know how to make the text box always show in the range of the camera

    • @jontopielski6227
      @jontopielski6227  2 роки тому +1

      Make sure the textbox is a CanvasLayer node (or a child of a CanvasLayer node). Then it should appear over everything else, regardless of the current camera. If you must, you can also Autoload the textbox so it is preloaded at the start of every scene and it can be globally accessible.

  • @justarandomgamer5648
    @justarandomgamer5648 5 місяців тому

    could this be edited to have dialogue sounds too?

  • @rpminergabe2953
    @rpminergabe2953 2 роки тому

    Trying to use this to implement it into a game, and needless to say, its a very well made tutorial, but I'm having one issue. I did exactly what you did, but despite that, I cant manage to get the start symbol, end symbol, or label text to be blank. my code is the exact same as yours, but when I run the scene, the text is the same and not blank

  • @themaxandwax
    @themaxandwax Рік тому

    One thing I wanna ask is do we still need the print commands or no?

  • @lawsona
    @lawsona 3 роки тому

    im having an error that i cant figure out the reasoning behind, "_build_interpolation: Tween target object has no property named: percent visible"
    any idea why this happens?

    • @jontopielski6227
      @jontopielski6227  3 роки тому +1

      Did you add an underscore? “percent_visible”

    • @lawsona
      @lawsona 3 роки тому

      ​@@jontopielski6227 i did not, thanks! but i still am having an issue with the tweening, for me the text has appeared as soon as i play the scene and because of this the "end_symbol" doesnt show up (well i guess thats obvious since it shows up when tweening is complete and im having an issue with the tweening..)

    • @jontopielski6227
      @jontopielski6227  3 роки тому +1

      @@lawsona i'm guessing the tweening isn't starting - double check the tweening parameters and don't forget to call $Tween.start(). for reference, i've uploaded the code from this tutorial so you can cross check the scene structure and scripts: github.com/jontopielski/rpg-textbox-tutorial
      also, i noticed a slight mistake in my tutorial - make sure you connect the Tween's tween_completed, NOT tween_all_completed signal. the reason is that when there are multiple texts the tween_all_completed() doesn't emit properly. i've noted it in the description.
      if you're still stuck after a while, feel free to upload your project somewhere publicly accessible and i'll take a look when i get the chance.

    • @lawsona
      @lawsona 3 роки тому +1

      @@jontopielski6227 thanks for the help!! i’ll try and see what’s going on with it tmmrw

    • @lawsona
      @lawsona 3 роки тому

      ​@@jontopielski6227 okay so the tweening still has some unidentified problem but the if you press "ui_accept" the text appears, but the problem is its just an empty box until you press ui accept.

  • @lawsona
    @lawsona 3 роки тому +3

    rlly helpful video, could you make a tutorial on how to do an rpg party follwing system like in eartbound where the other party members follow behind the player?

  • @fal_pal_
    @fal_pal_ Місяць тому

    No size flags in Godot 4.3? Starts at 1:40

    • @fal_pal_
      @fal_pal_ Місяць тому

      I ended up using "Container Sizing" settings to emulate this part of the video

  • @loopolofi
    @loopolofi Рік тому

    How can I use this dialog on an Npc?

  • @huppsy
    @huppsy Рік тому

    genius

  • @lawsona
    @lawsona 3 роки тому +1

    whats the easiest way i could get the textbox to appear when i press ui accept and my character collision is touching the collision of an object? (basically like interacting with an object)

    • @jontopielski6227
      @jontopielski6227  3 роки тому +1

      I'll do my best to explain one way to do this. First, make sure your TextBox scene is autoloaded so it's always in the scene and always accessible by code.
      You'll want to decide how exactly you're going to interact with objects. One way is to use a RayCast2D that is attached to the player and points out. It's not perfect, but let's go with that for this example.
      In the player, whenever "ui_accept" is pressed, check if the collider is colliding with any object that can be interacted with. If there is a collision, then grab the dialogue information from that object directly from the raycast collision check. To make the dialogue information visible from the collided object, try this - create a new scene called "Dialog" that is just an empty node that exports a single String called "dialogue". Then, attach it as a child to any StaticBody2D that the player is going to interact with. The hierarchy will look like this:
      - Sprite
      - StaticBody2D
      - Dialog
      - CollisionShape2D
      Then, when you check the raycast collision on the player, you can check if the body it collided with (in this case the StaticBody2D) has a child named "Dialog". If it does, grab the exported "dialog" string (which will be the text you want displayed), and push that text to the global TextBox.
      Because of how difficult this was to try and explain, I decided to publish a project that I stopped working on that has a working interaction system: github.com/jontopielski/shade
      Look at TextBox.tscn, Player.tscn, and Dialog.tscn to get a better understanding of how the systems work. Cheers!

    • @veto_5762
      @veto_5762 3 роки тому

      A simpler way could be check the body raycast and use the has_method funtion to check if it has a specifyc function for that:
      if Input.is_action_just_pressed("ui_accept") and raycast.is_colliding():
      var body = raycast.get_collider()
      if body.has_method("on_interact"):
      body.on_interact()
      Then inside the object function you send the message (+ any other interactions/result) that happens when you interact with the object, and idk if is possible something like virtual functions in godot to make this process as simple as overwrite a function

  • @manoterasfloweskultor
    @manoterasfloweskultor Рік тому

    guay me costo pero lo conseguí sacar gracias

  • @tekmonster10
    @tekmonster10 2 місяці тому

    where is the size flags in gd4

    • @fal_pal_
      @fal_pal_ Місяць тому

      Also trying to find this...

    • @fal_pal_
      @fal_pal_ Місяць тому

      I ended up using "Container Sizing" settings, seems to do what the video is demonstrating

    • @tekmonster10
      @tekmonster10 Місяць тому

      @@fal_pal_ thanks but I already got it

  • @suretmeyenateistoc4252
    @suretmeyenateistoc4252 3 роки тому

    this is simple ?

  • @nesyta1749
    @nesyta1749 3 роки тому

    Oh nooo. This is not Game Maker Studio 2

  • @alikeremozfidan288
    @alikeremozfidan288 3 роки тому +1

    is it possible to we skip the animation if button pressed while animating

    • @jontopielski6227
      @jontopielski6227  3 роки тому

      Yes, I talk about that at 09:49 - if we press enter while it's reading, it will skip to the end and go into the finished state.

    • @alikeremozfidan288
      @alikeremozfidan288 3 роки тому

      @@jontopielski6227 wow,thanks! it is the only tutorial about dialogs that include both animation and skipping.thank again,you deserve much more subscribers.

  • @teamusic581
    @teamusic581 2 роки тому

    Can you make it a little slow,Ur so fast😅

  • @burcusimsek8992
    @burcusimsek8992 2 роки тому

    you just create canvas layer WTF how ?

  • @red27
    @red27 11 місяців тому +2

    Slow down ffs

  • @notmainchoice
    @notmainchoice Рік тому

    fix for flickering box:
    func _process(delta):
    match currentState:
    State.READY:
    get_tree().paused = true
    if !textQueue.empty():
    displayText()
    State.READING:
    if Input.is_action_just_pressed("ui_skip"):
    dialogue.percent_visible = 1.0
    $Tween.remove_all()
    changeState(State.FINISHED)
    State.FINISHED:
    if Input.is_action_just_pressed("ui_accept"):
    changeState(State.READY)
    if !textQueue.empty():
    showTextbox()
    else:
    hideTextbox()
    ### the code is pretty much the same just with an added if-else in the State.FINISHED, remember to use your equivalent function names for showTextbox and hideTextbox

  • @kaynex1039
    @kaynex1039 17 днів тому

    Working code for Godot 4.3:
    extends CanvasLayer
    @onready var textbox_container = %TextboxContainer
    @onready var start = %Start
    @onready var label = %Label
    @onready var end = %End
    enum BoxState {READY, READING, FINSIHED}
    var _cur_state: BoxState = BoxState.READY
    var _tween: Tween
    var _text_queue: Array[String] = []
    var speed := 40.0
    func _ready() -> void:
    _hide_textbox()
    add_text("First text queued up!")
    add_text("Second text queued up!")
    add_text("Third text queued up!")
    add_text("Fourth text queued up!")
    func _process(delta: float) -> void:
    match _cur_state:
    BoxState.READY:
    if !_text_queue.is_empty():
    display_text()
    BoxState.READING:
    if !_tween.is_running():
    label.visible_ratio = 1.0
    end.text = "v"
    change_state(BoxState.FINSIHED)
    if Input.is_action_just_pressed("ui_accept"):
    _tween.kill()
    BoxState.FINSIHED:
    if Input.is_action_just_pressed("ui_accept"):
    _hide_textbox()
    change_state(BoxState.READY)
    func _hide_textbox() -> void:
    start.text = ""
    end.text = ""
    label.text = ""
    textbox_container.hide()
    func _show_textbox() -> void:
    start.text = "*"
    textbox_container.show()
    func change_state(state: BoxState) -> void:
    _cur_state = state
    func add_text(next_text: String) -> void:
    _text_queue.push_back(next_text)
    func display_text() -> void:
    var next_text = _text_queue.pop_front()
    var length = next_text.length()
    label.visible_characters = 0
    label.text = next_text
    change_state(BoxState.READING)
    _show_textbox()
    _tween = create_tween()
    _tween.tween_property(label, "visible_characters", length, length/speed)

    • @kaynex1039
      @kaynex1039 17 днів тому

      This code does exactly what the video shows. However, I think I should now add:
      - A signal for proceeding through a textbox, and a signal for emptying the queue. I can see myself awaiting these signals, so a character can say something, then after talking, do something.
      - A way to "reserve" the textbox, so characters cannot talk over each other, or try to enter a conversation during another conversation.
      - A bit more control. One thing I have in mind is to end a textbox without input, so a character can be interrupted.
      - A choice system. Or, a way to talk back.
      - Effects. Pictures and sounds. Make it a bit more "undertale styled".

  • @CrispyRichter
    @CrispyRichter 2 роки тому

    I have an Issue, every time I skip the dialog the text stops and the window minimizes itself. I did everthing like in the video and then I tried the UPDATES in the description. The error occoured even before I used "tween_completed" and "$Tween.remove_all()".

    • @CrispyRichter
      @CrispyRichter 2 роки тому

      OMFG I misspelled FINISHED multiple times... THX for the github code. Otherwise I wouldn't have found out what's up with it not working.

  • @roxwize
    @roxwize 3 роки тому

    Excellent tutorial! However, I have a question. I'm trying to implement multiple character voices per text box and per "session" (as in, the time during where the textbox is visible and is showing a clear conversation or narrative). However, in order to switch character voices on the fly I have to yield for until the State is set to FINISHED. I'm wondering if there's a better way to go about this or if this is all I can do, as I feel like the yielding, due to it freezing the entire script until a signal is called (in this case, the custom textCompleted signal), might cause performance issues in the near future. I can send code if necessary, here is the debug code in the meantime...
    func _on_Button_pressed():
    _$Button.disabled = true
    _$Textbox.textSound = load("res://sounds/sans_placeholder2.wav")
    _$Textbox.queuetext("Teste")
    _yield($Textbox,"textFinished")
    _$Textbox.textSound = load("res://sounds/sans_placeholder.wav")
    _$Textbox.queuetext("Test2")
    _yield($Textbox,"textFinished")
    _$Textbox.textSound = load("res://sounds/sans_placeholder2.wav")
    _$Textbox.queuetext("Hello there....")
    _$Button.disabled = false

    • @roxwize
      @roxwize 3 роки тому

      Hell, I'll go ahead and send the code
      extends CanvasLayer
      const CHAR_READ_RATE = 0.05
      export (AudioStream) var textSound #setget ,setsound
      onready var container = $MarginContainer
      onready var text = $MarginContainer/MarginContainer/HBoxContainer/Text
      onready var end = $MarginContainer/MarginContainer/HBoxContainer/End
      enum State {
      READY,
      READING,
      FINISHED
      }
      signal textFinished
      var currentState = State.READY
      var textQueue = []
      var charCount = 0
      func _ready():
      hidetxt()
      setsound()
      func _process(_delta):
      match currentState:
      State.READY:
      if !textQueue.empty():
      dsptxt()
      State.READING:
      if Input.is_action_just_pressed("ui_accept"):
      text.percent_visible = 1
      $Tween.stop_all()
      end.text = "Z"
      changestate(State.FINISHED)
      State.FINISHED:
      if Input.is_action_just_pressed("ui_accept"):
      changestate(State.READY)
      hidetxt()
      func hidetxt():
      text.text = ""
      end.text = ""
      container.hide()
      func showtxt():
      container.show()
      func dsptxt():
      setsound()
      charCount = 0
      var txt = textQueue.pop_front()
      text.text = txt
      text.percent_visible = 0
      changestate(State.READING)
      showtxt()
      $Tween.interpolate_property(text,"percent_visible",0.0,1.0,len(txt)*CHAR_READ_RATE,Tween.TRANS_LINEAR,Tween.EASE_OUT)
      $Tween.start()
      func queuetext(txt):
      textQueue.push_back(txt)
      #func debug():
      # queuetext($TextEdit.text)
      func tween_finish(object, key):
      end.text = "Z"
      changestate(State.FINISHED)
      func changestate(next):
      currentState = next
      if next == State.FINISHED:
      emit_signal("textFinished")
      func text_step(object, key, elapsed, value):
      var nextCharCount = text.visible_characters
      if nextCharCount > charCount:
      charCount = nextCharCount
      $TextSound.play()
      func setsound():
      $TextSound.stream = textSound

    • @roxwize
      @roxwize 3 роки тому +1

      Okay, I think I've found a solution. It's a bit of a bodge and I have yet to test it, but I figure I can make the text array into a key-value (with two properties for text and voice) array and add an optional second argument to queuetext for the character voice. Hopefully it works...

    • @jontopielski6227
      @jontopielski6227  3 роки тому +2

      @@roxwize I think that's a nice idea. I was going to suggest an additional array for managing the "speaker", but creating a key-value pair object and storing that object in the queue also works. You can add things like the text, the speaker, maybe a portrait image, etc. Good luck!

  • @Idkikdhdnbd
    @Idkikdhdnbd 3 місяці тому

    it dosent work , can you help ? , this is my code :
    extends CanvasLayer
    const speel_speed = 2
    @onready var textbox_container = $textbox_container
    @onready var lable = $textbox_container/MarginContainer/HBoxContainer/Label
    @onready var tween = create_tween()
    enum State {
    READY,
    READING,
    FINISHED
    }
    var current_state = State.READY
    var text_queue = []
    func _ready():
    $Timer.wait_time = speel_speed
    _hide_text_box()
    _queue_text("hello im lara")
    _queue_text("hello im lara2")
    _queue_text("hello im lara3")
    _queue_text("hello im lara4")
    pass
    func _process(delta):
    match current_state :
    State.READY :
    if !text_queue.is_empty() :
    _diplay_text()
    State.READING :
    if Input.is_action_just_pressed("move_up") :
    tween.stop()
    lable.visible_ratio = 1.0
    _change_state(State.FINISHED)
    State.FINISHED :
    if Input.is_action_just_pressed("move_up") :
    _change_state(State.READY)
    _hide_text_box()
    func _queue_text(next_text):
    text_queue.push_back(next_text)
    pass
    func _hide_text_box():
    lable.text = ""
    textbox_container.hide()
    func _show_text_box():
    textbox_container.show()
    func _diplay_text():
    var next_text = text_queue.pop_front()
    _change_state(State.READING)
    $Timer.start()
    lable.text = next_text
    _show_text_box()
    tween.tween_property(lable , "visible_ratio", 1.0, speel_speed)
    func _change_state(next_state):
    current_state = next_state
    match current_state :
    State.READY :
    pass
    State.READING :
    pass
    State.FINISHED :
    pass
    func _on_timer_timeout():
    $Timer.stop()
    _change_state(State.FINISHED)

  • @aronaronaronaronaronaronaronar
    @aronaronaronaronaronaronaronar 3 роки тому

    Is it possible to somehow see how many queued texts are there? I just want the textbox to not disappear every time you change text.