Fill screen with 2D cubes dynamically accordingly Screen.width - unity3d

I was trying to use a for loop to instantiate cube as much fit on the screen. So i checked how wide the screen is and is checked how wide my cube was. Divided it by each other and it didnt work.
So what i think i did wrong is that Screen.width is in pixels and renderer.bounds.size.x is in world size.
How do i fix this? I didnt figure it out on the internet..
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class move : MonoBehaviour
{
public GameObject cubePrefab;
public static bool spawn;
float times;
int screenWidth;
float objectSize;
// Use this for initialization
void Start()
{
spawn = true;
screenWidth = Screen.width;
objectSize = GameObject.Find("vork").GetComponent<Renderer>().bounds.size.x;
times = screenWidth / objectSize;
}
// Update is called once per frame
void Update()
{
if(spawn == true)
{
for(int i=0; i < times;i++) {
Vector3 pos = new Vector3(i * 2, i *2, 0);
Instantiate(cubePrefab, pos, transform.rotation);
}
spawn = false;
}
}
}
2D game

You need to calculate pixel width. In order to calculate screen position from world position use Camera.WorldToScreenPoint. This is how a function could look like:
public static float GetPixelWidth(GameObject gO)
{
Bounds bounds = gO.GetComponent<Renderer>().bounds;
Vector3 boundsPos1 = Camera.main.WorldToScreenPoint(new Vector3(gO.transform.position.x + bounds.extents.x, gO.transform.position.y, gO.transform.position.y));
Vector3 boundsPos2 = Camera.main.WorldToScreenPoint(new Vector3(gO.transform.position.x - bounds.extents.x, gO.transform.position.y, gO.transform.position.y));
return Vector3.Distance(boundsPos1, boundsPos2);
}
And this is how to use the function in your code:
// Use this for initialization
void Start()
{
spawn = true;
screenWidth = Camera.main.pixelWidth;
objectSize = GetPixelWidth(GameObject.Find("vork"));
times = screenWidth / objectSize;
}
I have tested and it works with orthographic camera

Related

How do I make this piece of c# go vertical instead of horizontal?

I have been trying to make an infinitely repeating background. Found this piece below but it goes horizontally instead of vertically. I tried rotating my sprites but it didn't work, also changed the x values with y and the loop stopped happening.
I'm stuck trying to figure out a solution.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class RepeatBg : MonoBehaviour
{
private BoxCollider2D boxCollider;
private Rigidbody2D rb;
private float width;
private float speed = -3f;
// Start is called before the first frame update
void Start()
{
boxCollider = GetComponent<BoxCollider2D>();
rb = GetComponent<Rigidbody2D>();
width = boxCollider.size.x;
rb.velocity = new Vector2(speed,0);
}
// Update is called once per frame
void Update()
{
if (transform.position.x<-width)
{
Reposition();
}
}
private void Reposition()
{
Vector2 vector = new Vector2(width * 2f, 0);
transform.position = (Vector2)transform.position + vector;
}
}
You need to change all "vertical stuff" to horizontal.
Add a member variable
private float height;
In method Start set
height = boxCollider.size.y;
rb.velocity = new Vector2(0, speed);
In method Update change the condition to
if (transform.position.y < -height)
In method Reposition set
Vector2 vector = new Vector2(0, height * 2f);

Draging camera to a limit (x, y axis) - UNITY

i did a tutorial about doing a camera drag on a 2D or 3D worldmap.
The code is working. Looks like the following:
void Update_CameraDrag ()
{
if( Input.GetMouseButtonUp(0) )
{
Debug.Log("Cancelling camera drag.");
CancelUpdateFunc();
return;
}
// Right now, all we need are camera controls
Vector3 hitPos = MouseToGroundPlane(Input.mousePosition);
//float maxWidth = 10;
//if (hitPos.x > maxWidth)
//{
// hitPos.x = maxWidth;
//}
Vector3 diff = lastMouseGroundPlanePosition - hitPos;
Debug.Log(diff.x+ Space.World);
Camera.main.transform.Translate (diff, Space.World);
lastMouseGroundPlanePosition = hitPos = MouseToGroundPlane(Input.mousePosition);
}
Now my problem is, that you can drag unlimiited into any directions.
I would rather like to difine something like borders on the x and y axis.
Basically maximum values for the camera. If the camera would surpass these values, their position value would be set to the given maximum value.
Unfortunately, i am not sure how it works, especially, since the tutorial set everything into relation to Space.World - and i am not even sure what that is. I mean i understand that "diff" is the change between the current position and the new positon in relation to Space.World and then the camera gets moved accordingly. I would just like to define a max value which the camera can not surpass. Any ideas how to do that. I am unfortunately still learning - so kinda hard for me and i was hoping for help.
If you were to record the X and Y position of the camera as it goes in a variable and use the MathF function. I.e
if you have a map that is 100(x)x150(y)units you could use
xPositionOfCamera = Mathf.Clamp(xPositionOfCamera, -50, 50);
yPositionOfCamera = Mathf.Clamp(YPositionOfCamera, -75, 75);
I'm not 100% sure if that's what you want it to do, but it's how I would limit it.
I write a simple and reliable script for my game to handle camera drag and swipe for any camera aspect ratio. Everyone can use this code easily :) Just adjust the xBoundWorld and yBoundWorld values
using UnityEngine;
public class CameraDragController : MonoBehaviour
{
[SerializeField] private Vector2 xBoundWorld;
[SerializeField] private Vector2 yBoundWorld;
[SerializeField] public bool HorizentalDrag = true;
[SerializeField] public bool VerticalDrag = true;
[SerializeField] public float speedFactor = 10;
private float leftLimit;
private float rightLimit;
private float topLimit;
private float downLimit;
public bool allowDrag = true;
private void Start()
{
CalculateLimitsBasedOnAspectRatio();
}
public void UpdateBounds(Vector2 xBoundNew, Vector2 yBoundNew)
{
xBoundWorld = xBoundNew;
yBoundWorld = yBoundNew;
CalculateLimitsBasedOnAspectRatio();
}
private void CalculateLimitsBasedOnAspectRatio()
{
leftLimit = xBoundWorld.x - Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0)).x;
rightLimit = xBoundWorld.y - Camera.main.ViewportToWorldPoint(new Vector3(1, 0, 0)).x;
downLimit = yBoundWorld.x - Camera.main.ViewportToWorldPoint(new Vector3(0, 0, 0)).y;
topLimit = yBoundWorld.y - Camera.main.ViewportToWorldPoint(new Vector3(0, 1, 0)).y;
}
Vector3 lastPosView; // we use viewport because we don't want devices pixel density affect our swipe speed
private void LateUpdate()
{
if (allowDrag)
{
if (Input.GetMouseButtonDown(0))
{
lastPosView = Camera.main.ScreenToViewportPoint(Input.mousePosition);
}
else if (Input.GetMouseButton(0))
{
var newPosView = Camera.main.ScreenToViewportPoint(Input.mousePosition);
var cameraMovment = (lastPosView - newPosView) * speedFactor;
lastPosView = newPosView;
cameraMovment = Limit2Bound(cameraMovment);
if (HorizentalDrag)
Camera.main.transform.Translate(new Vector3(cameraMovment.x, 0, 0));
if (VerticalDrag)
Camera.main.transform.Translate(new Vector3(0, cameraMovment.y, 0));
}
}
}
private Vector3 Limit2Bound(Vector3 distanceView)
{
if (distanceView.x < 0) // Check left limit
{
if (Camera.main.transform.position.x + distanceView.x < leftLimit)
{
distanceView.x = leftLimit - Camera.main.transform.position.x;
}
}
else // Check right limit
{
if (Camera.main.transform.position.x + distanceView.x > rightLimit)
{
distanceView.x = rightLimit - Camera.main.transform.position.x;
}
}
if (distanceView.y < 0) // Check down limit
{
if (Camera.main.transform.position.y + distanceView.y < downLimit)
{
distanceView.y = downLimit - Camera.main.transform.position.y;
}
}
else // Check top limit
{
if (Camera.main.transform.position.y + distanceView.y > topLimit)
{
distanceView.y = topLimit - Camera.main.transform.position.y;
}
}
return distanceView;
}
}

Camera not displaying anything when clamped used to set restrictions in Unity

Good day
I am trying to restrict my camera movement using a function that I am using to restrict other elements in a 2D game. When I call this function using my camera, it does something strange.
For some reason it does not display anything as soon as I called the function. I have tested the camera's position using Debug.log, and it seems to be in exactly the same place. The constraints also seem to work, but that is useless if nothing displays.
I am using a Mathf.Clamp function to try and constrain the map. I know that there are many tutorials showing how to constrain map movement, and honestly my approach seems similar.
I want to know why this function is failing. I am trying to keep things generic, and am already using this function to restrict the movement of other game elements.
My code looks like this:
int cameraSpeed = 10;
GameObject camera;
int maxX = 20;
int minX = -20;
int maxY = 20;
int minY = -20;
// Use this for initialization
public void constrain(GameObject obj)
{
Vector2 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
obj.transform.position = pos;
}
void Start () {
camera = GameObject.Find("Main Camera");
}
// Update is called once per frame
void Update()
{
if (Input.GetKey(KeyCode.RightArrow))
{
camera.transform.Translate(new Vector2(cameraSpeed * Time.deltaTime, 0));
}
if (Input.GetKey(KeyCode.LeftArrow))
{
camera.transform.Translate(new Vector2(-cameraSpeed * Time.deltaTime, 0));
}
if (Input.GetKey(KeyCode.DownArrow))
{
camera.transform.Translate(new Vector2(0, -cameraSpeed * Time.deltaTime));
}
if (Input.GetKey(KeyCode.UpArrow))
{
camera.transform.Translate(new Vector2(0, cameraSpeed * Time.deltaTime));
}
Debug.Log(camera.transform.position.x);
Debug.Log(camera.transform.position.y);
constrain(camera);
}
Screenshot of game without constraints:
Screenshot of game with constraints:
I am new to Unity and am trying to understand it thoroughly. Any advice would be greatly appropriated.
The Z-position of your camera is being set to 0. All of your other objects have the same Z-position, so the camera won't render them.
Change constrain() to:
public float zPos = -10
public void constrain(GameObject obj)
{
Vector3 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
pos.z = zPos
obj.transform.position = pos;
}
and that should fix it.
EDIT: The reason that this is happening is because you were using a Vector2 for your camera position. In Unity, a Vector2 is a Vector3 with a z-value of 0.
I have managed to find the bug with #DerwB's assistance. I now see that the camera needs to be on a lower z index than the objects it is displaying. DerwB's answer is close to a solution, but it does not allow the function to be reused to constrain other objects.
I have thus modified the function as below:
public void constrain(GameObject obj, bool isCamera = false)
{
Vector3 pos = obj.transform.position;
pos.x = Mathf.Clamp(pos.x, -maxX, maxX);
pos.y = Mathf.Clamp(pos.y, -maxY, maxY);
if(isCamera)
pos.z = 0;
else
pos.z = 1;
obj.transform.position = pos;
}
You then call the function as follows for the camera:
GameObject camera = GameObject.Find("Main Camera");
constrain(camera.gameObject,true); //if you are constraining the camera object
And like this if you are referencing other game objects:
GameObject player= GameObject.Find("Player");
constrain(player.gameObject,true); //skip the optional parameter if not referencing the camera

How to place a Unity monobehavior object in 3D [duplicate]

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Teleport : MonoBehaviour {
public Vector3 terrainArea;
public float spinSpeed = 2.0f;
public int cloneTeleportations;
public GameObject prefab;
private bool rotate = false;
private bool exited = false;
private Transform[] teleportations;
private Random rnd = new Random();
private void Start()
{
GameObject go = GameObject.Find("Terrain");
Terrain terrain = go.GetComponent(Terrain);
terrainArea = terrain.terrainData.size;
for (int i = 0; i < cloneTeleportations; i++)
{
GameObject Teleportaion = Instantiate(prefab, new Vector3(Random.Range(i * 10.0F, i * 50.0F), 0, Random.Range(i * 10.0F, i * 50.0F)), Quaternion.identity);
Teleportaion.transform.parent = this.transform;
Teleportaion.transform.tag = "Teleportation";
}
}
}
Now some gameobjects are out of the terrain area.
What I want to do is to keep the clones to be in random position but only inside the terrain area.
How I do Instantiate Objects inside the terrain area?
I noticed that you are creating new instance of the Random class. Don't do that with Unity's Random API. Just use Random.Range to generate random numbers.
As for generating random GameObjects on a terrain:
1.Find the X position:
Min = terrain.terrainData.size.x.
Max = terrain.transform.position.x + terrain.terrainData.size.x.
The final random X should be:
randX = UnityEngine.Random.Range(Min, Min + Max);
2.Find the Z position:
Min = terrain.transform.position.z;
Max = terrain.transform.position.z + terrain.terrainData.size.z;
The final random Z should be:
randZ = UnityEngine.Random.Range(Min, Min + Max);
3.Find the Y position:
The y-axis does not have to be random. Although, you can make it a random value if you want.
It just has to be over the terrain so that the Instantiated Object will not be under the terrain.
This is where Terrain.SampleHeight comes into place. You must use this function in order to perfectly generate a position that is not under the terrain. You need the result from #1 and #2 to use this:
yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
If you want to apply offset to the y-axis, you can now do it at this time.
yVal = yVal + yOffset;
Below is a general example. You have to use this example to extend your current code.
public GameObject prefab;
public Terrain terrain;
public float yOffset = 0.5f;
private float terrainWidth;
private float terrainLength;
private float xTerrainPos;
private float zTerrainPos;
void Start()
{
//Get terrain size
terrainWidth = terrain.terrainData.size.x;
terrainLength = terrain.terrainData.size.z;
//Get terrain position
xTerrainPos = terrain.transform.position.x;
zTerrainPos = terrain.transform.position.z;
generateObjectOnTerrain();
}
void generateObjectOnTerrain()
{
//Generate random x,z,y position on the terrain
float randX = UnityEngine.Random.Range(xTerrainPos, xTerrainPos + terrainWidth);
float randZ = UnityEngine.Random.Range(zTerrainPos, zTerrainPos + terrainLength);
float yVal = Terrain.activeTerrain.SampleHeight(new Vector3(randX, 0, randZ));
//Apply Offset if needed
yVal = yVal + yOffset;
//Generate the Prefab on the generated position
GameObject objInstance = (GameObject)Instantiate(prefab, new Vector3(randX, yVal, randZ), Quaternion.identity);
}

How to set texture to automatically match with a change in window size by using same texture

I made a small 2D game by using unity3D(5.0.2f1). I dragged in some textures to use as the background in a scene. It worked well in the Unity Editor, but not when I built and ran it in a different window size. It didn't look as what I had seen in Unity Editor.
What should I do to change the texture size automatically when window size changes? Here is a screenshot of how the image looks in the editor and the build, as well as my build settings:
Maybe these will help!
//file ExtensionsHandy.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public static class ExtensionsHandy
{
public static float OrthoScreenWidth(this Camera c)
{
return
c.ViewportToWorldPoint(new Vector3(1,1,10)).x
- c.ViewportToWorldPoint(new Vector3(0,1,10)).x;
}
public static float OrthoScreenHeight(this Camera c)
{
return
c.ViewportToWorldPoint(new Vector3(0,1,10)).y
- c.ViewportToWorldPoint(new Vector3(0,0,10)).y;
}
}
try like this
void Start()
{
float w = Camera.main.OrthoScreenWidth();
Debug.Log("w is " +w.ToString("f4");
}
Note. If not familiar with "extensions": quick tutorial.
Here are more very handy extensions for you.
These will actually move an object to the screen points!
For example,
transform.ScreenRight();
transform.ScreenTop();
the object, is now at the top-right of the screen!!!
And consider this ......
void Update()
{
transform.ScreenRight();
}
In that example: even if the user changes the orientation of the device, even if the user resizes the screen (Mac or Windows), the object is ALWAYS on the right of the screen!!
public static Vector3 WP( this Camera c, float x, float y, float z)
{
return c.ViewportToWorldPoint(new Vector3(x,y,z));
}
public static void ScreenLeft(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 leftTop = Camera.main.WP(0f,1f,0f);
float leftX = leftTop.x;
rr.x = leftX;
moveme.transform.position = rr;
}
public static void ScreenRight(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 rightTop = Camera.main.WP(1f,1f,0f);
float rightX = rightTop.x;
rr.x = rightX;
moveme.transform.position = rr;
}
public static void ScreenBottom(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 bottomLeft = Camera.main.WP(0f,0f,0f);
float bottomY = bottomLeft.y;
rr.y = bottomY;
moveme.transform.position = rr;
}
public static void ScreenTop(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 topLeft = Camera.main.WP(0f,1f,0f);
float topY = topLeft.y;
rr.y = topY;
moveme.transform.position = rr;
}
Hope it helps.....