how to get camera width in unity - c#

Problem
I have a spawn manager written in c# which spawns my game object, i use screen.width, to set the maximum screen with and -screen.width to set the minimum screen width for the spawning, but my game object spawns way off the screen.
I am using a portrait camera 2:3 instead of free aspect as my camera view, as i want my game to be in portrait mode
how do i make my game object spawn within the camera widths(max and min)?
my code
public class SpawnManager : MonoBehaviour {
public int maxBalloons = 100;
public GameObject balloon;
public float horizontalMin = -Screen.width;
public float horizontalMax = Screen.width;
public float verticalMin = -5.0f;
public float verticalMax = 1.0f;
private Vector2 originPosition;
void Start () {
originPosition = transform.position;
Spawn ();
}
void Spawn()
{
for (int i = 0; i < maxBalloons; i++)
{
Vector2 randomPosition = originPosition + new Vector2 (Random.Range(horizontalMin, horizontalMax), Random.Range (verticalMin, verticalMax));
Instantiate(balloon, randomPosition, Quaternion.identity);
originPosition = randomPosition;
}
}
}
Edit
I changed
Vector2 randomPosition = originPosition + new Vector2 (Random.Range(horizontalMin, horizontalMax), Random.Range (verticalMin, verticalMax));
To
Vector2 randomPosition =Camera.ScreenToWorldPoint (originPosition + new Vector2 (Random.Range(horizontalMin, horizontalMax), Random.Range (verticalMin, verticalMax)));
Still did not work as it should

A position on your screen with a X smaller than 0 will be always out of your screen. The bottom left corner of your screen is the origin of your the coordinate (x: 0, y: 0)
But here I think you mingled 2 kinds of positions. The position on your screen, is not the same position in the world space of your scene. It depends where the camera is rendering.
The position on the bottom left corner of your screen will not be x:0 y:0 in the world space.
To achieve what you are looking for you need to transform the position on the left and the right of your camera into worldspace positions.
Use Camera.ScreenToWorldPoint to achieve that : https://docs.unity3d.com/ScriptReference/Camera.ScreenToWorldPoint.html

Related

How to make a smooth crosshair in Unity3D?

In Unity 3D I'd like to create a crosshair for my top-down 2D-shooter that gradually moves to its target whenever the player has the same x-position as the target.
The problem is that I want a smooth animation when the crosshair moves to the target. I have included a small gif from another game that shows a crosshair I'd like to achieve. Have a look at it:
Crosshair video
I tried to do that with the following script but failed - the crosshair jumps forth and back when the enemies appear. It doesn't look so smooth like in the video I mentioned above.
The following script is attached to the player:
[SerializeField]
private GameObject crosshairGO;
[SerializeField]
private float speedCrosshair = 100.0f;
private Rigidbody2D crosshairRB;
private bool crosshairBegin = true;
void Start () {
crosshairRB = crosshairGO.GetComponent<Rigidbody2D>();
crosshairBegin = true;
}
void FixedUpdate() {
//Cast a ray straight up from the player
float _size = 12f;
Vector2 _direction = this.transform.up;
RaycastHit2D _hit = Physics2D.Raycast(this.transform.position, _direction, _size);
if (_hit.collider != null && _hit.collider.tag == "EnemyShipTag") {
// We touched something!
Debug.Log("we touched the enemy");
Vector2 _direction2 = (_hit.collider.gameObject.transform.position - crosshairGO.transform.position).normalized;
crosshairRB.velocity = new Vector2(this.transform.position.x, _direction2.y * speedCrosshair);
crosshairBegin = false;
} else {
// Nothing hit
Debug.Log("nothing hit");
crosshairRB.velocity = Vector2.zero;
Vector2 _pos2 = new Vector2(this.transform.position.x, 4.5f);
if (crosshairBegin) crosshairGO.transform.position = _pos2;
}
}
I think you need create a new variable call Speed translation
with
speed = distance from cross hair to enemy position / time (here is Time.fixedDeltaTime);
then multiply speed with velocity, the cross hair will move to enmey positsion in one frame.
but you can adjust speed by mitiply it with some float > 0 and < 1;

Camera shaking/Jitters when Player moves

I made a Camera Script that follows the player using a lerp for making it look more smooth, but for some reason, it looks laggy when walking in some sudden areas.
The ground the player is walking on is tilemap, and at first, I thought there were tiny cell gaps that caused the problem, but it still happens even when I changed the ground to one solid block. So I concluded it must be something with Camera Script that cause this problem.
Here is a video clip of what I'm talking about: https://youtu.be/mmBMHWuHpxo
I think the problem stems from this part of my camera script:
void SetTargetPos()
{
// By default the target x and y coordinates of the camera are it's current x and y coordinates.
targetX = transform.position.x;
targetY = transform.position.y;
// If the player has moved beyond the x margin...
if (CheckXMargin())
{
// ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position.
targetX = Mathf.Lerp(transform.position.x, transformPlayer.position.x, xSmooth * Time.deltaTime);
}
// If the player has moved beyond the y margin...
if (CheckYMargin())
{
// ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position.
targetY = Mathf.Lerp(transform.position.y, transformPlayer.position.y, ySmooth * Time.deltaTime);
}
// The target x and y coordinates should not be larger than the maximum or smaller than the minimum.
targetX = Mathf.Clamp(targetX, currentMinBounds.x, currentMaxBounds.x);
targetY = Mathf.Clamp(targetY, currentMinBounds.y, currentMaxBounds.y);
// Set the camera's position to the target position with the same z component.
transform.position = new Vector3(targetX, targetY, transform.position.z);
TestOutOfCamBounds();
}
Btw I have the exact same script on different Unity Projects with the same variable inputs. There is a small difference, and that just the overall size of everything in the second project is a lot smaller than the first one. But it works completely fine on that project. I have also tried Smoothdamp instead of Lerp, still no success. Here is a video clip of the other project: https://youtu.be/baJmKehYfG0
Any help will be much appreciated.
If you want to look at the entire script here it is:
public class Camera_Controller : MonoBehaviour
{
private static Camera_Controller _instance;
public static Camera_Controller instance;
[Header("Put player here")]
public GameObject player;
public Transform transformPlayer;
[Space]
Vector2 currentMinBounds;
Vector2 currentMaxBounds;
public Vector3 targetPos;
[Space]
[Header("Camera Properties")]
public float xMargin = 1f;
public float yMargin = 1f;
public float xSmooth = 8f;
public float ySmooth = 8f;
public Vector3 velocity = Vector3.zero;
private float targetY;
private float targetX;
[Header("Smooth Transition")]
public Vector3 oldPosition;
public Vector3 targetPosition;
public float transitionsTime;
public bool switchingCamera;
private void Awake()
{
if (_instance != null && _instance != this)
{
Destroy(gameObject);
return;
}
else
{
_instance = this;
}
instance = _instance;
}
void Start()
{
targetPos = transform.position;
}
private bool CheckXMargin()
{
// Returns true if the distance between the camera and the player in the x axis is greater than the x margin.
return Mathf.Abs(transform.position.x - transformPlayer.position.x) > xMargin;
}
private bool CheckYMargin()
{
// Returns true if the distance between the camera and the player in the y axis is greater than the y margin.
return Mathf.Abs(transform.position.y - transformPlayer.position.y) > yMargin;
}
void Update()
{
if (!switchingCamera)
{
SetTargetPos();
}
}
public void SetCamBounds(Vector2 minBounds, Vector2 maxBounds) //Called from Game Events Trough WarpController as trigger
{
currentMinBounds = minBounds;
currentMaxBounds = maxBounds;
}
//SetTargetPos() should be causing the problem
void SetTargetPos()
{
// By default the target x and y coordinates of the camera are it's current x and y coordinates.
targetX = transform.position.x;
targetY = transform.position.y;
// If the player has moved beyond the x margin...
if (CheckXMargin())
{
// ... the target x coordinate should be a Lerp between the camera's current x position and the player's current x position.
targetX = Mathf.Lerp(transform.position.x, transformPlayer.position.x, xSmooth * Time.deltaTime);
}
// If the player has moved beyond the y margin...
if (CheckYMargin())
{
// ... the target y coordinate should be a Lerp between the camera's current y position and the player's current y position.
targetY = Mathf.Lerp(transform.position.y, transformPlayer.position.y, ySmooth * Time.deltaTime);
}
// The target x and y coordinates should not be larger than the maximum or smaller than the minimum.
targetX = Mathf.Clamp(targetX, currentMinBounds.x, currentMaxBounds.x);
targetY = Mathf.Clamp(targetY, currentMinBounds.y, currentMaxBounds.y);
// Set the camera's position to the target position with the same z component.
transform.position = new Vector3(targetX, targetY, transform.position.z);
TestOutOfCamBounds();
}
void TestOutOfCamBounds() //Set Camera some boundaries.
{
if (targetPos.x <= currentMinBounds.x)
{
targetPos.x = currentMinBounds.x;
}
if (targetPos.x >= currentMaxBounds.x)
{
targetPos.x = currentMaxBounds.x;
}
if (targetPos.y <= currentMinBounds.y)
{
targetPos.y = currentMinBounds.y;
}
if (targetPos.y >= currentMaxBounds.y)
{
targetPos.y = currentMaxBounds.y;
}
}
}
Try doing the call for the cammer movement in Late update, Example bellow.
private void LateUpdate() {
SetTargetPos();
}
This is called after the update method and might help reduce the cammer jitter.
Your second video is 2d and your first is 3d. try lerping the z position also.
targetZ = Mathf.Lerp(transform.position.z, transformPlayer.position.z, zSmooth * Time.deltaTime);
I found a solution to it all!
I changed the update function to LateUpdate()... Sorry for wasting your time

Camera Lock-On behind player while targeting enemy

Something similar to either Rocket League or Kingdom Hearts, where the camera locks onto the target but it still keeps the player in the center of the screen. I've placed the camera as a child of the player, but after trying out various solutions from others I'm still unable to position the camera correctly.
public List<Transform> targets;
private void EnemyCam()
{
Vector3 centerPoint = GetCenterPoint();
transform.LookAt(centerPoint);
Vector3 newPos = centerPoint;
transform.position = Vector3.SmoothDamp(transform.position, newPos, ref
velocity, smoothTime);
}
private Vector3 GetCenterPoint()
{
if (targets.Count == 1)
return targets[0].position;
var bounds = new Bounds(targets[0].position, Vector3.zero);
for (int i = 0; i < targets.Count; ++i)
bounds.Encapsulate(targets[i].position);
return bounds.center;
}
If you are moving you camera by script, it shouldn't be child of the moving player at the same time. You are setting up some position from script, but at the same time, this position is modified also by parent object so final result is unpredictable.

Spawning zombies just outside of camera bounds in Unity

Usually in any new engine I try to make a top down zombie shooter using simple graphics (usually squares/rectangles) and that's what I'm currently trying to do in Unity.
I've got to the point where I have:
A player that shoots (and is controlled via WASD/arrow keys and
mouse)
Zombies that spawn and go towards the player
Zombies that can be killed (and once all zombies are dead, another
wave spawns)
But, currently, it seems that the way I spawn them spawns them way too far away from the player. I use an orthographic camera.
Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZombieSpawner : MonoBehaviour {
private int waveNumber = 0;
public int enemiesAmount = 0;
public GameObject zombie;
public Camera cam;
// Use this for initialization
void Start () {
cam = Camera.main;
enemiesAmount = 0;
}
// Update is called once per frame
void Update () {
float height = 2f * cam.orthographicSize;
float width = height * cam.aspect;
if (enemiesAmount==0) {
waveNumber++;
for (int i = 0; i < waveNumber; i++) {
Instantiate(zombie, new Vector3(cam.transform.position.x + Random.Range(-width, width),3,cam.transform.position.z+height+Random.Range(10,30)),Quaternion.identity);
enemiesAmount++;
}
}
}
}
If You want them to spawn zombies just outside camera view don't multiply orthographic size.
float height = cam.orthographicSize; // now zombies spawn on camera view border
float height = cam.orthographicSize + 1 // now they spawn just outside
It'a a small change, but You could also set width as:
float width = cam.orthographicSize * cam.aspect + 1;
Try to spawn another wave when there is one zombie left and see how game pacing has changed ;)

Building an orthographic camera for Unity3D, how can I keep four specific targets in sight?

I have a 2D Orthographic camera for a game that is built similarly to Tennis. I've been working out the code for this, and I think I'm only part of the way so far. At the moment... it... sort-of keeps the two players in frame, with the frame leading more towards the human player - Player One. However, it also has a tendency to drop below the ground level - especially when it zooms out to keep the targets in view. There are four specific targets: The Ground, Ball, Player One, and Player Two.
The ground should always be at the 'bottom', otherwise when the camera goes below ground it shows sky - not really a desirable effect. This is the code I've developed so far... the two players are effectively paddles, but it only shows the center between them:
using UnityEngine;
using System.Collections;
public class CameraController : MonoBehaviour {
// Moving Camera, This Camera tries to follow Player One, Two, and Ball //
public static CameraController Instance;
public Transform PlayerOne;
public Transform PlayerTwo;
public Transform Ball;
public bool Ready = false;
private float MinX = -46.0f;
private float MaxX = 46.0f;
private float MinY = 12.0f;
private float MaxY = 35.0f;
private float LimitFromPlayerX = 20.0f;
private float LimitFromPlayery = 20.0f;
private float DistanceToGround = 0.0f;
private float DistanceFromCenter = 2.0f;
private float Height = 4.0f;
private float Damping = 5f;
private Vector3 EstimatedCameraPosition = Vector3.zero;
private Vector3 WantedPosition = Vector3.zero;
void Awake()
{
Instance = this;
}
public void SetCameraPosition()
{
Vector3 PlayerPosistion = PlayerOne.position;
PlayerPosistion.z = -10.10f;
transform.position = PlayerPosistion;
}
// Update is called once per frame
void FixedUpdate () {
if (Ready) {
Vector3 PlayerPosistion = PlayerOne.position;
PlayerPosistion.z = -10.10f;
Vector3 CameraPosition = transform.position;
CameraPosition.z = -10.10f;
// Get the Distance from the Player to the Ball //
Vector3 WantedPosition = PlayerTwo.transform.position - -PlayerOne.transform.position;
float WPMag = Mathf.Abs(WantedPosition.magnitude);
WPMag = Mathf.Clamp(WPMag, 20, 40);
Debug.Log(WPMag);
Camera.main.orthographicSize = WPMag;
transform.position = Vector3.Lerp(CameraPosition, WantedPosition, Damping * Time.deltaTime);
}
}
void LateUpdate()
{
Vector3 Posit = transform.position;
Posit.x = Mathf.Clamp (Posit.x, MinX, MaxX);
Posit.y = Mathf.Clamp (Posit.y, MinY, MaxY);
transform.position = Posit;
}
}
WPMag was my attempt to zoom out and match the players at least, but so far it's only partially working.
To keep all three objects in view, you'll want to focus the camera on the midpoint or "average" position of the three objects. Getting the midpoint of three objects works just like getting the midpoint of two objects: (PlayerOne.position + PlayerTwo.position + Ball.position) / 3.0f
You'll then want to set orthographic size to the furthest distance from the midpoint of the three tracked objects. This will ensure that all three objects stay in the frame.
Finally, to keep the camera from showing underground skies, you should enforce a lower limit for the camera's Y position. The orthographic size is half the vertical height of the viewport, so you'd use CameraPosition.y = Mathf.Max(CameraPosition.y, groundHeight + camera.main.orthographicSize)

Categories