Search Unity

Centering Camera around Multiple Players, while keeping all in frame

Discussion in 'Scripting' started by empirebattles, Sep 3, 2017.

  1. empirebattles

    empirebattles

    Joined:
    May 17, 2013
    Posts:
    19
    I'm working on a script to center a camera on multiple players, and is working fairly well (finding midpoint between all players, and centering focus on that position). Players cannot move outside of the frame of view.

    however, the problem i'm running into now, is that when one player moves, the camera/view can move so that other players are no longer inside the view.

    I'm running with an orthographic view.
    I assume I need to gather the minimum and maximum coordinates for all the players, but tying that into the focal point of the camera is where my brain is shutting off.


    Code

    Code (CSharp):
    1.  
    2.  
    3.     //public GameObject player;       //Public variable to store a reference to the player game object
    4.     public float offX;
    5.     public float offY;
    6.     public float offZ;
    7.     private Vector3 offset;         //Private variable to store the offset distance between the player and camera
    8.     private List<Transform> playerlist=new List<Transform>();//Private variable to store a list of the location of each player
    9.     private Vector3 midpoint;
    10.     // Use this for initialization
    11.     void Start ()
    12.     {
    13.         //Calculate and store the offset value by getting the distance between the player's position and camera's position.
    14.         offset.Set(offX,offY,offZ);
    15.     }
    16.  
    17.     // LateUpdate is called after Update each frame
    18.     void LateUpdate ()
    19.     {
    20.         List<Transform> playerlist=new List<Transform>();
    21.         GameObject[] players = GameObject.FindGameObjectsWithTag ("Player");
    22.         int count = 0;
    23.         foreach (GameObject p in players) {
    24.             count++;
    25.             playerlist.Add (p.transform);
    26.         }
    27.         float midx;
    28.         float midy;
    29.         float midz;
    30.         int i;
    31.         if (count > 1) {
    32.             for (i = 1; i < count; i++) {
    33.                 midx = +playerlist [i].transform.position.x;
    34.             }
    35.             midx = (midx-playerlist [0].transform.position.x) / count;
    36.             midpoint.x =midx+playerlist [0].transform.position.x;
    37.  
    38.             for (i = 1; i < count; i++) {
    39.                 midy = +playerlist [i].transform.position.y;
    40.             }
    41.             midy = (midy-playerlist [0].transform.position.y) / count;
    42.             midpoint.y =midy+playerlist [0].transform.position.y;
    43.  
    44.             for (i = 1; i < count; i++) {
    45.                 midz = +playerlist [i].transform.position.z;
    46.             }
    47.             midz = (midz-playerlist [0].transform.position.z) / count;
    48.             midpoint.z =midz+playerlist [0].transform.position.z;
    49.  
    50.             transform.position = new Vector3(midpoint.x + offset.x, midpoint.y+offset.y, midpoint.z+offset.z);
    51.         } else {
    52.             transform.position = new Vector3 (playerlist [0].transform.position.x + offset.x, playerlist [0].transform.position.y+offset.y, playerlist [0].transform.position.z+offset.z);
    53.         }
    54.     }
     
  2. qqqbbb

    qqqbbb

    Joined:
    Jan 13, 2016
    Posts:
    113
    Unity's Tanks! tutorial has this kind of camera.
     
    lyingturkey likes this.
  3. empirebattles

    empirebattles

    Joined:
    May 17, 2013
    Posts:
    19
    Thanks, i'll check this out
     
  4. empirebattles

    empirebattles

    Joined:
    May 17, 2013
    Posts:
    19
    Looking at this tutorial, it does do the centering (same effect that I have accomplished), but instead of forcing players to stay within the screen, it expands the screen. I need a way to keep the screen the same size, and keep all players within it (aka, dont allow the screen to move if moving would move a player past the perimeter).
     
  5. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    so similar to a side-scroller like Contra...

    Use a Bounds. have the camera specify and update a Bounds area every LateUpdate. and each player will use player.position = cameraBounds.ClosestPoint(player.position) on Update so that they are always forced within the bounds
     
  6. empirebattles

    empirebattles

    Joined:
    May 17, 2013
    Posts:
    19
    that sounds like it should work. Just set the bounds to be the middle point between the players, and set it to be smaller than the view size... in theory, no player should be able to move more than x distance away from the center of all players, and the view will be x+15, to ensure the view completely encapsulates the bounds.

    I'm not at a computer for a few days, so i'll have to wait to test it out. But it sounds viable in theory.

    Silly question: is there any way to give the bounds its own dimensions? or is it always like camera and based round size? (i dont forsee any issue where i need unique bounds, but.... never know :p )
     
  7. JoshuaMcKenzie

    JoshuaMcKenzie

    Joined:
    Jun 20, 2015
    Posts:
    916
    Bounds is just a simple volumetric area in the shape of a box (or rectangle or line, depending if the extents vector has any zeros). it only has 2 variables, center and extents. All other data and methods are derived from those two variables.
    Its often used by Renderers, Colliders, and even Mesh objects to perform the very fast AABB calculation (aka Axis-Aligned Bounding Box via the Contains() method) to see if one object is inside or overlapping with the other. Just like they do internally, your camera will need to manage setting their dimensions and center.

    Bounds has a constructor where you can set its center and size. You can also update both variables. It also has an Encapsulate() method so that it grows one side of the bounding box until it fully envelopes the point or other bounds you provided. Bounds isn't directly affected by a transform position, rotation, or scale, it holds no such concepts. typically when it matters such data would be preprocessed before sent through the bounds methods.