- Home /
 
attack damage scrolling
I'm trying to create basic combat text and the way I was thinking of doing it is spawning a new guiText object everytime you take damage. I'm just unsure about how to spawn multiple instances of the same guitext for each different ammount of damage you take and then scroll for a while upwards before deleting the object completly.
Answer by aldonaletto · May 27, 2011 at 01:16 AM
I did it with GUIText. That's the sequence:
1- Create a GUIText and select its properties (font, size etc.)
2- Create the script below and add it to the GUIText:
 public var color: Color = Color(0.8,0.8,0,1.0);
 public var scroll: float = 0.05;  // scrolling velocity
 public var duration: float = 1.5; // time to die
 public var alpha: float;
 
 function Start(){
     guiText.material.color = color; // set text color
     alpha = 1;
 }
 
 function Update(){
     if (alpha>0){
         transform.position.y += scroll*Time.deltaTime; 
         alpha -= Time.deltaTime/duration; 
         guiText.material.color.a = alpha;        
     } else {
         Destroy(gameObject); // text vanished - destroy itself
     }
 }
 
               3- Drag the GUIText from Hierarchy to Project view to make it a prefab
4- Add these lines to the script where the effect will be fired:
 var ptsPrefab: Transform; // drag the prefab to this variable in Inspector
 
 function SpawnPts(points: float, x: float, y: float){
     x = Mathf.Clamp(x,0.05,0.95); // clamp position to screen to ensure
     y = Mathf.Clamp(y,0.05,0.9);  // the string will be visible
     var gui: Transform = Instantiate(ptsPrefab,Vector3(x,y,0),Quaternion.identity);
     gui.guiText.text = points.ToString();
 }
 
               5- Drag the prefab you've made to the ptsPrefab var in the Inspector
Done! If you fire the effect calling something like this:
 SpawnPts(150,0.3,0.4);
 
               you will see a yellow 150 appearing at the GUI position 0.3,0.4 and going up while vanishing to death.
EDITED: If you want it to appear at the position the object is picked, use this in the object's OnTriggerEnter function:
 var v:Vector3 = Camera.main.WorldToViewportPoint(transform.position);
 SpawnPts(100, v.x, v.y); // 100 points picked
 
               If it's a damage value, you can create the scrolling points in the ApplyDamage (or equivalent) function, using the hit point as the origin (called hitPoint here):
 var v:Vector3 = Camera.main.WorldToViewportPoint(hitPoint);
 SpawnPts(damage, v.x, v.y); 
 
 
              Yours is nicer than $$anonymous$$e. In the last line, use Vector3 pp = Camera.WorldToViewPort(thingThatWasHit); to get the x and y values (in place of 0.3 and 0.4.) $$anonymous$$aybe add 0.05 to y so you don't spawn at the feet.
Good idea, Owen. I tried to do something like that, but the function I used to locate the screen spot didn't work for some stupid reason; I'll try this one soon. Thanks!
also if you want to maintain the selected prefab color remove guiText.material.color = Color(0.8,0.8,0,1.0);
Answer by Owen-Reynolds · May 26, 2011 at 11:33 PM
I've done that with GUITexts, and it does work OK. A few ways to do it (I currently use an array and ONGui to make them all for the entire sceeen.)
Make a GUIText prefab with a script on it. When you get hit, Instantiate the GUItext prefab and fill in the value. Don't worry about position or rotation, since the script will be setting those. Rough idea:
 // Whenever we do damage:
 // spawn floating damage text, position/rotation won't matter:
 Transform damageText = Instantiate(dmgPrefab, Vector3.zero, Quaternion.identity);
 // set text:
 damageText.GUIText.Text = "-4";
 // set color if we added a GUIstyle:
 damageText.GetComponent<dmgPrefabScript>().GStyle.color = Color.red;
 // set target to thing we hit:
 damageText.GetComponent<dmgPrefabScript>().target = orcThatgotHit;
 
 // the GUIText script:
 Transform target; // the guy I am on. Filled in by the guy who Instantiates me
 float rise=0; // 0 to 0.5 -- what % of the screen I am up
 void Update() {
   // Find spot to draw it on the sceen:
   // GUITexts are in screen coords: 0-1 L/R, 0-1 U/D
   // this converts the orc's (x,y,z) into the screen spot:
   transform.position = Camera.WorldToScreen(target);
   // -z means it is behind us (I think)
   if(transformtarget.z<0) transform.position = Vector3.up*100; // off screen
   // it is now ON the orc, move it up:
   transform.position += rise * Vector3.up;
 
   // rise up a little for next frame:
   rise += 0.02f; // this a percent of the screen, per frame, so small
 
   // Could die after 2 secs, but dieing after going up 50% is easier:
   //fading out would be cooler, but more work:
   if(rise>0.5f) Destroy(gameObject);
 }
 
              Answer by firestoke · Nov 11, 2015 at 01:03 AM
Thank for aldonaletto's answer. I reference his code and make some changes for C# and Unity5. Additional, I add another display mode via using TextMesh. Here is my code (it's tested, should be work. BTW, I use it in a 2D game.):
 using UnityEngine;
 using UnityEngine.UI;
 using System.Collections;
 
 public class FlyingText : MonoBehaviour {
     // attributes
     public float speed = 0.0f;
     public float duration = 20f;
     public float alpha = 1f;
     public bool bTextMesh = false;
 
     // this will create a UI text game object in the passed canvas transform
     // parameters: pos - it should be a world space position value
     //             parentTransform - it should be a canvas game object's transform
     public static FlyingText getInstance(string text, Vector3 pos, int fontSize, Color color, float speed, float duration, Transform parentTransform) {
         // create game object
         GameObject obj = new GameObject ("Flying Text");
         obj.transform.parent = parentTransform;
         obj.transform.position = Camera.main.WorldToScreenPoint (pos);
         obj.transform.localScale = new Vector3 (1, 1, 1);
 
         // add text component
         Text t = obj.AddComponent<Text> ();
         t.text = text;
         t.alignment = TextAnchor.MiddleCenter;
         t.font = Font.CreateDynamicFontFromOSFont ("Arial", 20);
         //t.font = Resources.Load ("Fonts/slkscr") as Font; // use custom font
         t.fontSize = fontSize;
         t.color = color;
 
         // change rect transform value
         RectTransform rt = obj.GetComponent<RectTransform> ();
         rt.sizeDelta = new Vector2 (200, 40);
         
         // add script component
         FlyingText ft = obj.AddComponent<FlyingText> ();
         ft.bTextMesh = false;
         ft.speed = speed;
         ft.duration = duration;
 
         return ft;
     }
 
     // this will create a TextMesh game object in the passed parent transform
     public static FlyingText getInstanceWithTextMesh(string text, Vector3 pos, int fontSize, Color color, float speed, float duration, Transform parentTransform) {
         pos.z = parentTransform.position.z;
 
         // create game object
         GameObject obj = new GameObject ("Flying Text");
         obj.transform.parent = parentTransform;
         obj.transform.position = pos;
         obj.transform.localScale = new Vector3 (1, 1, 1);
         
         // add text component
         TextMesh t = obj.AddComponent<TextMesh> ();
         t.text = text;
         t.alignment = TextAlignment.Left;
         t.font = Font.CreateDynamicFontFromOSFont ("Arial", 20);
 //        t.font = Resources.Load ("Fonts/slkscr") as Font;
         t.fontSize = fontSize;
         t.color = color;
         t.characterSize = 0.1f;
 
         // assign renderer material
         Renderer r = obj.GetComponent<Renderer> ();
         r.sharedMaterial = t.font.material;
     // set position, make the passed pos parameter as center
     pos.x -= r.bounds.size.x / 2;
     obj.transform.position = pos;
         
         // add script component
         FlyingText ft = obj.AddComponent<FlyingText> ();
         ft.bTextMesh = true;
         ft.speed = speed;
         ft.duration = duration;
         
         return ft;
     }
     
     // Update is called once per frame
     void Update () {
         if (alpha > 0) {
             // change the y position
             Vector3 pos = transform.position;
             pos.y += speed * Time.deltaTime;
             transform.position = pos;
 
             // change alpha value
             alpha -= Time.deltaTime/duration;
 
             if( bTextMesh ) {
                 TextMesh t = GetComponent<TextMesh> ();
                 Color color = t.color;
                 color.a = alpha;
                 t.color = color;
             } else {
                 Text t = GetComponent<Text> ();
                 Color color = t.color;
                 color.a = alpha;
                 t.color = color;
             }
         } else {
             // destroy the game object if it's invisible
             Destroy(gameObject);
         }
     }
 }
 
               Usage:
 // create a flying text via UI Text
 string text = "12345";
 Vector2 pos = transform.position;
 float speed = 20f;
 float duration = 5f;
 GameObject canvas = GameObject.Find ("UICanvas");
 FlyingText.getInstance (text, pos, 20, Color.red, speed, duration, canvas.transform);
 // create a flying text via TextMesh
 speed = 0.3f;
 Transform parentTransform = GameObject.Find ("Someone").transform;
 FlyingText.getInstanceWithTextMesh(text, pos, 24, Color.red, speed, duration, parentTransform);
 
               That's it. The following is the screenshot of testing result. 
Answer by GlennHeckman · May 26, 2011 at 11:19 PM
This is untested code, but give this a try:
 private var damageList:String[];
 private var scrollPosition:Vector2 = Vector2.zero;
 
 function addNewDamage(d:String):void
 {
     damageList.push(d);
     yield WaitForSeconds (5);
     if(damageList.Length > 0)
        damageList.Shift();
 }
 
 function OnGUI()
 {
      scrollPosition = GUILayout.BeginScrollView (scrollPosition ,500,300);
      for(var i:int = damageList.Length-1; i >= 0; i--)
      {
         GUILayout.Label(GUIContent (damageList[i]));
      }
      GUILayout.EndScrollView();
 }
 
 // this goes in the function where you get damaged
 addNewDamage("Gun shot -15");
 
              Answer by Wylht · Mar 09, 2016 at 06:58 AM
Hello, this post and the aldonaletto answer is a little old, but i think it is very helpful, so I updated it a little for C# bellow: Like he said, create the GUIText and use this script bellow inside this GUIText's public class monoBehaviour :
     public Color color = new Color(0.8f,0.8f,0,1.0f);
     public float scroll = 0.02f;  // scrolling velocity
     public float duration = 4.5f; // time to die
     public float alpha;
     
     void  Start (){
         GetComponent<GUIText>().material.color = color; // set text color
         alpha = 1;
     }
     
     void  Update (){
         if (alpha>0){
             Vector3 temp = transform.position; 
             temp.y += scroll*Time.deltaTime;
             transform.position = temp;
             alpha -= Time.deltaTime/duration; 
             Color tempC=GetComponent<GUIText>().material.color;
             tempC.a=alpha;
             GetComponent<GUIText>().material.color=tempC;       
         } else {
             Destroy(gameObject); // text vanished - destroy itself
         }
     }
 
               So do what he said, transform it in a prefab dragging to project view. And inside the code where you want to fire it use this code bellow:
 public Transform ptsPrefab;
 
 void  SpawnPts ( float points ,   float x ,   float y  ){
         x = Mathf.Clamp(x,0.05f,0.95f); // clamp position to screen to ensure
         y = Mathf.Clamp(y,0.05f,0.9f);  // the string will be visible
         Transform gui = Instantiate(ptsPrefab,new Vector3(x,y,0),Quaternion.identity) as Transform;
         gui.GetComponent<GUIText>().text = points.ToString();
     }
 
               Drag the prefab to the inspector inside the public ptsPrefab and you can fire it with:
 Vector3 v= Camera.main.WorldToViewportPoint(transform.position);
 SpawnPts(150,v.x,v.y);
 
              Do you think it is wise to answer an question from 2011? The GUIText has been obsolete for some time now.
Don't answer Q's from 5(!) years ago (or as you say, a little old ;) ) please, even if they are not closed for some reason. Now this question pops up in the news feed and takes the place of a relevant question.
sure, i think it wise update an good answer of a question made in 2011, sorry if you didnt like. :/
Your answer