Moving UI Text

I am trying to display points scored at different locations on the screen; where characters are destroyed.

Why does the following method not work?

1 Like

Hey @RetroDan, cool idea =D

I think that this is happening because you are instantiating it to a world position reference while the text is using the position inside the canvas as reference to be displayed. This don’t happen when a text actually exists since the text is already with a reference inside the canvas.

One option would be to create a gameobject with a canvas and setting this canvas scale to a very small scale (really, really small) and then create a text on it with a script, then you set it`s render mode to world space, now you can instantiate this new prefab in a world position and set it to be destroyed after a couple of seconds. (I’m saying this because i had the same problem, I was trying to display the damage done to the enemies, this was the solution that I found).

Probably there are some other options such as:

  • instantiate it using a camera position or screen position, you would have to create a some variables to get the world space reference and transform it to camera/screen position and set it as parameter to get the reference under the canvas space, but honestly I don`t even have a clue about how one could do that xD

This one would have a better performance than the one that I used too =x but I still have to try that, I`m quite a beginner into coding, probably other members will give better solutions to it too.

looking forward to see this working inside your game!! :grinning:

I tried putting a canvas inside and object. them move the object around.
That did not work.

I will try to instantiate that object around the screen.

You are welcome! Did you manage solve it?

No, I tried to instantiate the object, but that does not work either; The object will not budge from its initial position.
Here is my code for that; have I done it right? Points is what I am trying to move.

1 Like

How is the points gameobject? In which kind of canvas he is in?

Here is how it is arranged in the Hierarchy:

This is the Canvas in the Inspector:

1 Like

Set the canvas render mode to world space and it should work, i dont know thought if the canvas can be inside another gameobject, but i think so

I can now move the object with canvas manually in the inspector, but I still cannot move from script?
It still won’t instantiate the Object with the Canvas inside.

That line triggers a run-time error and immediate return.

1 Like

Have you tried a Raycast?
You should be able to cast a ray from the object to the camera (or vice versa). Where it intersects the Canvas plane should give you coordinates for where to place your text box.

Retro, I dont know why it is not working, by the way, is there a reason to this gameobject having a rigidbody and collider?

Here is the Error I am getting now:

Here is where I dropped the “Points” prefab into the script.

And “Points” is the object that contains the Canvas and Text:

1 Like

Did you get it sorted yet Dan?

just looking at the initial post, you have declared a reference to a Text type with pointsText;
private Text pointsText;

but its not being assigned anything that I can see;

Ive never used the worldspace canvas before, but I thought I would have a play around with it this evening.

ive created a package and uploaded it to dropbox of the scene i was testing out.

create a new project and then import this package and then open the scene thats in there.
if you play it, the green dot moves right to left, and as it collides with a red circle it destroys it and then shows hit points on a new world space canvas.
see if it helps you out any.

what I done was;

  • create a baddie sprite gameobject.
  • I attached a Canvas (called Points Canvas) as a child of that baddie sprite and set it to world space and set the blocking to none.
  • set the canvas position to 0, 0, 0 so its centre of its parent (the baddie), and just set its width and height to 1 and 1.
  • i set the canvas scale to 0.1, 0.1, 0.1.
  • added a Text component to that Canvas, setting the text to display 200 just as a placeholder.
    you can see the settings i used for the Text component in the asset package.
  • I added a small script ‘DestroyMeTimer.cs’ to the canvas object, just so I can destroy it automatically after say 2 seconds.
  • Created a prefab of that canvas, and deleted it from the scene.

so Ive now got a prefab of a small world space canvas i can instantiate at runtime.

I then went to the baddie prefab and added a script to it so i can instantiate the canvas on collision.
its the ShowPointsUI.cs script.
that script has a public method in there, so I can call it and pass it in the number to display.

on the goodie object, i have a simple script to move it over time, and an OnTriggerEnter2D method in there too, so when it collides with the baddie, it finds its ShowPointsUI component and calls the DisplayPoints() method to create the canvas.

Its by no means elegant or fully fleshed out, but its all i could figure out in the meantime to see if it helps.

1 Like

I don’t know why this is happening, my structure is similar to yours, my arrow projectile is this:

public class ArrowProprieties : MonoBehaviour {

	Renderer CorCritico;
	public GameObject ParticleCrit;
	public float damage = 100;
	float CritRoll;
	public GameObject Scrollingtext;
	void Start()
	{
		CritRoll = Random.value;
		if (CritRoll <= (GameObject.Find("Player").GetComponent<MovementController>().Crt))
		{
			damage = damage*GameObject.Find("Player").GetComponent<MovementController>().AtkMult*2;
			CorCritico = GetComponent<SpriteRenderer>();
			CorCritico.material.color = Color.red;
			GameObject Ptcl = Instantiate (ParticleCrit, gameObject.transform.position, Quaternion.identity) as GameObject;
			Ptcl.transform.SetParent(gameObject.transform);
			gameObject.GetComponent<Rigidbody2D>().mass = 0.4f;
			damage = damage* Random.Range(0.85f,1.15f);
		}
		else
		{
			damage = damage*GameObject.Find("Player").GetComponent<MovementController>().AtkMult;
			damage = damage* Random.Range(0.85f,1.15f);
		}
	}
	void OnCollisionEnter2D(Collision2D collider)
	{
		EnemyBehaviourScript Monstro = collider.gameObject.GetComponent<EnemyBehaviourScript>();
		if(Monstro)
		{
			gameObject.transform.SetParent(collider.transform);
			gameObject.transform.GetComponent<BoxCollider2D>().enabled = false;
			gameObject.transform.GetComponent<Rigidbody2D>().isKinematic = true;
			Destroy(gameObject, 10f);
			GameObject sctx = Instantiate (Scrollingtext, transform.position, Quaternion.identity) as GameObject;
			sctx.transform.GetChild(0).GetComponent<DmgScroll>().dmgdelt = this.damage;
			print (damage);
		}

	}
}

and this is the script in my text:

using UnityEngine.UI;

public class DmgScroll : MonoBehaviour {
	public Text Dmg;
	public float dmgdelt;
	void Start () 
	{
	`	Dmg = GetComponent<Text>();
		Destroy(gameObject.transform.parent.gameObject,0.5f);
		Destroy(gameObject,0.6f);


	}
	void Update()
	{
		int danoint = (int) dmgdelt;
		Dmg.text = danoint.ToString();
		gameObject.transform.Translate(0, 1 * Time.deltaTime, 0,Space.World);

	}

}

My prefab inspector:

the game i’m using it:
http://gamebucket.io/game/a48e8bdd-5848-4610-8a59-b5e5c8464e7b

@OboShape I an trying your method of instantiating a Canvas at the collision point.
Here is my code, can you spot anything wrong, DisplayPoints(100) will not execute.

Why can’t I move Points around like any other object?

1 Like

for the Points gameobject.

Im assuming that Points refers to a gameobject that is currently within the scene?

in the inspector if we drag an object from the scene into a public variable slot it stores a reference as to where to find that exact instance of the gameobject again and refer to it.
but if that gameobject that Points refers to, is deleted or removed from the scene, it no longer knows where to find it and you get errors when you try to use it.

if the public variable slot refers to a prefab, it must be instantiated first before we have an instance of it to work with change etc. as the prefab is more a template and objects can be instantiated/created based on the prefab template.

also as a note, if you have the canvas on this Points gameobject set to ‘screen space’ its rect transform/position is purely driven by the camera frustum, which is indicated in the inspector as its uneditable. this can be seen in action if we have the game and scene views open, and if we change the size of the game window, you can see the canvas scale in the scene view as we alter the size of the game window.

need to excuse me if syntax etc is off a bit, just writing off the cuff just now as dont have Unity/Mono open

onto the DisplayPoints() method
Ive just editited it slightly to add a heap of comments and alot of debug statements so we can see where the issue may lie.

public void DisplayPoints(int points)
{
Debug.Log(“Display Points method called. to display " + points + " points score”);
// Canvas2 is a prefab, so we need to instantiate it in our scene
// instantiate on its own just creates an instance of Canvas2 in the scene of an Object type
// but it wont give us a reference to do anything with it, it just simply creates it and positions it with
// whatever the transform position is in the Prefab. which is generally why you zero out the positions of a prefab.
// So we know its a Canvas type, we can create a temporary reference, in this case ’ temp’ to store how to refer
// to it once its created
// and then tell unity to instantiate an instance of Canvas2, but instantiate it as a type Canvas
// and store a reference to it in the variable temp.
Canvas temp = Instantiate(Canvas2, transform.position, Quaternion.identity) as Canvas;

// did it instantiate?
if(temp == null)
Debug.Log(“failed to instantiate Canvas2 prefab.”);
else
Debug.Log(“Canvas2 instance created.”);

  // can I find the Text component child in the Canvas we created
  Text tempTextRef = temp.GetComponentInChildren<Text>();
  if (tempTextRef == null)
  	Debug.Log("Cannot find Text component of instantiated canvas");
  else
  	tempTextRef.text = points.ToString();
  }

If you want and you cant get it going the way you would like and need an extra pair of eyes, Im not away to work this weekend if you zip the project up onto dropbox or something I can always have a look for you.

1 Like

Morning,

if your dmgText script Start method.

where you have
Dmg = GetComponent();

remember that GetComponent is a generic and needs the < >, so geting the Text component would be.

Dmg = GetComponent<Text>();

1 Like

hello @OboShape, the forum don’t allow to use some characters in some situations, the script does have the GetComponent<Text>, thank you for noting that the one I’ve sent here lost this part, I’ll edit it.

Ah, sorry :frowning:

1 Like

no problem, :grinning:
You don’t have to be sorry, it was good that you spotted that, I was the one using the wrong tool(Quote) to send the code, I should be using the “Preformatted text” from the text editor here in the forum.