Poisht
Poisht

Reputation: 1

(Unity c#) Moving canvas map to center current level on the camera

I am making a 2D android game on Unity. In the world map (level choosing) settings I have a camera that changes shape to fit the largest possible 9:16 aspect on the screen that calls on Awake. Next I have a Start() function that is supposed to move the map on the canvas so that the last clicked level goes to the center of the screen. It seems to work fine on Unity itself and my phone; however, it centers on a wrong position on my tab. I feel it may have something to do with the Canvas scaler Screen match mode but I am not sure where the problem really is.

The code for the camera aspect setting is:

  void Awake() {
    CamAspect();
  }
  public void CamAspect() {
    float targetaspect = 9f / 16f;
    float windowaspect = (float)Screen.width / (float)Screen.height;
    float scaleheight = windowaspect / targetaspect;
    Camera camera = GetComponent<Camera>();
    if (scaleheight < 1f) {
      Rect rect = camera.rect;
      rect.width = 1f;
      rect.height = scaleheight;
      rect.x = 0;
      rect.y = (1f - scaleheight) / 2f;
      camera.rect = rect;
    } else {
      float scalewidth = 1f / scaleheight;
      Rect rect = camera.rect;
      rect.width = scalewidth;
      rect.height = 1f;
      rect.x = (1f - scalewidth) / 2f;
      rect.y = 0;
      camera.rect = rect;
    }
  }

The code for the map centering is (all inside the canvas). The canvas settings are: Render mode: Screen Space - Camera UI scale mode: Scale with screen size, screen match mode Shrink (Match width/height at 0.5 also seemed to work on PC free aspect views). The lastLevelT below gives the position wrt to the bottom left of the map which the level is the child to. The map in turn is positioned wrt to the center of the mapholder (scroll enabling parent). Centering calculations are done with these in mind.

  RectTransform RT;
  float[] lastLevelT;
  float cameraScreenWidth;
  float cameraScreenHeight;
  // map is 4096 wide by 3072 tall
  float shiftx;
  float shifty;
  float mapwidth;
  float mapheight;
  new Camera camera;
  void Start() {
    RT = GetComponent<RectTransform>();
    camera = Camera.main;
    lastLevelT = SettingsManager.currentFocusLevelTransform;
    if (lastLevelT[0] == 0 && lastLevelT[1] == 0) {
      cameraScreenHeight = (float)camera.pixelHeight;
      cameraScreenWidth = (float)camera.pixelWidth;
      RT.localPosition = new Vector2(-cameraScreenWidth * 0.5f, -cameraScreenHeight * 0.5f);
    } else {
      Transform();
    }
  }
  void Transform() {
    mapwidth = RT.rect.width;
    mapheight = RT.rect.height;
    cameraScreenHeight = (float)camera.pixelHeight;
    cameraScreenWidth = (float)camera.pixelWidth;
    shiftx = lastLevelT[0];
    shifty = lastLevelT[1];
    if ((mapwidth - lastLevelT[0]) < (cameraScreenWidth * 0.5f)) {
      shiftx = mapwidth - cameraScreenWidth * 0.5f;
    }
    if (lastLevelT[0] < (cameraScreenWidth * 0.5f)) {
      shiftx = cameraScreenWidth * 0.5f;
    }
    if ((mapheight - lastLevelT[1]) < (cameraScreenHeight * 0.5f)) {
      shifty = mapheight - cameraScreenHeight * 0.5f;
    }
    if (lastLevelT[1] < (cameraScreenHeight * 0.5f)) {
      shifty = cameraScreenHeight * 0.5f;
    }
    RT.localPosition = new Vector2(-shiftx, -shifty);
  }

The mapHolder has a scroll rect on which the map is a child and allows the player to move the map as shown below: MapScene

What should be happening is the following where the map is shifted to try to center the level on map load: Unity scene on PC

The problem is with the tablet where this happens (screen shot of tablet view): Tablet Scene As you can see, the camera does the aspect resizing well and things work but the level is not centered like in the pc (and mobile) cases.

Upvotes: 0

Views: 223

Answers (1)

Poisht
Poisht

Reputation: 1

I solved the issue. In the case of PC and phone, the screen size always (somehow) led to a camera being smaller than the 900:1600px reference resolution. Hence for the edge-level cases where I use half the camera width would use the correct values to shift. However, on a larger screen, the camera size and hence width/height would be larger than the reference 900:1600px and so on the edge cases where the shift amount depends on the camera size it would get shifted more than usual due to a larger camera size in pixels.

Upvotes: 0

Related Questions