I am trying to make a Scrabble word game using a fixed camera, but I have a simple issue.
I add some boxes as game objects and the number of these boxes is the length of the word so if the word is "Fish" we will add 4 boxes dynamically. I did that successfully, but I can't center those boxes in the screen. I tried to add those game objects as children under another game object, then center the parent, but with no effect.
This is my code:
void Start () {
for (int i=0; i<word.Length; i++) {
GameObject LetterSpaceObj = Instantiate(Resources.Load ("LetterSpace", typeof(GameObject))) as GameObject;
LetterSpaceObj.transform.parent = gameObject.transform;
LetterSpaceObj.transform.localPosition = new Vector2(i*1.5f,0.0f);
LetterSpaceObj.name = "LetterSpace-"+count.ToString();
count++;
}
gameObject.transform.position = new Vector2 (0.0f, 0.0f);
}
This image shows you the idea:
I believe your code is working, but the problem is that your first letter is located at your parent object, and then every letter from then on is added to the right. That means that when you center the parent object what you are doing is putting the first letter in the center of the screen.
If you run the game and use the scene view to look at where the parent object is this can confirm this. What you can do instead is that rather than placing the parent at the center of the screen, offset it by an amount equal to the length of the word.
gameObject.transform.position = new Vector2 (-(word.Length / 2.0f) * 1.5f, 0.0f);
You might also want to consider changing some of those constants, such as the 1.5f into variables with names like LetterSize or basing it off the actual prefab so that way any future changes will work automatically.
This is the last solution after some edits to fix this issue.
GameObject LetterSpaceObjRow;
int count = 1;
string word = "Father";
float ObjectXPos;
float LocalScaleX;
void Start () {
for (int i=0; i<word.Length; i++) {
GameObject LetterSpaceObj = Instantiate(Resources.Load ("LetterSpace", typeof(GameObject))) as GameObject;
LocalScaleX = LetterSpaceObj.transform.localScale.x;
ObjectXPos = i*(LocalScaleX+(LocalScaleX/2));
LetterSpaceObj.transform.parent = gameObject.transform;
LetterSpaceObj.transform.localPosition = new Vector2(ObjectXPos,0.0f);
LetterSpaceObj.name = "LetterSpace-"+count.ToString();
count++;
}
gameObject.transform.position = new Vector2 (-(ObjectXPos/2.0f) , 0.0f);
}
Related
I've searched around and can't seem to find a write up on the calculations I might need for placing an object onto another one without them placing halfway inside of eachother.
private void MovePlaceableObject()
{
Ray ray = new Ray(Camera.main.transform.position, Camera.main.transform.forward);
Debug.DrawRay(ray.origin, ray.direction * 20f);
RaycastHit hit;
if(Physics.Raycast(ray, out hit, 15f))
{
Vector3 newPosition = hit.point;
currentPlaceableObject.transform.position = newPosition; //move object to where we have the mouse
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal); //rotation equal to the current rotation of our hitinfo, then up
}
}
private void HandeNewObjectHotkey()
{
if (Input.GetKeyDown(newObjectHotkey))
{
if(currentPlaceableObject == null)
{
currentPlaceableObject = Instantiate(placeableObjectPrefab);
//currentPlaceableObject.GetComponent<BoxCollider>().enabled = false;
}
else
{
Destroy(currentPlaceableObject); //pressing the button again will destroy current object
}
}
}
I've tried storing the object I'm looking at's size to floats for x,y,z and a vector3 for it's position, and tried fiddling around with adding those to the newPosition with the hit.point to no avail.
I've wracked my brains for about a day now, i'm terrible at math, however I know that you must need to get the current object your looking ats position or size, then factor that into your placement right?
Get the size of the object that you are looking at by accessing its collider component. You can use the bounds property of the collider to get its size.
Bounds objectBounds = hit.collider.bounds;
Calculate the center point of the object by adding half of its size to its position.
Vector3 objectCenter = hit.collider.transform.position + objectBounds.extents;
Calculate the position of the new object by adding the size of the new object to the center point of the object that you are looking at. This will place the new object on top of the other object.
Bounds newObjectBounds = currentPlaceableObject.GetComponent<Collider>().bounds;
Vector3 newObjectPosition = objectCenter + new Vector3(0, newObjectBounds.extents.y, 0);
Set the position of the new object to the calculated position.
currentPlaceableObject.transform.position = newObjectPosition;
You can also set the rotation of the new object to match the normal of the surface that it is being placed on, as you are already doing in your code.
currentPlaceableObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, hit.normal);
I am attempting to instantiate differently shaped prefabs next to eachother. I have a folder full of differently sized objects that allow for me to string them together randomly to create a 2D endless runner. My issue is that all the answers online about placing objects beside eachother don't work when different sized objects are used. Here is the code I am using to instantiate the sections. It works when it only randomly selects similar sized objects. When the selected prefab is a different length it leaves either a gap between, or overlaps, the previous object.
for(int i = 0; i < activeSectionsAtOnce; i++)
{
int index = Random.Range(0, sectionPrefabs.Length);
GameObject currentOb = sectionPrefabs[index];
Vector2 position = new Vector2();
if(activeSections.Count == 0)
{
//set a (0, 0) position for first object
position = Vector2.zero;
}
else
{
//get most recently placed object from list
GameObject lastOb = activeSections[activeSections.Count - 1];
//my attempt at getting bounds for the last object and for the next prefab that will be used
Bounds lasObbounds = new Bounds(lastOb.transform.position, Vector2.zero);
Bounds currentBounds = new Bounds(currentOb.transform.position, Vector2.zero);
//Include child objects(all have sprite renderers)
foreach (Renderer r in lastOb.GetComponentsInChildren<Renderer>())
{
lasObbounds.Encapsulate(r.bounds);
}
foreach (Renderer rend in currentOb.GetComponentsInChildren<Renderer>())
{
currentBounds.Encapsulate(rend.bounds);
}
//position object will be instantiated at
position.x = lastOb.transform.position.x + (lasObbounds.size.x / 2) + (currentBounds.size.x/2);
}
//instantiate at selected position
activeSections.Add(
Instantiate(currentOb, position, Quaternion.identity)
);
}
This is in the start method. I'm not sure if the problem is how I'm creating the bounds, or how im mathematicaly creating the x coordinate. This is the expected result that happens when I use same sized prefabs. This is what happens with different prefabs
The shorter protrusion from the first object should be cleanly between the other two without a gap.
Here's an image of one prefab
Thanks for any advice
Using ARCore on Unity, I'm trying to place one gameObject between two gameObjects. Unfortunately it doesn't display, it seems it is a problem with Anchor.
*Using Vuforia, i didn't had problem to position game objects.
What i try to achieve is:
Place two objects (A and B) on the ground when i touch the surface. It Works
Place a gameObject (C) between the two objects (A and B).Not displaying
// Place target objects A and B on surface touch
GameObject prefab;
GameObject prefab2;
prefab = AndyPointPrefab;
prefab2 = AndyPlanePrefab;
hitpoint= hitpoint + 1;
// Place object A
if (hitpoint==1){
target1 = Instantiate(prefab, hit.Pose.position, hit.Pose.rotation);
target1.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
target1.transform.parent = anchor.transform;
mIsFirsttargetVisible=true;
}
else if (hitpoint==2){ // Place object B
target2 = Instantiate(prefab2, hit.Pose.position, hit.Pose.rotation);
target2.transform.Rotate(0, k_ModelRotation, 0, Space.Self);
var anchor = hit.Trackable.CreateAnchor(hit.Pose);
target2.transform.parent = anchor.transform;
mIsSecondTargetVisible=true;
hitpoint=-1;
}
//Update function : todisplay point C in-between.
Update() {
// Place object C
if(mIsFirsttargetVisible && mIsSecondTargetVisible){
GameObject objectMiddle = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Vector3 middlePosition = (target1.transform.position+target2.transform.position)/2;
objectMiddle.transform.position = middlePosition;
objectMiddle.transform.localScale = new Vector3(200.0f, 10.0f, 200.0f);
}
}
EDIT
I successfully arrived to place the gameobject in between.
i added this last line in my code: target1.transform.parent = objectMiddle.transform;
if(mIsFirsttargetVisible && mIsSecondTargetVisible){
GameObject objectMiddle = GameObject.CreatePrimitive(PrimitiveType.Sphere);
Vector3 middlePosition = (target1.transform.position+target2.transform.position)/2;
objectMiddle.transform.position = middlePosition;
objectMiddle.transform.localScale = new Vector3(200.0f, 10.0f, 200.0f);
target1.transform.parent = objectMiddle.transform;
}
I have a gameobject in my scene. I want to show the dimension of the gameobject as shown here: So, I created a UI prefab. Now when I am trying to scale the UI (Which us a world UI canvas) prefab. It's not scaling properly! How can I do it? I am trying this now which is indeed not working. Help Needed!
public void setDimension()
{
GameObject g = Instantiate(dimUiPrefab);
BoxCollider b = activeFurniture.GetComponent<BoxCollider>();
Vector2 cameraViewPort =
Camera.main.WorldToViewportPoint(activeFurniture.transform.lossyScale);
g.transform.position = new Vector3(b.transform.position.x/2,b.transform.position.y +2f, b.transform.position.z);
g.GetComponent<RectTransform>().transform.localScale = cameraViewPort;
}
If you are using UGUI,
GameObject g = Instantiate(dimUiPrefab);
RectTransform rectTransform = g.GetComponent<RectTransform>();
// Set size
rectTransform.sizeDelta = new Vector2(width, height);
// Set position
rectTransform.position = new Vector3(posX, posY, posZ);
I am newbie in Unity platform. I have 2D game that contains 10 boxes vertically following each other in chain. When a box goes off screen, I change its position to above of the box at the top. So the chain turns infinitely, like repeating Parallax Scrolling Background.
But I check if a box goes off screen by comparing its position with a specified float value. I am sharing my code below.
void Update () {
offSet = currentSquareLine.transform.position;
currentSquareLine.transform.position = new Vector2 (0f, -2f) + offSet;
Vector2 vectorOne = currentSquareLine.transform.position;
Vector2 vectorTwo = new Vector2 (0f, -54f);
if(vectorOne.y < vectorTwo.y) {
string name = currentSquareLine.name;
int squareLineNumber = int.Parse(name.Substring (11)) ;
if(squareLineNumber < 10) {
squareLineNumber++;
} else {
squareLineNumber = 1;
}
GameObject squareLineAbove = GameObject.Find ("Square_Line" + squareLineNumber);
offSet = (Vector2) squareLineAbove.transform.position + new Vector2(0f, 1.1f);
currentSquareLine.transform.position = offSet;
}
}
As you can see, when I compare vectorOne.y and vectorTwo.y, things get ugly. Some boxes lengthen and some boxes shorten the distance between each other even I give the exact vector values in the code above.
I've searched for a solution for a week, and tried lots of codes like Mathf.Approximate, Mathf.Round, but none of them managed to compare float values properly. If unity never compares float values in the way I expect, I think I need to change my way.
I am waiting for your godlike advices, thanks!
EDIT
Here is my screen. I have 10 box lines vertically goes downwards.
When Square_Line10 goes off screen. I update its position to above of Square_Line1, but the distance between them increases unexpectedly.
Okay, I found a solution that works like a charm.
I need to use an array and check them in two for loops. First one moves the boxes and second one check if a box went off screen like below
public GameObject[] box;
float boundary = -5.5f;
float boxDistance = 1.1f;
float speed = -0.1f;
// Update is called once per frame
void Update () {
for (int i = 0; i < box.Length; i++) {
box[i].transform.position = box[i].transform.position + new Vector3(0, speed, 0);
}
for (int i = 0; i < box.Length; i++)
{
if(box[i].transform.position.y < boundary)
{
int topIndex = (i+1) % box.Length;
box[i].transform.position = new Vector3(box[i].transform.position.x, box[topIndex].transform.position.y + boxDistance, box[i].transform.position.z);
break;
}
}
}
I attached it to MainCamera.
Try this solution:
bool IsApproximately(float a, float b, float tolerance = 0.01f) {
return Mathf.Abs(a - b) < tolerance;
}
The reason being that the tolerances in the internal compare aren't good to use. Change the tolerance value in a function call to be lower if you need more precision.