Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Need help with screenspace/offset/rotation math.

Discussion in 'Scripting' started by Nanako, Nov 18, 2014.

  1. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    Hi all. I'm trying to create a third person camera to my specific requirements, and i'm almost there! it works 90%. i wrote it all myself <3 but it has a problem

    However, here's how i'm doing it at the moment:

    To begin with, my camera calculates a desired offset from the player in order to keep them at a specific point in screenspace. It does this by using ScreenToWorldPoint to calculate the player offset, and inverts that. It takes SubjectScreenOffset as an input, which is a Vector2 that ranges +-0.5 on each axis.

    Code (CSharp):
    1.     void CalculateCameraOffset()
    2.     {
    3.         Vector2 screenSize = new Vector2(cam.pixelWidth, cam.pixelHeight);
    4.         Vector2 screenPixelPosition = new Vector2((SubjectScreenOffset.x * screenSize.x) + (screenSize.x * 0.5f), (SubjectScreenOffset.y * screenSize.y) + (screenSize.y * 0.5f));
    5.         Vector3 desiredPlayerPosition = cam.ScreenToWorldPoint(new Vector3((SubjectScreenOffset.x * screenSize.x) + (screenSize.x * 0.5f), (SubjectScreenOffset.y * screenSize.y) + (screenSize.y * 0.5f),Distance));
    6.    
    7.         cameraWorldOffset = desiredPlayerPosition - transform.position;
    8.         cameraWorldOffset *= -1;
    9.         focalPoint = (Vector3.forward * FocalDistanceFromSubject) + player.collider.bounds.center;
    10.     }
    (an initial focal point is set here to prevent math errors in the first frame)
    Once this offset is calculated, it is correct for when the focal point is in the direction of Vector3.forward from the player. Each frame the camera finds where the focal point has adjusted to, and rotates its offset from the player accordingly, like this:

    Code (CSharp):
    1.     void Move()
    2.     {
    3.         rotationToFocalPoint.SetFromToRotation(Vector3.forward, focalPoint - player.collider.bounds.center);
    4.         transform.position = player.collider.bounds.center + (rotationToFocalPoint * cameraWorldOffset);
    5.         transform.LookAt(focalPoint);
    6.     }
    As can be seen here, after setting its offset every frame, the camera then turns to look at the focal point. THAT is where i'm going wrong. Because the camera is rotating, the player's screenspace location changes away from what is desired.

    However it seems to rotate by a consistent amount with each lookAt, so the player's screenspace location IS constant as originally designed. It's just not at the specified point Generally it's much closer to the centre. And if i increase the SubjectScreenOffset beyond 0.5 in either direction, the camera just zooms out and fails to compensate for anything.

    Basically what i have is a chicken/egg problem that i don't know how to solve. Here's a pictoral example:



    The camera needs to point at the focal point. And because of that, the required offset to achieve what i want will be different from how i'm calculating it now. But i don't know how to calculate that required value.

    and if i used LookAt after calculating the original offset, and then recalculated the offset, then the rotation that LookAt gives would change, and so recalculating the offset would be required. And then look at would change, and so on. I don't have the math knowledge to solve this corectly
     
  2. A.Killingbeck

    A.Killingbeck

    Joined:
    Feb 21, 2014
    Posts:
    483
    So the camera should always look at the focal point at a constant distance? It's not clear to me at least what you're actually trying to accomplish. Is there a similar game with the desired camera movement?
     
  3. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    distance is irrelevant, that's calculated elsewhere. you don't need to worry about that for the purpose of helping me, i've got it solved

    What i'm trying to accomplish is to keep the player's screenspace location the same. That is, the player stays in the exact same spot on the screen as the camera is rotated around them. (generally, offset to one side of the centre so that the player model doesn't block the view). And as already mentioned, i have achieved this! The spot just isn't where i want it to be because of the camera rotating to look at the focal point

    The model for the system is red faction guerilla, among others:


    but i think it's common to a lot of third person shooter games.
     
  4. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    hooray, i've figured it out on my own. And then run into a completely seperate problem. in many situations (particularly when the focal point is close) it's impossible to keep the focal point in the centre AND keep the player's screenspace position, without sacrificing one of the distances. i think i can solve it from here with pythagoras though
     
  5. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    I think each frame:

    1. Position camera at player position.
    2. Point camera at focus (must be done before step 3).
    3. .translate camera back/right/up by a few units (as specified in a public Vector3 variable).

    Should work fine, I've done this a few times. It just does it in separate simple steps. Might need to perform step 2 again after. It all works out since it's performed each frame.
     
  6. Stoven

    Stoven

    Joined:
    Jul 28, 2014
    Posts:
    171
    Use hippocoder's solution if you want to make your life easier.

    I think the mathematical solution for this problem is to find the plane in the system of equations that satisfy these conditions:

    -The Plane with a direction vector that points towards the Focal point at the camera's new point on the plane (more specifically, satisfying this condition: focal point location - camera's new point on the plane as the direction of the camera)
    -The Plane with the player's position projected at a specific position upon the Plane, relative to the camera's new point on the plane

    In order to determine what that specific position is, you would need to use the Aspect Ratio of the screen and relate the size in pixels somehow (which will likely require using the Camera's perspective matrix and converting world space to screen space) and then when you find the Plane and the point along the plane that the Camera needs to be at, place the Camera on that point and facing in that Plane's direction.

    Basically, it feels like way more work than its worth. There may be other ways, but I think this is one of the 'calculated' ways to solve your problem.
     
    Last edited: Nov 18, 2014
  7. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    I've got it solved now.

    My mistake was pointing at the focal point, that shouldn't have been done. Sinc the camera's disatance from the player is fixed, and the camera's angle to the player is also fixed, something's gotta give. That something is the focal point. In normal mouselook mode, the camera and player are known, and the focal point is calculated. I'll work backwards when i implement lock-on mode.

    I solved it all with trigonometry.. long story short, i needed more sleep and coffee to resore my ability to generalize properly. I also struggled for hours before realising Mathf.sin takes radians.

    Nah you're overcomplicating it. i already had this problem solved in the camera offset function posted earlier., ScreenToWorldPoint does all the heavy lifting.
     
  8. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    You're smarter than I am! glad it was solved :)
     
  9. Nanako

    Nanako

    Joined:
    Sep 24, 2014
    Posts:
    1,047
    I resent that implication >: O

    so saving that as a quote for the future though
     
  10. hippocoder

    hippocoder

    Digital Ape Moderator

    Joined:
    Apr 11, 2010
    Posts:
    29,723
    The implication it was solved, or the implication that you might be smarter? :O