Page 1 of 1

Best way to create a list of text updates that fades out

Posted: 16 Aug 2013, 15:20
by lboldt
Two scenarios:

1) Player gets hit continously by 10 dmg. Above the player I want to display -10 dmg, -10 dmg, -10dmg etc, each string fades out.

2) I have TextBlock in my GUI in the upper left of the screen showing the value 0. Each time it's incrased by 1 I want to display +1, +1, +1 in a "list" below it which also fades out.

I assume both scenarios are solved in a similar way. But the first scenario needs to factor 3D space while the second only 2D space.

Do I just add textblocks dynamically with xyz values of the "parent" object and animate opacity and xyz accordingly? Is this best solved in XAML or through the Unity API?

Thanks!

Re: Best way to create a list of text updates that fades out

Posted: 17 Aug 2013, 02:08
by sfernandez
<Grid
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid.Resources>
        <Storyboard x:Key="AnimDamage" RepeatBehavior="Forever">
            <DoubleAnimationUsingKeyFrames
              Storyboard.TargetName="DamageText"
              Storyboard.TargetProperty="RenderTransform.Children[0].ScaleX">
                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="1.5"/>
                <LinearDoubleKeyFrame KeyTime="0:0:0.5" Value="1.5"/>
                <LinearDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames
               Storyboard.TargetName="DamageText"
               Storyboard.TargetProperty="RenderTransform.Children[0].ScaleY">
                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="1.5"/>
                <LinearDoubleKeyFrame KeyTime="0:0:0.5" Value="1.5"/>
                <LinearDoubleKeyFrame KeyTime="0:0:1" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames
               Storyboard.TargetName="DamageText"
               Storyboard.TargetProperty="RenderTransform.Children[1].Y">
                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:0.2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:1" Value="-80"/>
            </DoubleAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames
               Storyboard.TargetName="DamageText"
               Storyboard.TargetProperty="Foreground.Color">
                <LinearColorKeyFrame KeyTime="0:0:0" Value="#00FF0000"/>
                <LinearColorKeyFrame KeyTime="0:0:0.2" Value="#FFFF0000"/>
                <LinearColorKeyFrame KeyTime="0:0:0.6" Value="#FFFF0000"/>
                <LinearColorKeyFrame KeyTime="0:0:1" Value="#00FF0000"/>
            </ColorAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="AnimPoints" RepeatBehavior="Forever">
            <ObjectAnimationUsingKeyFrames
               Storyboard.TargetName="Points"
               Storyboard.TargetProperty="Text">
                <DiscreteObjectKeyFrame KeyTime="0:0:1" Value="1"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:2" Value="2"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:3" Value="3"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:4" Value="4"/>
                <DiscreteObjectKeyFrame KeyTime="0:0:5" Value="5"/>
            </ObjectAnimationUsingKeyFrames>
            <ColorAnimationUsingKeyFrames
               Storyboard.TargetName="Plus1"
               Storyboard.TargetProperty="Foreground.Color">
                <LinearColorKeyFrame KeyTime="0:0:0" Value="#0000FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:1" Value="#0000FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:1.2" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:1.6" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:2" Value="#0000FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:2.2" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:2.6" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:3" Value="#0000FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:3.2" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:3.6" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:4" Value="#0000FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:4.2" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:4.6" Value="#FF00FF00"/>
                <LinearColorKeyFrame KeyTime="0:0:5" Value="#00000000"/>
            </ColorAnimationUsingKeyFrames>
            <DoubleAnimationUsingKeyFrames
               Storyboard.TargetName="Plus1"
               Storyboard.TargetProperty="RenderTransform.Y">
                <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:2" Value="10"/>
                <LinearDoubleKeyFrame KeyTime="0:0:2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:2.2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:3" Value="10"/>
                <LinearDoubleKeyFrame KeyTime="0:0:3" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:3.2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:4" Value="10"/>
                <LinearDoubleKeyFrame KeyTime="0:0:4" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:4.2" Value="0"/>
                <LinearDoubleKeyFrame KeyTime="0:0:5" Value="10"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Grid.Resources>

    <Grid.Triggers>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard Storyboard="{StaticResource AnimDamage}"/>
            </EventTrigger.Actions>
        </EventTrigger>
        <EventTrigger RoutedEvent="FrameworkElement.Loaded">
            <EventTrigger.Actions>
                <BeginStoryboard Storyboard="{StaticResource AnimPoints}"/>
            </EventTrigger.Actions>
        </EventTrigger>
    </Grid.Triggers>
    
    <!-- Scenario 1 -->
    <Grid x:Name="DamageGroup" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Grid.RenderTransform>
            <!-- Use this to position damage text above player -->
            <TranslateTransform X="200" Y="100"/>
        </Grid.RenderTransform>
        <TextBlock x:Name="DamageText" Text="-10 dmg" FontSize="20"
          Foreground="Red" RenderTransformOrigin="0.5,0.5">
            <TextBlock.RenderTransform>
                <TransformGroup>
                    <ScaleTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </TextBlock.RenderTransform>
        </TextBlock>
    </Grid>
    
    <!-- Scenario 2 -->   
    <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top">
        <TextBlock x:Name="Points" Text="0" FontSize="20" Width="40"
          TextAlignment="Right"/>
        <Grid x:Name="Plus1Group" Width="40">
            <TextBlock x:Name="Plus1" Text="+1" FontSize="20" TextAlignment="Right"
              Foreground="Green">
                <TextBlock.RenderTransform>
                    <TranslateTransform/>
                </TextBlock.RenderTransform>
            </TextBlock>
        </Grid>
    </StackPanel>

</Grid>
Does the previous XAML fit your requirements?

Re: Best way to create a list of text updates that fades out

Posted: 17 Aug 2013, 02:23
by lboldt
Nice one!

That was pretty much what I was looking for. Lots going on here that I need to read through carefully :-)

For others browsing, copy and paste the XAML into Kaxaml to see the nice effects!

Thanks for the effort sfernandez, hopefully others will benefit from this too!

Re: Best way to create a list of text updates that fades out

Posted: 18 Aug 2013, 12:43
by nitro52
Nice, there should be a Community Gallery for things like this.

I do have a question though. Say you get hit 3 times within the time it takes to animate it would look like you only got hit once won't it?

would you have to dynamically spawn a new TextBlock each time you were hit? Would you have to add it to the Grid's content?

Re: Best way to create a list of text updates that fades out

Posted: 18 Aug 2013, 14:29
by lboldt
I've converted the above example to a mix between XAML and C# within Unity so I can display the correct values etc. The cool thing about storyboards is that you can reuse it and "apply it" to any control that supports it.

I'm not an expert here, but this is how I did it (slightly changed for the purpose of example):
<Storyboard x:Key="AnimStats" RepeatBehavior="0:0:2">
      <ColorAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground.Color">
        <LinearColorKeyFrame KeyTime="0:0:0" Value="#0000FF00"/>
        <LinearColorKeyFrame KeyTime="0:0:1" Value="#0000FF00"/>
        <LinearColorKeyFrame KeyTime="0:0:1.2" Value="#FF00FF00"/>
        <LinearColorKeyFrame KeyTime="0:0:1.6" Value="#FF00FF00"/>
        <LinearColorKeyFrame KeyTime="0:0:2" Value="#0000FF00"/>
      </ColorAnimationUsingKeyFrames>
      <DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="RenderTransform.Y">
        <LinearDoubleKeyFrame KeyTime="0:0:0" Value="0"/>
        <LinearDoubleKeyFrame KeyTime="0:0:1" Value="0"/>
        <LinearDoubleKeyFrame KeyTime="0:0:1.2" Value="0"/>
        <LinearDoubleKeyFrame KeyTime="0:0:2" Value="10"/>
      </DoubleAnimationUsingKeyFrames>
    </Storyboard>
For some reason the animation would run 2 times if I didn't specify a RepeatBehaviour that matched the animation length, not sure if this is how XAML works or not, like I said, not an expert :-)

Now in C#:
NoesisGUIPanel gui = GetComponent<NoesisGUIPanel>();		
FrameworkElement root = gui.GetRoot<FrameworkElement>();

Stackpanel goldPnlAnim = root.FindName<StackPanel>("goldPnlAnim"); // Aligned in XAML so that any child in it ends up where they should

// Get storyboard
Storyboard animStats = root.FindStringResource<Storyboard>("AnimStats");

// Now simply create a textblock, add it to stackpanel and apply storyboard animation
TextBlock goldAnim = new TextBlock();
TextBlock.SetText("+10");
goldPnlAnim.GetChildren().Add(goldAnim);
animStats.Begin(goldAnim);
// When animation is complete, send it to an event handler that destroys it or whatever you want to do with it
animStats.Completed += OnAnimComplete;
If there are better ways to do it I'm all ears!

Re: Best way to create a list of text updates that fades out

Posted: 19 Aug 2013, 07:59
by nitro52
Yeah i think this pretty much what i was thinking you would need to do. As you mentioned in the event it would be important to remove the texblock from the stackpanel or recycle the texblock in some way. otherwise it would just continually grow.

Re: Best way to create a list of text updates that fades out

Posted: 19 Aug 2013, 11:19
by pSupaNova
Nice, there should be a Community Gallery for things like this.
Agree.

Also could you show some simple examples of these.

Health/Status Bars that follow Gameobjects.
Radar
Minimap
inventory Slots
Sliding Picture Thumbnails.

Thanks.