Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by Baconaise · May 28, 2012 at 01:09 AM · camerapositioningviewportviewporttoworldpoint

ViewportToWorldPoint relative to camera angle

Using the very helpful tip from this thread, I was able to lock my object to remain inside the viewport, and it works with both orthographic and perspective cameras, with one issue.

I need this using a perspective camera at an angle. The camera's X axis rotation is -45 degrees. This seems to mess up the position logic below. Any idea why I'm missing?

 float dist = (transform.position - myCamera.transform.position).z;  

 float leftBorder = myCamera.ViewportToWorldPoint(new Vector3(0,0,dist)).x;
 float rightBorder = myCamera.ViewportToWorldPoint(new Vector3(1,0,dist)).x;
 float bottomBorder = myCamera.ViewportToWorldPoint(new Vector3(0,0,dist)).y;     
 float topBorder = myCamera.ViewportToWorldPoint(new Vector3(0,1,dist)).y; 

 float x = Mathf.Clamp(transform.position.x,leftBorder,rightBorder); 
 float y = Mathf.Clamp(transform.position.y,bottomBorder,topBorder);
 
 transform.position = new Vector3(x,y, transform.position.z);

For clarity, when the camera is level the object is prevented from moving off camera, it just 'sticks' as far as it can go. However when the camera is angled it seems to change my z depth. Dragging the object to the top does prevent it from moving off camera, but it starts to zoom along the z-index.

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image You! · May 28, 2012 at 01:13 AM 0
Share

@Baconaise, thank you

avatar image Datael · May 28, 2012 at 08:50 AM 0
Share

I haven't got any code to fix this so I won't post it as an answer, but you need to adjust how you use the dist variable according to the camera rotation; you're actually going to have to rethink a lot of this if you want to include it in the calculations.

If you want the object to move somewhere on the camera's viewplane at a certain depth then you will have to rethink the last 3 lines; you're only adjusting the x and y and are not adjusting the z. This will mean the distance gets lost...

How exactly do you want the movement to be limited? And is the camera free-rotating/moving?

2 Replies

· Add your reply
  • Sort: 
avatar image
5
Best Answer

Answer by Bunny83 · May 28, 2012 at 11:51 AM

Instead of

 float dist = (transform.position - myCamera.transform.position).z;

use

 float dist = myCamera.transform.InverseTransformPoint(transform.position).z;

This will transform the vector in the cameras local space, so the z axis is your view direction and the distance from the camera origin parallel to the near plane. Keep in mind that the camera origin always is located behind the nearplane for perspective cameras. To get the distance from the nearplane, just subract the near value from the distance ;) ViewportToWorldPoint needs the distance from the camera origin afaik.

edit
The whole clamping process can be done like this:

 Vector3 localPos = myCamera.transform.InverseTransformPoint(transform.position);

 Vector3 leftBottom = myCamera.ViewportToWorldPoint(new Vector3(0,0,dist));
 Vector3 rightTop = myCamera.ViewportToWorldPoint(new Vector3(1,1,dist));
 leftBottom = myCamera.transform.InverseTransformPoint(leftBottom);
 rightTop = myCamera.transform.InverseTransformPoint(rightTop);
 
 float x = Mathf.Clamp( localPos.x, leftBottom.x, rightTop.x );
 float y = Mathf.Clamp( localPos.y, leftBottom.y, rightTop.y );
 
 transform.position = myCamera.transform.TransformPoint(new Vector3(x,y, localPos.z));

This will transform all coordinates into the cameras local space, clamp the position and convert back to world space at the end.

Comment
Add comment · Show 3 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Bunny83 · May 28, 2012 at 12:12 PM 0
Share

If the camera distance and orientation doesn't change it might be a bit faster to setup a Plane in Start, but haven't tried it that way ;)

avatar image whydoidoit · May 28, 2012 at 12:22 PM 0
Share

Nice stuff :)

avatar image Baconaise · May 29, 2012 at 03:34 PM 0
Share

This didn't quite do the trick because of some scaling issues, but InverseTransformPoint pointed me in the right direction. Thanks! :)

avatar image
3

Answer by whydoidoit · May 28, 2012 at 11:36 AM

Ok so your problem is your are thinking in x,y,z which pretty much goes out of the window when you start rotating things. Instead you need to consider this as a 3d problem.

You've defined a plane, using the cameras viewport and the distance of the plane from the camera.

Now you want to constrain the object to lie within two vectors that define the plane. First you need to split up the transform.position so it is comprised of two parts, one for each of the axes, then you want to constrain each of those split parts so that they fall within the desired range, then put them back together again :)

Just a note, due to the floating point inaccuracies, you need to have a desiredPosition variable that holds where you want the object to be - otherwise it will probably just float off into nowhere :)

UPDATE

Used Bunny83's parallel distance calculation, clamped the dot product which I forgot in the last version (oops).

Here you go:

 public Vector3 desiredPosition;
 
 // Use this for initialization
 void Start ()
 {
     desiredPosition = transform.position;
     
 }
 
 // Update is called once per frame
 void Update ()
 {
     var myCamera = Camera.main;
     //Get the distance from the camera
     float dist = Mathf.Abs(myCamera.transform.InverseTransformPoint (desiredPosition).z);
     
     //Get the coordinates of the camera at distance d
     Vector3 topLeft = myCamera.ViewportToWorldPoint (new Vector3 (0, 0, dist));
     Vector3 topRight = myCamera.ViewportToWorldPoint (new Vector3 (1, 0, dist));
     Vector3 bottomLeft = myCamera.ViewportToWorldPoint (new Vector3 (0, 1, dist));     
     
     //Work out the two vectors that define the plane on which the object
     //must remain
     Vector3 vY = bottomLeft - topLeft;
     Vector3 vX = topRight - topLeft;
     //Project the objects coordinates onto the plane vectors
     Vector3 vpX = (Mathf.Max (0, (Vector3.Dot (desiredPosition - topLeft, vX))) / vX.sqrMagnitude) * vX;
     Vector3 vpY = (Mathf.Max (0, (Vector3.Dot (desiredPosition - topLeft, vY))) / vY.sqrMagnitude) * vY;
     //Clamp the object to fit in the range defined by the existing vectors
     vpX = Mathf.Clamp01 (vpX.magnitude / vX.magnitude) * vX;
     vpY = Mathf.Clamp01 (vpY.magnitude / vY.magnitude) * vY;
     
     //Set the transform back again
     transform.position = vpX + vpY + topLeft;

     
 
     
 }
Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

8 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Code behind 'Camera.ViewportPointToRay'? 2 Answers

ViewportToWorldPoint with multiple cameras 0 Answers

Viewport to World Coordinates 2 Answers

ViewportToWorldPoint returns same value regardless of input 1 Answer

How to resize a camera's orthoSize for an object to fit inside its rect viewport? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges