- Home /
How to make a smash bros-like camera
I have been making a multiplayer game with the camera focusing on everyone on the screen. Just like smash bros, the camera focuses on the center of all of the characters positions while zooming to keep the players viewable.
My only problem is the zooming with an orthographic camera. So, is there anyone who knows how to zoom the camera to keep the players in view?
(Sample Code would be nice)
Alright, but how do I make the camera know how much to change the size of the viewport to keep every player on screen?
Well , after the rect calculation, the center of the rect can be calculated ((leftx + rightx) /2 , (topy + boty) / 2). You set the camera to look at that point.
The size of the camera is formed by getting the "greater" dimension (either width or height) , and the other one will be calculated preserving the camera ratio.
ex : camera ratio is 4:3 , rect width is 700 , rect height is 300 the final rect will be half of the vertical volume, but the vertical volume has to preserve the ratio , hence 700 * 3/4 = 525 the orthographic size is half the vertical dimension = 212.5
Hmm that is interesting. You also mentioned that I can put a Rect around the object that it is displaying. How would you do that, and for multiple players?
I used the rect to reference the viewport rectangle. As ilustrated on this picture
CodinRonin has given you lots of information to get started on this. From the first comment :
you can iterate through the positions of all the players and get the Rect in which they are all displayed (the topmost and lowest y , the leftmost and rightmost x )
Have you done this yet?
PseudoCode :
var $$anonymous$$X : float = $$anonymous$$athf.infinity;
var maxX : float = -$$anonymous$$athf.infinity;
var $$anonymous$$Y : float = $$anonymous$$athf.infinity;
var maxY : float = -$$anonymous$$athf.infinity;
for each player
{
if player.x < $$anonymous$$X
$$anonymous$$X = player.x
else if player.x > maxX
maxX = player.x
if player.y < $$anonymous$$Y
$$anonymous$$Y = player.y
else if player.y > maxY
maxY = player.y
}
from this you will have the bottom-left and top-right corner of your bounding rect area. You should also add a buffer so the player is not cut in half on the edge of the screen.
Edit the question with the progress and code you have made so far.
Answer by Kalbytron · Mar 17, 2014 at 08:23 PM
Sorry about me taking a while to say thanks for the help. I'm just going to post this for everyone to view.
Thanks to CodinRonin and alucardj.
// Update is called once per frame void Update() {
CalculateBounds();
CalculateCameraPosAndSize();
}
void CalculateBounds() { minX = Mathf.Infinity; maxX = -Mathf.Infinity; minY = Mathf.Infinity; maxY = -Mathf.Infinity;
players = GameObject.FindGameObjectsWithTag("Player");
foreach (GameObject player in players){
Vector3 tempPlayer = player.transform.position;
//X Bounds
if (tempPlayer.x < minX)
minX = tempPlayer.x;
if (tempPlayer.x > maxX)
maxX = tempPlayer.x;
//Y Bounds
if (tempPlayer.y < minY)
minY = tempPlayer.y;
if (tempPlayer.y > maxY)
maxY = tempPlayer.y;
}
}
void CalculateCameraPosAndSize() { //Position Vector3 cameraCenter = Vector3.zero;
foreach(GameObject player in players){
cameraCenter += player.transform.position;
}
Vector3 finalCameraCenter = cameraCenter / players.Length;
//Rotates and Positions camera around a point
rot = Quaternion.Euler(angles);
pos = rot * new Vector3(0f, 0f, -camDist) + finalCameraCenter;
transform.rotation = rot;
transform.position = Vector3.Lerp(transform.position, pos, camSpeed * Time.deltaTime);
finalLookAt = Vector3.Lerp (finalLookAt, finalCameraCenter, camSpeed * Time.deltaTime);
transform.LookAt(finalLookAt);
//Size
float sizeX = maxX - minX + cameraBuffer.x;
float sizeY = maxY - minY + cameraBuffer.y;
camSize = (sizeX > sizeY ? sizeX : sizeY);
camera.orthographicSize = camSize * 0.5f;
}
I know this is a little bit old, but now I want to have this kind of camera in my game. I tried this code but it's not okay: Camera movement How to solve this? Did you found a good solution?
i made a similar camera system until i tried removing and adding the targets into the list when the players died. Adding the targets back to the array were very challenging and i could not find a way to do so as List.Add() does not work if the element is 0. i tried List.insert but it still didn;t work. it's like 4 am now and im gonna go nuts soon pls help :(((( thanks in advance!
Have a look at this, this is from brackeys channel (they used to do really nice tuorials) : https://www.youtube.com/watch?v=aLpixrPvlB8
Answer by angelsin · Dec 22, 2016 at 11:46 AM
@GaborV unity 5 answer using a perspective cam
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
namespace Assets.Scripts.Player
{
public class PlayerCam : MonoBehaviour
{
private new Transform transform;
private Vector3 DesiredPos;
public List<Transform> Players;
public float camSpeed;
private Camera cam;
void Awake()
{
transform = GetComponent<Transform>();
cam = GetComponent<Camera>();
}
private void Start()
{
var p = GameObject.FindGameObjectsWithTag("Player");
Players = new List<Transform>();
for (int i = 0; i < p.Length; i++)
{
Players.Add(p[i].GetComponent<Transform>());
}
}
void Update()
{
if (Players.Count <= 0)//early out if no players have been found
return;
DesiredPos = Vector3.zero;
float distance = 0f;
var hSort = Players.OrderByDescending(p => p.position.y);
var wSort = Players.OrderByDescending(p => p.position.x);
var mHeight = hSort.First().position.y - hSort.Last().position.y;
var mWidth = wSort.First().position.x - wSort.Last().position.x;
var distanceH = -(mHeight + 5f) * 0.5f / Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
var distanceW = -(mWidth / cam.aspect + 5f) * 0.5f / Mathf.Tan(cam.fieldOfView * 0.5f * Mathf.Deg2Rad);
distance = distanceH < distanceW ? distanceH : distanceW;
for (int i = 0; i < Players.Count; i++)
{
DesiredPos += Players[i].position;
}
if (distance > -10f) distance = -10f;
DesiredPos /= Players.Count;
DesiredPos.z = distance;
}
void LateUpdate()
{
transform.position = Vector3.MoveTowards(transform.position, DesiredPos, camSpeed);
}
}
}
Answer by CodeElemental · Feb 20, 2014 at 08:14 PM
You can zoom the orthographic camera by adjusting it's orthographic size . As for the positions , you can iterate through the positions of all the players and get the Rect in which they are all displayed (the topmost and lowest y , the leftmost and rightmost x ) , and center the camera to look at that rect.