This script position text/numbers in front/above objects depending on the flags settings to true or false.
It was working fine when I called the method ChangeTextPosition only in the Start
but now I want to make that the changes will be also in the Update if I enable false the above or front it will remove the numbers/text and if both enabled true then it will position the numbers above and the text in front if only numbers is true it will position only the numbers above without the text at all and if only text then without the numbers.
Same it should be in the Start, if when starting the game and only one of the flags is true then only show the one is true and if both then show both.
Now when I called it in the Update it's just keep creating none stop numbers and texts.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class Generatenumbers : MonoBehaviour
{
public UnityEngine.GameObject[] objectsToNumber;
public UnityEngine.GameObject text;
public float yPadding;
public bool rotateNumbers = false;
public float rotationSpeed = 10f;
public bool textAbove = false;
public bool textInFront = false;
public bool textOnFaces = false;
private List<GameObject> newTexts = new List<GameObject>();
private MeshRenderer[] renderer;
private Vector3 newPos;
private TextMesh textmesh;
private int numbers;
private void Start()
{
renderer = new MeshRenderer[objectsToNumber.Length];
ChangeTextPosition();
}
private void Update()
{
if (rotateNumbers == true)
{
for (int i = 0; i < newTexts.Count; i++)
{
newTexts[i].transform.Rotate(Vector3.up, 10 * rotationSpeed * Time.deltaTime);
}
}
ChangeTextPosition();
}
private void ChangeTextPosition()
{
for (int i = 0; i < objectsToNumber.Length; i++)
{
GameObject newText = Instantiate(text);
renderer[i] = newText.GetComponent<MeshRenderer>();
if (textAbove == true)
{
newPos = new Vector3
(
objectsToNumber[i].transform.position.x,
((objectsToNumber[i].transform.position.y + renderer[i].bounds.extents.y) + yPadding),
objectsToNumber[i].transform.position.z
);
}
if (textInFront == true)
{
newPos = new Vector3
(
((objectsToNumber[i].transform.position.x + renderer[i].bounds.extents.x) + yPadding),
objectsToNumber[i].transform.position.y,
objectsToNumber[i].transform.position.z
);
}
newText.transform.position = newPos;
newText.transform.parent = transform;
newText.name = i.ToString();
newText.tag = "Number";
newTexts.Add(newText);
textmesh = newText.GetComponent<TextMesh>();
textmesh.transform.localRotation = Quaternion.Euler(0, -90, 0);
if (textAbove == true)
{
textmesh.text = i.ToString();
}
if (textInFront == true)
{
textmesh.text = "Hello World";
}
}
}
}
What I tried so far :
First I tried to use only the Start. The rules should be if one of the flags textAbove or textInfront is true put the numbers/text above or in front. If both are true put both text and numbers the numbers above the text in front. if both false don't add anything if one is false one is true add only the one that true.
Same rules for the Update.
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class Generatenumbers : MonoBehaviour
{
public UnityEngine.GameObject[] objectsToNumber;
public UnityEngine.GameObject text;
public float yPadding;
public bool rotateNumbers = false;
public float rotationSpeed = 10f;
public bool textAbove = false;
public bool textInFront = false;
public bool textOnFaces = false;
private List<GameObject> newTexts = new List<GameObject>();
private MeshRenderer[] renderer;
private Vector3 newPosAbove;
private Vector3 newPosFront;
private List<Vector3> newPositions = new List<Vector3>();
private TextMesh textmesh;
private int numbers;
private List<GameObject> textInstances = new List<GameObject>();
private void Start()
{
renderer = new MeshRenderer[objectsToNumber.Length];
for (int i = 0; i < objectsToNumber.Length; i++)
{
textInstances.Add(Instantiate(text));
}
ChangeTextPosition();
}
private void Update()
{
if (rotateNumbers == true)
{
for (int i = 0; i < newTexts.Count; i++)
{
newTexts[i].transform.Rotate(Vector3.up, 10 * rotationSpeed * Time.deltaTime);
}
}
//ChangeTextPosition();
}
private void ChangeTextPosition()
{
for (int i = 0; i < objectsToNumber.Length; i++)
{
renderer[i] = textInstances[i].GetComponent<MeshRenderer>();
if (textAbove == true)
{
newPosAbove = new Vector3
(
objectsToNumber[i].transform.position.x,
((objectsToNumber[i].transform.position.y + renderer[i].bounds.extents.y) + yPadding),
objectsToNumber[i].transform.position.z
);
newPositions.Add(newPosAbove);
}
if (textInFront == true)
{
newPosFront = new Vector3
(
((objectsToNumber[i].transform.position.x + renderer[i].bounds.extents.x) + yPadding),
objectsToNumber[i].transform.position.y,
objectsToNumber[i].transform.position.z
);
newPositions.Add(newPosFront);
}
for(int x = 0; x < newPositions.Count; x++)
{
textInstances[i].transform.position = newPositions[x];
textInstances[i].transform.parent = transform;
textInstances[i].name = i.ToString();
textInstances[i].tag = "Number";
newTexts.Add(textInstances[i]);
textmesh = textInstances[i].GetComponent<TextMesh>();
textmesh.transform.localRotation = Quaternion.Euler(0, -90, 0);
if (textAbove == true)
{
textmesh.text = i.ToString();
}
}
}
}
}
But this is not working good even only for the Start()
It's showing only numbers and only the numbers 1,3,5 and it should show 6 numbers since there are 6 objects 3 numbers above and 3 in front. Each object should have a number above and in front.
Related
So I am trying to create a game where a player can swing with a rope/grappling hook, similar to a game like Teeworlds. The grappling hook feels great when I am hooked onto things and I am using my movement keys, the problem comes when I let go of my left or right movement keys the character slowly floats down. Feels like the gravity gets put to like 0.00001 on the character until i let go of the grappling hook button.
Will post a gif of how it looks and the code I am using for the grappling hook.
Thanks,
The Pepsidi.
Game Play of Issue
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
public class GrappleSystem : MonoBehaviour
{
public GameObject grappleAnchor;
public DistanceJoint2D grappleJoint;
public Transform crosshair;
public PlayerMovement playerMovement;
private bool grappleAttached;
private Vector2 playerPosition;
private Rigidbody2D grappleAnchorRb;
private SpriteRenderer grappleAnchorSprite;
public LineRenderer grappleRenderer;
public LayerMask grappleLayerMask;
private float grappleMaxCastDistance = 20f;
private List<Vector2> grapplePositions = new List<Vector2>();
private bool distanceSet;
void Awake()
{
grappleJoint.enabled = false;
playerPosition = transform.position;
grappleAnchorRb = grappleAnchor.GetComponent<Rigidbody2D>();
grappleAnchorSprite = grappleAnchor.GetComponent<SpriteRenderer>();
}
void Update()
{
var worldMousePosition = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f));
var facingDirection = worldMousePosition - transform.position;
var aimAngle = Mathf.Atan2(facingDirection.y, facingDirection.x);
if (aimAngle < 0f)
{
aimAngle = Mathf.PI * 2 + aimAngle;
}
var aimDirection = Quaternion.Euler(0, 0, aimAngle * Mathf.Rad2Deg) * Vector2.right;
playerPosition = transform.position;
if (!grappleAttached)
{
SetCrosshairPosition(aimAngle);
}
HandleInput(aimDirection);
UpdateGrapplePositions();
}
private void SetCrosshairPosition(float aimAngle)
{
var x = transform.position.x + 5f * Mathf.Cos(aimAngle);
var y = transform.position.y + 5f * Mathf.Sin(aimAngle);
var crossHairPosition = new Vector3(x, y, 0);
crosshair.transform.position = crossHairPosition;
}
private void HandleInput(Vector2 aimDirection)
{
if (Input.GetMouseButtonDown(1))
{
if (grappleAttached) return;
grappleRenderer.enabled = true;
var hit = Physics2D.Raycast(playerPosition, aimDirection, grappleMaxCastDistance, grappleLayerMask);
if (hit.collider != null)
{
grappleAttached = true;
if (!grapplePositions.Contains(hit.point))
{
transform.GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, 5f), ForceMode2D.Force);
grapplePositions.Add(hit.point);
grappleJoint.distance = Vector2.Distance(playerPosition, hit.point);
grappleJoint.enabled = true;
grappleAnchorSprite.enabled = true;
}
}
else
{
grappleRenderer.enabled = false;
grappleAttached = false;
grappleJoint.enabled = false;
}
}
if (Input.GetMouseButtonUp(1))
{
ResetGrapple();
}
}
private void ResetGrapple()
{
grappleJoint.enabled = false;
grappleAttached = false;
//playerMovement.isSwinging = false;
grappleRenderer.positionCount = 2;
grappleRenderer.SetPosition(0, transform.position);
grappleRenderer.SetPosition(1, transform.position);
grapplePositions.Clear();
grappleAnchorSprite.enabled = false;
}
private void UpdateGrapplePositions()
{
if (!grappleAttached)
{
return;
}
grappleRenderer.positionCount = grapplePositions.Count + 1;
for (var i = grappleRenderer.positionCount - 1; i >= 0; i--)
{
if (i != grappleRenderer.positionCount - 1)
{
grappleRenderer.SetPosition(i, grapplePositions[i]);
if (i == grapplePositions.Count - 1 || grapplePositions.Count == 1)
{
var grapplePosition = grapplePositions[grapplePositions.Count - 1];
if (grapplePositions.Count == 1)
{
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
else
{
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
}
else if (i - 1 == grapplePositions.IndexOf(grapplePositions.Last()))
{
var grapplePosition = grapplePositions.Last();
grappleAnchorRb.transform.position = grapplePosition;
if (!distanceSet)
{
grappleJoint.distance = Vector2.Distance(transform.position, grapplePosition);
distanceSet = true;
}
}
}
else
{
grappleRenderer.SetPosition(i, transform.position);
}
}
}
}
First I find the objects that interest me using GameObject.FindGameObjectsWithTag. And I bring them into one array All[ ] . I create NavMeshAgent>. I drive the agent to selected points on the map. Until he meets someone from the All[ ] array. And it would seem that everything works, but BUT. The agent only triggers on the last object in the array. I sat for 2 days, tried many ways, the result is the same, it can run the array not through ( foreach or for ) . Maybe there is a complex solution to the problem. Or even another way, I'm in the programming of bread, but I try my best. Any idea is accepted and tested. Thanks!!!
public void getTarget(GameObject[] targets) runs through array objects - this is where the problem lies
public GameObject[] Concat(GameObject[] first, GameObject[] second, GameObject[] third) concatenates arrays of objects
public void moveToTarget(Vector3 target) points to the target for the
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MinionMoveByLine : MonoBehaviour
{
public enum MovementType
{
Moveing,
Learp
}
//Переменные для перемещения по карте
public MovementType type = MovementType.Moveing;
public NavMeshLineToMove MyLine;
public float speed = 1;
public float maxDistance = .3f;
private NavMeshAgent enemy;
//Переменные для растояний и приоритета крипов
private GameObject[] minions;
private GameObject[] towers;
private GameObject[] players;
private GameObject[] All;
public GameObject minion;
private Vector3[] position;
private Vector3 targetPosition;
private float distanceVisionForAttack = 6f;
private float radiusOfAttack = 2f;
private IEnumerator<Transform> pointInPath;
// Start is called before the first frame update
void Start()
{
minions = GameObject.FindGameObjectsWithTag("minion");
towers = GameObject.FindGameObjectsWithTag("tower");
players = GameObject.FindGameObjectsWithTag("player");
All = Concat(players, towers, minions);
Debug.Log("minions "+ minions.Length);
Debug.Log("towers " + towers.Length);
Debug.Log("players " + players.Length);
minion = (GameObject)this.gameObject;
enemy = GetComponent<NavMeshAgent>();
if (MyLine == null)
{
Debug.Log("Line Not Set");
return;
}
pointInPath = MyLine.GetNextPathPoint();
pointInPath.MoveNext();
if (pointInPath.Current == null)
{
Debug.Log("Need point to move");
return;
}
transform.position = pointInPath.Current.position;
}
void LateUpdate()
{
Vector3 position = minion.transform.position;
if (pointInPath == null || pointInPath.Current == null)
{
return;
}
foreach(var obj in All)
{
Debug.Log(All.Length);
Debug.Log(obj);
}
getTarget(All);
var distanceSqure = (transform.position - pointInPath.Current.position).sqrMagnitude;
if (distanceSqure < maxDistance * maxDistance)
{
pointInPath.MoveNext();
}
}
public GameObject[] Concat(GameObject[] first, GameObject[] second, GameObject[] third)
{
GameObject[] Concated = new GameObject[first.Length+second.Length+third.Length];
for (int i = 0; i < first.Length; i++)
{
Concated[i] = first[i];
}
for (int i = 0; i < second.Length; i++)
{
Concated[first.Length + i] = second[i];
}
for (int i = 0; i < third.Length; i++)
{
Concated[first.Length + second.Length + i] = third[i];
}
return Concated;
}
public void getTarget(GameObject[] targets)
{
Vector3 minionPosition = this.transform.position;
foreach (GameObject go in targets)
{
Transform transform = go.GetComponent<Transform>();
Vector3 transformPosition = transform.position;
float distanceToTarget = Vector3.Distance(transformPosition, minionPosition);
if (distanceToTarget <= distanceVisionForAttack && distanceToTarget > radiusOfAttack)
{
moveToTarget(transformPosition);
}else if(distanceToTarget <= radiusOfAttack)
{
moveToTarget(minion.transform.position);
}
else if(type == MovementType.Moveing && distanceToTarget > distanceVisionForAttack)
{
enemy.SetDestination(pointInPath.Current.position);
}
}
var distanceSqure = (transform.position - pointInPath.Current.position).sqrMagnitude;
if (distanceSqure < maxDistance * maxDistance)
{
pointInPath.MoveNext();
}
}
public void moveToTarget(Vector3 target)
{
enemy.SetDestination(target);
}
}
result of starting scene
What is happening in redactor - YouTube
I leave for those who in the future will face the same stupidity as me, change
getTarget ( );
new variables added
GameObject currentTarget;
float dist = Mathf.Infinity;
and cycle
foreach(GameObject go in targets)
{
Vector3 targetPosition = go.transform.position;
float distanceToTarget = Vector3.Distance(targetPosition,
minionPosition);
if (distanceToTarget < dist)
{
dist = distanceToTarget;
currentTarget = go;
}
}
Special thanks to BugFinder
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.AI;
public class MinionMoveByLine : MonoBehaviour
{
public enum MovementType
{
Moveing,
Learp
}
//Переменные для перемещения по карте
public MovementType type = MovementType.Moveing;
public NavMeshLineToMove MyLine;
public float speed = 1;
public float maxDistance = .3f;
private NavMeshAgent enemy;
//Переменные для растояний и приоритета крипов
private GameObject[] minions;
private GameObject[] towers;
private GameObject[] players;
private GameObject[] All;
public GameObject minion;
private Vector3[] position;
private Vector3 targetPosition;
private float distanceVisionForAttack = 6f;
private float radiusOfAttack = 2f;
GameObject currentTarget;
float dist = Mathf.Infinity;
private IEnumerator<Transform> pointInPath;
// Start is called before the first frame update
void Start()
{
minions = GameObject.FindGameObjectsWithTag("minion");
towers = GameObject.FindGameObjectsWithTag("tower");
players = GameObject.FindGameObjectsWithTag("player");
All = Concat(players, towers, minions);
Debug.Log("minions "+ minions.Length);
Debug.Log("towers " + towers.Length);
Debug.Log("players " + players.Length);
//currentTarget = All[0];
minion = (GameObject)this.gameObject;
enemy = GetComponent<NavMeshAgent>();
if (MyLine == null)
{
Debug.Log("Line Not Set");
return;
}
pointInPath = MyLine.GetNextPathPoint();
pointInPath.MoveNext();
if (pointInPath.Current == null)
{
Debug.Log("Need point to move");
return;
}
transform.position = pointInPath.Current.position;
}
void LateUpdate()
{
Vector3 position = minion.transform.position;
if (pointInPath == null || pointInPath.Current == null)
{
return;
}
foreach(var obj in All)
{
Debug.Log(All.Length);
Debug.Log(obj);
}
getTarget(All);
var distanceSqure = (transform.position - pointInPath.Current.position).sqrMagnitude;
if (distanceSqure < maxDistance * maxDistance)
{
pointInPath.MoveNext();
}
}
public GameObject[] Concat(GameObject[] first, GameObject[] second, GameObject[] third)
{
GameObject[] Concated = new GameObject[first.Length+second.Length+third.Length];
for (int i = 0; i < first.Length; i++)
{
Concated[i] = first[i];
}
for (int i = 0; i < second.Length; i++)
{
Concated[first.Length + i] = second[i];
}
for (int i = 0; i < third.Length; i++)
{
Concated[first.Length + second.Length + i] = third[i];
}
return Concated;
}
public void getTarget(GameObject[] targets)
{
Vector3 minionPosition = this.transform.position;
foreach (GameObject go in targets)
{
Vector3 targetPosition = go.transform.position;
float distanceToTarget = Vector3.Distance(targetPosition, minionPosition);
if (distanceToTarget < dist)
{
dist = distanceToTarget;
currentTarget = go;
}
}
float distanceToCurrentTarget = Vector3.Distance(currentTarget.transform.position, minionPosition);
if (distanceToCurrentTarget <= distanceVisionForAttack && distanceToCurrentTarget > radiusOfAttack)
{
moveToTarget(currentTarget);
}
else if (distanceToCurrentTarget <= radiusOfAttack)
{
moveToTarget(minion);
}
else if (type == MovementType.Moveing && distanceToCurrentTarget > distanceVisionForAttack)
{
dist = Mathf.Infinity;
enemy.SetDestination(pointInPath.Current.position);
}
var distanceSqure = (transform.position - pointInPath.Current.position).sqrMagnitude;
if (distanceSqure < maxDistance * maxDistance)
{
pointInPath.MoveNext();
}
}
public void moveToTarget(GameObject target)
{
enemy.SetDestination(target.transform.position);
}
}
The goal is to count from 1 and from 0.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
public class MoveOnCurvedLines : MonoBehaviour
{
public LineRenderer lineRenderer;
public float speed;
public bool go = false;
public bool moveToFirstPositionOnStart = false;
public float rotSpeed;
public bool random = false;
public int currentCurvedLinePointIndex;
public Text lastWaypointText;
private Vector3[] positions;
private Vector3[] pos;
private int index = 0;
private bool goForward = true;
private List<GameObject> curvedLinePoints = new List<GameObject>();
private int numofposbetweenpoints;
private bool getPositions = false;
int randomIndex;
int curvedPointsIndex;
// Start is called before the first frame update
void Start()
{
curvedLinePoints = GameObject.FindGameObjectsWithTag("Curved Line Point").ToList();
if (curvedLinePoints != null && curvedLinePoints.Count > 0)
{
transform.rotation = curvedLinePoints[1].transform.rotation;
}
if (random)
GetNewRandomIndex();
lastWaypointText.text = curvedPointsIndex + 1.ToString();
}
Vector3[] GetLinePointsInWorldSpace()
{
positions = new Vector3[lineRenderer.positionCount];
//Get the positions which are shown in the inspector
lineRenderer.GetPositions(positions);
//the points returned are in world space
return positions;
}
// Update is called once per frame
void Update()
{
if (lineRenderer.positionCount > 0 && getPositions == false)
{
pos = GetLinePointsInWorldSpace();
numofposbetweenpoints = pos.Length / curvedLinePoints.Count;
if (moveToFirstPositionOnStart == true)
{
transform.position = pos[index];
}
getPositions = true;
}
if (go == true && lineRenderer.positionCount > 0)
{
Move();
Vector3 targetDirection = (curvedLinePoints[c].transform.position - transform.position).normalized;
curvedLinePoints[c].transform.localRotation = Quaternion.LookRotation(targetDirection);
transform.localRotation = Quaternion.RotateTowards(transform.localRotation, curvedLinePoints[c].transform.localRotation, Time.deltaTime * rotSpeed);
}
var dist = Vector3.Distance(transform.position, curvedLinePoints[curvedPointsIndex].transform.position);
if (dist < 0.1f)
{
if (curvedPointsIndex < curvedLinePoints.Count - 1)
{
curvedPointsIndex++;
lastWaypointText.text = curvedPointsIndex.ToString();
}
currentCurvedLinePointIndex = curvedPointsIndex;
}
}
curvedPointsIndex in the Start() is 0 so if there are 30 curvedLinePoints it will start counting from 0 to 29 but i want it to display in the lastWaypointText.text from 1 to 30.
I tried in the Start() instead :
lastWaypointText.text = curvedPointsIndex.ToString();
To make
lastWaypointText.text = curvedPointsIndex + 1.ToString();
but that's making the first number in the text 01 and then counting to 29.
When you do lastWaypointText.text = curvedPointsIndex + 1.ToString(); you are just applying ToString to the last part of the formula which makes it add "1" after your lastWaypointIndex. You need to wrap it in a parenthesis instead like this:
lastWaypointText.text = (curvedPointsIndex + 1).ToString();
I want to see the "Hello World" text. But there is nothing.
Either if using 3D Object > 3D Text
Or UI > Text
Or UI > Text - TextMeshPro
No matter what text component I'm using since there is no mesh renderer attached to it I'm getting exception so I'm adding to the Text component first a mesh renderer.
But then I'm getting exception say there is no TextMesh component attached to the new created texts so I'm changing this line :
var textmesh = newText.GetComponent<TextMesh>();
To
var textmesh = newText.GetComponent<Text>();
But still it's not working getting exception say textmesh is null.
So I changed the text component to UI > Text
Added to the text a MeshRenderer and now not getting exceptions/errors :
And
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class AddTextToObject : MonoBehaviour
{
public UnityEngine.GameObject[] objectsToNumber;
public UnityEngine.GameObject text;
public float yPadding;
public bool rotateNumbers = false;
public float rotationSpeed = 10f;
public bool textChild = false;
public bool textAbove = false;
public bool textInFront = false;
public bool textOnFaces = false;
private List<GameObject> newTexts = new List<GameObject>();
private MeshRenderer[] renderer;
private Vector3 newPos;
private void Start()
{
renderer = new MeshRenderer[objectsToNumber.Length];
for (int i = 0; i < objectsToNumber.Length; i++)
{
GameObject newText = Instantiate(text);
renderer[i] = newText.GetComponent<MeshRenderer>();
if (textAbove == true)
{
newPos = new Vector3
(
objectsToNumber[i].transform.position.x,
((objectsToNumber[i].transform.position.y + renderer[i].bounds.extents.y) + yPadding),
objectsToNumber[i].transform.position.z
);
}
if (textInFront == true)
{
newPos = new Vector3
(
((objectsToNumber[i].transform.position.x + renderer[i].bounds.extents.x) + yPadding),
objectsToNumber[i].transform.position.y,
objectsToNumber[i].transform.position.z
);
}
newText.transform.position = newPos;
newText.transform.parent = transform;
newText.name = i.ToString();
newText.tag = "Number";
newTexts.Add(newText);
var textmesh = newText.GetComponent<TextMesh>();
textmesh.transform.localRotation = Quaternion.Euler(0, -90, 0);
if (textAbove == true)
{
textmesh.text = i.ToString();
}
if (textInFront == true)
{
textmesh.text = "Hello World";
}
}
}
private void Update()
{
if (rotateNumbers == true)
{
for (int i = 0; i < newTexts.Count; i++)
{
newTexts[i].transform.Rotate(Vector3.up, 10 * rotationSpeed * Time.deltaTime);
}
}
}
}
Update :
Trying using TextMeshPro :
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using TMPro;
public class AddTextToObject : MonoBehaviour
{
public UnityEngine.GameObject[] objectsToNumber;
public UnityEngine.GameObject text;
public float yPadding;
public bool rotateNumbers = false;
public float rotationSpeed = 10f;
public bool textChild = false;
public bool textAbove = false;
public bool textInFront = false;
public bool textOnFaces = false;
private List<GameObject> newTexts = new List<GameObject>();
private MeshRenderer[] renderer;
private Vector3 newPos;
private void Start()
{
renderer = new MeshRenderer[objectsToNumber.Length];
for (int i = 0; i < objectsToNumber.Length; i++)
{
GameObject newText = Instantiate(text);
renderer[i] = objectsToNumber[i].GetComponent<MeshRenderer>();
if (textAbove == true)
{
newPos = new Vector3
(
objectsToNumber[i].transform.position.x,
((objectsToNumber[i].transform.position.y + renderer[i].bounds.extents.y) + yPadding),
objectsToNumber[i].transform.position.z
);
}
if (textInFront == true)
{
newPos = new Vector3
(
((objectsToNumber[i].transform.position.x + renderer[i].bounds.extents.x) + yPadding),
objectsToNumber[i].transform.position.y,
objectsToNumber[i].transform.position.z
);
}
newText.transform.position = newPos;
newText.transform.SetParent(transform, false);
newText.name = i.ToString();
newText.tag = "Number";
newTexts.Add(newText);
var textmesh = newText.GetComponent<TextMeshProUGUI>();
textmesh.transform.localRotation = Quaternion.Euler(0, -90, 0);
if (textAbove == true)
{
textmesh.text = i.ToString();
}
if (textInFront == true)
{
textmesh.text = "Hello World";
}
}
}
private void Update()
{
if (rotateNumbers == true)
{
for (int i = 0; i < newTexts.Count; i++)
{
newTexts[i].transform.Rotate(Vector3.up, 10 * rotationSpeed * Time.deltaTime);
}
}
}
}
But the result is that the text is not close to the gameobjects.
The text "Hello World" should be like stick/attached to each gameobject.
And
And what I want to do is to stick/attach the text "Hello World" to the face front side of each of the 3 cubes New Game, Options, Quit :
Because it is not a child of a Canvas
The Canvas is the area that all UI
elements should be inside
any UI elements that are not under a Canvas in the hierarchy are not rendered.
There are two different kinds of text components in Unity. The legacy TextMesh and TextMeshPro which work standalone without a Canvas and are used and positioned like 3D objects.
And there are the UGUI or UI components Text and TextMeshProUGUI which are used in combination with a Canvas.
So the "correct" replacement for TextMeshPro would not be a Text but rather a TextMesh. (I wouldn't go that direction though .. if you already have TMP stick with it .. it is better than the legacy UI Text and TextMesh.
You should also not add a MeshRenderer manually to the object! UI elements like Text and TextMeshProUGUI bring their own renderer with them. Maybe you should go through the Unity UI Tutorial once.
Also checkout the TextMeshPro Guide!
The problem is in this script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class PatrolData
{
public Transform target = null;
public float minDistance = 5f;
public float lingerDuration = 5f;
public float desiredHeight = 10f;
public float flightSmoothTime = 10f;
public float maxFlightspeed = 10f;
public float flightAcceleration = 1f;
public float levelingSmoothTime = 0.5f;
public float maxLevelingSpeed = 10000f;
public float levelingAcceleration = 2f;
}
public class PatrolOverTerrain : MonoBehaviour
{
public FlyToOverTerrain flyOverTerrain;
public LookAtCamera lookAtCamera;
public enum PatrolMode { Clamp, Wrap, PingPong };
public PatrolData[] patrolPoints;
public PatrolMode mode = PatrolMode.Wrap;
private int iterator = 0;
private int index = 0;
private float lingerDuration = 0f;
private int oldLength = 0;
public List<GameObject> TeleportationBooths = new List<GameObject>();
public Vector3 distanceFromTarget;
private void Start()
{
GameObject[] tempObj = GameObject.FindGameObjectsWithTag("Teleportation Booth");
for (int i = 0; i < tempObj.Length; i++)
{
//Add to list only if it does not exist
if (!TeleportationBooths.Contains(tempObj[i]))
{
TeleportationBooths.Add(tempObj[i]);
}
}
//Get the current Size
if (tempObj != null)
{
oldLength = tempObj.Length;
}
GeneratePatrolPoints();
}
private void OnEnable()
{
if (patrolPoints.Length > 0)
{
lingerDuration = patrolPoints[index].lingerDuration;
}
}
private void Update()
{
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
int length = patrolPoints.Length;
if (!flyOverTerrain) return;
if (patrolPoints.Length < 1) return;
if (index < 0) return;
// Getting exception out of index on line 89.
// Need to make a list also for the Cubes(buildings).
var patrol = patrolPoints[index];
if (lingerDuration <= 0)
{
iterator++;
switch (mode)
{
case PatrolMode.Clamp:
index = (iterator >= length) ? -1 : iterator;
break;
case PatrolMode.Wrap:
iterator = Modulus(iterator, length);
index = iterator;
break;
case PatrolMode.PingPong:
index = PingPong(iterator, length);
break;
}
if (index < 0) return;
patrol = patrolPoints[index];
flyOverTerrain.target = patrol.target;
flyOverTerrain.desiredHeight = patrol.desiredHeight;
flyOverTerrain.flightSmoothTime = patrol.flightSmoothTime;
flyOverTerrain.maxFlightspeed = patrol.maxFlightspeed;
flyOverTerrain.flightAcceleration = patrol.flightAcceleration;
flyOverTerrain.levelingSmoothTime = patrol.levelingSmoothTime;
flyOverTerrain.maxLevelingSpeed = patrol.maxLevelingSpeed;
flyOverTerrain.levelingAcceleration = patrol.levelingAcceleration;
lookAtCamera.target = patrol.target;
lookAtCamera.RotationSpeed = 3;
lingerDuration = patrolPoints[index].lingerDuration;
}
Vector3 targetOffset = Vector3.zero;
if ((bool)patrol.target)
{
targetOffset = transform.position - patrol.target.position;
}
float sqrDistance = patrol.minDistance * patrol.minDistance;
if (targetOffset.sqrMagnitude <= sqrDistance)
{
flyOverTerrain.target = null;
lookAtCamera.target = null;
lingerDuration -= Time.deltaTime;
}
else
{
flyOverTerrain.target = patrol.target;
lookAtCamera.target = patrol.target;
}
distanceFromTarget = transform.position - patrol.target.position;
}
private int PingPong(int baseNumber, int limit)
{
if (limit < 2) return 0;
return limit - Mathf.Abs(limit - Modulus(baseNumber, limit + (limit - 2)) - 1) - 1;
}
private int Modulus(int baseNumber, int modulus)
{
return (modulus == 0) ? baseNumber : baseNumber - modulus * (int)Mathf.Floor(baseNumber / (float)modulus);
}
public void GeneratePatrolPoints()
{
patrolPoints = new PatrolData[TeleportationBooths.Count];
for (int i = 0; i < patrolPoints.Length; i++)
{
patrolPoints[i] = new PatrolData();
patrolPoints[i].target = TeleportationBooths[i].transform;
patrolPoints[i].minDistance = 30f;
patrolPoints[i].lingerDuration = 3f;
patrolPoints[i].desiredHeight = 20f;
patrolPoints[i].flightSmoothTime = 10f;
patrolPoints[i].maxFlightspeed = 10f;
patrolPoints[i].flightAcceleration = 3f;
patrolPoints[i].levelingSmoothTime = 0.5f;
patrolPoints[i].maxLevelingSpeed = 10000f;
patrolPoints[i].levelingAcceleration = 2f;
}
}
}
In this part inside the Update i'm comparing the old length of a list with the current length:
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
So in case i create a new objects without destroying the old ones first it will be fine the length is not the same and it will call GeneratePatrolPoints() and will update the targets with the new targets just added:
patrolPoints[i].target = TeleportationBooths[i].transform;
The problem is when i check the ui toggle and first destroy the objects and then create them again the length is the same as before so it will not call GeneratePatrolPoints() and will not update the targets.
So i'm getting missing object exception.
I'm updating the list but i also need to update the targets again.
In this script i decide if the create new objects and to add them to the list so the length will not be the same and everything is right or to destroy first the current objects and then create new ones but then the length will be the same:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GenerateObjectsButton : MonoBehaviour
{
[SerializeField]
private InstantiateObjects[] instantiateobjects;
private bool toggleOnOf;
public Toggle toggle;
private void Start()
{
toggle.onValueChanged.AddListener((value) =>
{
MyListener(value);
});
}
public void MyListener(bool value)
{
if (value)
{
//do the stuff when the toggle is on
toggleOnOf = true;
}
else
{
//do the stuff when the toggle is off
toggleOnOf = false;
}
}
public void OnButton()
{
for (int i = 0; i < instantiateobjects.Length; i++)
{
if (toggleOnOf == false)
{
instantiateobjects[i].generateObjectOnTerrain();
}
else
{
instantiateobjects[i].DestroyObjects();
instantiateobjects[i].generateObjectOnTerrain();
}
}
}
}
The problem is with the first script with comparing the length with the list count.
The solution is to add a new bool variable in the GenerateObjectsButton script:
public bool destroyed = false;
And set it to true after destroying and creating new objects again:
public void OnButton()
{
for (int i = 0; i < instantiateobjects.Length; i++)
{
if (toggleOnOf == false)
{
instantiateobjects[i].generateObjectOnTerrain();
}
else
{
instantiateobjects[i].DestroyObjects();
instantiateobjects[i].generateObjectOnTerrain();
destroyed = true;
}
}
}
Now destroyed is true.
Back to the PatrolOverTerrain script.
Now i'm not only checking if the length is not the same but also if destroyed is true:
//Check if oldLength has changed
if (oldLength != TeleportationBooths.Count)
{
//Update oldLength
oldLength = TeleportationBooths.Count;
//Call your the function
GeneratePatrolPoints();
}
GameObject go = GameObject.Find("Button");
var destroyed = go.GetComponent<GenerateObjectsButton>().destroyed;
if (destroyed)
{
GeneratePatrolPoints();
}
Now i know when i only created new objects and added them by comparing length or when first destroyed the objects and then created new so the length didn't change but the list it self did.
Anyway this is a working solution.