Unity typing text effect for dialogue | Unity tutorial

แชร์
ฝัง
  • เผยแพร่เมื่อ 15 ต.ค. 2024

ความคิดเห็น • 69

  • @ShapedByRainStudios
    @ShapedByRainStudios  2 ปีที่แล้ว +4

    Thanks for watching! 🙂It was pointed out that there's a better way to go about dealing with line breaks using the TextMeshPro _MaxVisibleCharacters_ property. If you're interested in those adjustments, check out the _Typing Text for Line Breaks_ timestamp of this video - th-cam.com/video/HP1EYVwAhRg/w-d-xo.html
    I also just recently started up this Discord server where you're welcome to come ask questions, suggest a video topic, or just hang out! It may take a bit to build up a community there, but I hope it eventually becomes a helpful place for other passionate developers! ➔ 📱 discord.gg/99gcnaHFf9

  • @PastaLaFeasta
    @PastaLaFeasta 2 ปีที่แล้ว +5

    Thank you so much for this detailed and easy to understand tutorial!!! I was struggling with this for quite some time now!

  • @SestoMazzanti
    @SestoMazzanti 2 ปีที่แล้ว +2

    Best video I've seen about autotyping in unity. Thanks

  • @nathancongdon248
    @nathancongdon248 ปีที่แล้ว +9

    For anybody having issues with the full text of lines 2+ being displayed, it's likely due to the "submit" button triggering the skip at the same time you submit an answer. To solve this, I slightly changed the code to only allow a skip once three letters are visible.
    I also followed the advice of another comment down below, who suggested that we use "{TextObjectName}.MaxVisibleCharacters = n", with "n" being the iteration you are on in a for loop. This prevents text wrapping errors, and does not require the code to account for rich text tags!
    My resulting code looks like this:
    for (int i = 1; i < lineLen; i++)
    {
    yield return new WaitForSeconds(typingSpeed);
    dialogueText.maxVisibleCharacters = i;
    if (playerControls.Player.Submit.IsPressed() && i > 3)
    {
    dialogueText.maxVisibleCharacters = lineLen;
    break;
    }
    }
    Hope this helps!

    • @qzlocx
      @qzlocx 3 หลายเดือนก่อน

      where do we put this code in? which coroutine?

    • @BraveStorms
      @BraveStorms 2 หลายเดือนก่อน

      this was such a huge help! thanks

  • @noahjames9457
    @noahjames9457 2 ปีที่แล้ว +3

    keep it up! this is the best dialogue system tutorial i've seen

  • @facumorazzani8231
    @facumorazzani8231 2 ปีที่แล้ว +1

    I say this in all your videos, but i love you treveeerrr!!!!

  • @Bwukly
    @Bwukly 2 ปีที่แล้ว +1

    I was looking for a simple way to implement this. Appreciate the video, thanks.

  • @takicomposer
    @takicomposer 2 ปีที่แล้ว +34

    I was having a problem where after I skipped the dialogue one time the next line didn't had the typing effect. The problem was the same as the jump problem in the first video, the input was calling the next line and skipping the coroutine at the same time, so here my fix to this:
    1 - I created a private bool called canSkip with a default value of false and created a new coroutine to make the variable true after a WaitForSeconds().
    private IEnumerator CanSkip()
    {
    canSkip = false; //Making sure the variable is false.
    yield return new WaitForSeconds(0.05f);
    canSkip = true;
    }
    2 - Created another private bool called submitSkip for the input and in the Update method I set the submitSkip to true (this is need because just use "Input.GetKeyDown(Keycode.space)" or for the new input system "controls.UI.Submit.triggered" doesn't work properly, I think it works better in the Update() because it's called every frame).
    private void Update()
    {
    if (controls.UI.Submit.triggered)
    {
    submitSkip = true;
    }
    if (!dialogueIsPlaying)
    {
    return;
    }
    if (controls.UI.Submit.triggered && canContinue)
    {
    ContinueStory();
    }
    }
    3 - In the DisplayLine Coroutine I set the submitSkip to false at beginning (because when you go to the next line submitSkip will be set to true), call the CanSkip Coroutine and in the foreach you put the canSkip and submitSkip variables in the if statement. Also for good measure, at the end I set false to the canSkip variable.
    private IEnumerator DisplayLine(string line)
    {
    dialogueTMP.text = "";
    continueIcon.SetActive(false); //Change to animation.
    submitSkip = false;
    canContinue = false;
    StartCoroutine(CanSkip());
    foreach (char letter in line.ToCharArray())
    {
    if (canSkip && submitSkip)
    {
    submitSkip = false;
    dialogueTMP.text = line;
    break;
    }
    dialogueTMP.text += letter;
    yield return new WaitForSeconds(typingSpeed);
    }
    continueIcon.SetActive(true); //Change to animation.
    canContinue = true;
    canSkip = false;
    }
    And that's it, if you were having the same problem should work fine now.
    Also thanks for the videos, Trevor. They are being a huge help in my game's development.

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      Thank you so much for the kind words and for sharing your detailed solution to this! I'm certain this will help others going through these tutorials. It's much appreciated! 🙂

    • @dawidziomalify
      @dawidziomalify 2 ปีที่แล้ว +1

      Thanks, this helped me. I stil wonder why is the reason that it initially didn't work for some people?

    • @Fintendo_NF
      @Fintendo_NF ปีที่แล้ว

      thank you legend

    • @almo4075
      @almo4075 ปีที่แล้ว

      Thank you so much!!!

    • @subspace_ow
      @subspace_ow ปีที่แล้ว

      absolute chad. great fix

  • @MaxIzrin
    @MaxIzrin ปีที่แล้ว +2

    While this will work, there may be an issue with line wrapping, as the text adjusts when additional letters are added.
    Using a text mesh pro, you can set the vertex colors to a transparent color, and then revealing them one letter at a time.
    It should prevent the text from adjusting mid-type, and also make handling the rich text tags trivial.

  • @humbaba2525
    @humbaba2525 2 ปีที่แล้ว +6

    Hi, thanks very much for this helpful series. You may want to consider setting the full text of the Text Mesh Pro object ahead of time and incrementing the maxVisibleCharacters property from zero for each character processed. This helps the situation where the layout may start to write on one line, then split to the next line if the word grows too large, "removing" the characters typed on the first line.

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      You're welcome and thank you for the tip! 🙂 That definitely makes it feel more polished!

    • @hrafnkellorrirastarson7544
      @hrafnkellorrirastarson7544 2 ปีที่แล้ว +2

      came here for this comment :)

    • @Atezian
      @Atezian 2 ปีที่แล้ว

      That's exactly what I needed. Cheers

    • @nathancongdon248
      @nathancongdon248 ปีที่แล้ว

      It also means you don't need to account for the rich text tags, because it's already "typed out" in the string!

    • @yasu3d
      @yasu3d ปีที่แล้ว

      I genuinely cannot thank you enough for pointing this out.
      I didn't even know or consider that TMPro could do that.
      You're a lifesaver and literally saved me from giving up on a project, thank you so much.

  • @indijuegos413
    @indijuegos413 2 ปีที่แล้ว +4

    i just want to say tha THIS is the exactcly dialog system that i was searching for now
    In the nexts weeks i will try to add an assets that adds animation on texts, works by tags on text mesh pro and support ink files, this could be great if it works

  • @imgeorgeirl
    @imgeorgeirl ปีที่แล้ว +2

    I've tried to implement this but whenever I add the if statement in the display choices foreach loop so I can skip dialogue, it will ignore it completely and not display the whole line, but for every subsequent line it displays the whole line without the typewriter effect. I cannot seem to figure out what's going wrong

  • @gaelfernandez6378
    @gaelfernandez6378 2 ปีที่แล้ว +1

    You sir are a genius!

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว +1

      I wouldn't quite say that haha, but thank you so much for the kind words! Glad you're finding these tutorials helpful! 🙂

  • @Wilhelm9218
    @Wilhelm9218 2 ปีที่แล้ว +1

    This is fantastic thank you!! I was able to follow along with everything except my rich text codes are still being typed out awkwardly.

    • @Wilhelm9218
      @Wilhelm9218 2 ปีที่แล้ว

      Happy to report I got it working! I'm extremely new to coding and unity and was using a Text object and not a TMP text object, which apparently made all the difference!

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      @@Wilhelm9218 Ah yeah, that'd do it! 🙂I'm glad you got it working and thank you so much for the kind words!

  • @SestoMazzanti
    @SestoMazzanti 2 ปีที่แล้ว +1

    Thanks! It works!

  • @Dhanen
    @Dhanen 2 ปีที่แล้ว

    Great tutorials, I am enjoying them and understanding most great part even (as you can note by my horrible writting) english is not my first language (neither my second). I want to ask you for the tag for the displaying speed, if it exists (instead using the X.XXf variable) just if you want, for exmple, make slower a couple of words to create expectation. I also want to ask if there is an alternative way to do all those effects to make translations easier is it done with TextMeshPro as you said in your fixed commentary? Thanks so much in advance.

  • @payasoprince9333
    @payasoprince9333 ปีที่แล้ว +2

    Great video dude! But I did notice an issue. When you call "WaitForSeconds(typingSpeed)" the submit button cannot be received while you wait. So there should be a (small) chance that the player presses submit while WaitForSeconds is waiting. To avoid this, you could make a for/while loop for the timer and inside the loop you can check for input. That way player input can be received the entire time.

  • @mahmudsyakiran803
    @mahmudsyakiran803 2 ปีที่แล้ว +1

    Quality content!

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      I really appreciate that and I'm glad you think so! 🙂

  • @abesedad
    @abesedad 6 หลายเดือนก่อน

    u save me.
    love u a lot

  • @Afflictionability
    @Afflictionability ปีที่แล้ว +2

    your tutorials should be the standard lol

  • @DataDrifterOFC
    @DataDrifterOFC 2 ปีที่แล้ว +1

    Hi Trever! First let me thank you so much for awesome tutorials, these are a lifesaver!
    I have a weird problem, I use the dialog to trigger form a button and everything works perfectly but the first line of dialog is shown immediately instead of getting a typing effect. If you have any insight of where I should start looking for the culprit I'd be very grateful.

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      Hey there! I'm really glad you've been finding the tutorials useful!
      This _sounds like_ it could be an Input related issue. For example - the first button press might be registering for both (1) starting the dialogue and (2) continuing to the end of the line in the DisplayLine() Coroutine. I would start with putting some Debug.Log(..) statements wherever there's Input related logic to see if that's the case. If so, you'll likely want to include some logic to ensure that button press only registers once per frame. If you have trouble figuring out how to go about that though - let me know and I can try to stub something out when I have a bit more time.
      If it's not an Input related issue - it could be something to do with your EnterDialogueMode method since it's only happening for the first line. Putting some Debug.Log(..) statements in and around there could help you narrow down what's going on.
      Best of luck and I hope that helps a bit! 🙂

    • @DataDrifterOFC
      @DataDrifterOFC 2 ปีที่แล้ว

      @@ShapedByRainStudios Now that you mentioned it, that is probably the issue, I'll remove mouseclick from submit buttons and try again to rule out the possibility of a doubleclick. Thank you for the offer, I like troubleshooting because it's a good learning experience but if I keep stumbling with this I'll let you know and report back anyway if I get it sorted 👍

    • @DataDrifterOFC
      @DataDrifterOFC 2 ปีที่แล้ว

      @@ShapedByRainStudios You were right on the money, after I removed left click from submit the problem went away! At first I thought the issue was elsewhere but it was just my own fix tries messing the code.
      My dialogueTrigger is on a button so I'll probably just add an IEnumerator with wait in the trigger and then run the dialogue, I guess that would get rid of the simultaneous executions and since everything else works perfectly there's no need to "over-engineer" 🤔
      Thanks again, you are a total bro! Your tutorials are extremely informative and easy to follow after getting the hang of the basics, only part where I was totally lost was the new input system but luckily there's already a ton of tutorials on that.

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว

      @@DataDrifterOFC Glad you figured it out! Adding a short wait either there or in built into your EnterDialogueMode() method seems like a good way to go. 🙂

    • @DataDrifterOFC
      @DataDrifterOFC 2 ปีที่แล้ว

      @@ShapedByRainStudios Yeah for some reason the wait didn't work so I ended up setting a bool to keep track if the line is first in the dialogue, check for it where the typewriting gets skipped, setting it false and re-enabling it in EndDialogue. The dark arts of coding is really new to me but hey, it worked and I'm happy!
      I've learned so much just messing around trying to tweak this to fit my needs that it's crazy. When I get the system finished and get some artwork done I can make a short video of it to show you what I've come up with if you want 😄

  • @qzlocx
    @qzlocx 3 หลายเดือนก่อน

    how would we add interpuncuation delays?

  • @gamoe
    @gamoe ปีที่แล้ว +1

    thanks you

  • @hitm4000
    @hitm4000 ปีที่แล้ว

    7:24
    you should put getkey instead of getkeydown here

    • @gaker19sc
      @gaker19sc ปีที่แล้ว +1

      Then the upcoming lines would also be skipped if the player didn't let go of the button fast enough

  • @__Rizzler__
    @__Rizzler__ 2 ปีที่แล้ว

    I came from reddit

  • @thejfisher9956
    @thejfisher9956 2 ปีที่แล้ว

    how conlangers really make languages: 3:07

  • @jaydenhall9277
    @jaydenhall9277 2 ปีที่แล้ว +2

    my skipping to the end of a line code isnt working and im not sure why, do you have any clue
    if (Input.GetKeyDown(KeyCode.E))
    {
    dialogueText.text = line;
    break;
    }

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว +1

      Hey! 🙂 At first glance, that snippet of code looks fine to me. Without seeing more though, it's hard to tell what could be wrong.
      For troubleshooting, you could put some *Debug.Log(...)* statements around that area to try and see if the code is doing what you'd expect. The main thing I'd check for is if the code is entering that 'if' block when you press the 'E' button or not. That'll give you a good indication of where the problem might be.

    • @MinerProfessional
      @MinerProfessional 2 ปีที่แล้ว

      I have the same problem. Did you find a solution?

    • @MinerProfessional
      @MinerProfessional 2 ปีที่แล้ว

      Works crookedly, the question is open

    • @ShapedByRainStudios
      @ShapedByRainStudios  2 ปีที่แล้ว +16

      @@MinerProfessional Hey! I was just helping someone troubleshoot this and it ended up being that the Input.GetKeyDown(..) wasn't registering within the Coroutine correctly.
      The solution that worked was to store the result of Input.GetKeyDown() in a variable in the Update() method and then reference that variable across the rest of the script - setting it to false so it can't be used twice in the same frame.
      Here's some code snippets that should hopefully help.
      1 - At the top of the DialogueManager class (or whatever script you're using)
      _private bool submitButtonPressedThisFrame = false;_
      2 - In the DialogueManager Update() method:
      private void Update()
      {
      // can replace this with Input.GetKeyDown(..) instead
      if (Input.GetButtonDown("Submit"))
      {
      _submitButtonPressedThisFrame = true;_
      }
      if (!dialogueIsPlaying)
      {
      return;
      }
      if (canContinueToNextLine
      && _submitButtonPressedThisFrame_
      && currentStory.currentChoices.Count == 0)
      {
      // set this to false so that it doesn't also count as input for the Coroutine
      submitButtonPressedThisFrame = false;
      ContinueStory();
      }
      }
      3 - In the Coroutine during the skip part
      if ( _submitButtonPressedThisFrame_ )
      {
      // set to false for good measure so that the input only happens once
      _submitButtonPressedThisFrame = false;_
      dialogueText.text = line;
      break;
      }
      I hope this ends up helping! 🙂

    • @MinerProfessional
      @MinerProfessional 2 ปีที่แล้ว +1

      @@ShapedByRainStudios OMG I'm stupid. It really helped. I had to think about it myself ... Thank you very much that you help solve such stupid questions!