• 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
0
Question by beau101023 · Aug 30, 2016 at 08:04 PM · rotationvector3normalsblocksrounding

Rounding a position against the surface of an object.

Hello, I am making a block-based building system.

It is supposed to be able to place a block against any surface, aligned to a grid, regardless of the surface's orientation. (For a space-themed ship building game)

I have already implemented the entire placement system, except that I cannot figure out how to place a block where it is supposed to be regardless of the orientation of the thing to be placed against.

My problem, specifically, is that when the surface is at a 45 degree angle, the block's position is not rounded against the surface in one direction. (In this case, the axis around which the object was rotated.)

Here is my current code:

 Vector3 RoundAgainstSurface(Vector3 v3, RaycastHit hit)
 {
     Vector3 vtemp;
 
     // if this direction isn't directly away or towards the surface (so that it doesn't round away or towards it)
     if(Mathf.Abs(hit.normal.x) < 0.5f)
     {
         // round relative distance to the center of the object we're placing on.
         vtemp.x = hit.collider.gameObject.transform.position.x + (float) System.Math.Round(hit.point.x - hit.collider.gameObject.transform.position.x, System.MidpointRounding.AwayFromZero);
     }
     else
     {
         vtemp.x = v3.x;
     }
 
     if(Mathf.Abs(hit.normal.y) < 0.5f)
     {
         vtemp.y = hit.collider.gameObject.transform.position.y + (float) System.Math.Round(hit.point.y - hit.collider.gameObject.transform.position.y, System.MidpointRounding.AwayFromZero);
     }
     else
     {
         vtemp.y = v3.y;
     }
 
     if(Mathf.Abs(hit.normal.z) < 0.5f)
     {
         vtemp.z = hit.collider.gameObject.transform.position.z + (float) System.Math.Round(hit.point.z - hit.collider.gameObject.transform.position.z, System.MidpointRounding.AwayFromZero);
     }
     else
     {
         vtemp.z = v3.z;
     }
 
     //                v make it so the object's center isn't directly at the point of intersection
     return vtemp + (hit.normal/2);
 }

Any help at all would be appreciated. Thanks in advance!

Comment
Add comment
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

1 Reply

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

Answer by b1gry4n · Aug 30, 2016 at 11:50 PM

It seems like youre doing more work than what you need for what you want.

If you want the block to be its default rotation, you wouldnt use the surface normal to calculate any sort of rotation. If you want the block to align to the surface, thats when you want the normal information. After you do your check to see if the clicked point is a suitable spot, simply place the block at the hit.point and set its rotation to Quaternion.identity

If youre trying to snap these objects to a grid you could use

 Vector3 pos= hit.point;
 float gridSize = 1;
 block.position = Vector3(Mathf.Round(pos.x / gridSize ) * gridSize,
                                  Mathf.Round(pos.y / gridSize ) * gridSize,
                                  Mathf.Round(pos.z / gridSize ) * gridSize);
Comment
Add comment · Show 6 · 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 beau101023 · Aug 31, 2016 at 12:05 AM 0
Share

Yes, that's the problem I'm running into. I do want the block to align to the surface, since it's going to be a space game in which the surface could be at any angle at all, in any position including non-rounded positions. (In global space)

What I'm looking for is some way to round the position in local space and align it to a 'grid' which could be in any position in global space.

avatar image b1gry4n beau101023 · Aug 31, 2016 at 12:16 AM 1
Share

Then you would need to translate from world space of the hit.point to local space of the object you wish to snap to (that could be at any rotation) and offset the blocks position/rotation to local space.

http://answers.unity3d.com/questions/181741/how-to-convert-between-local-world-coordinates.html

You can use what I posted above with a $$anonymous$$or tweak as well as a step prior and after.

If I understand correctly and for the purposes of demonstration... say you have an asteroid belt and all the asteroids are rotated differently. retrieving the hit.point on any given asteroid is the first step. The next would be to translate from world position to local position against the hit asteroid's transform. rotate the block to the asteroids rotation and then apply the code above, but ins$$anonymous$$d of using the "hit.point" use your converted "worldtolocal" position. After you have the new localposition you can translate from local back to world space and position your block.

An easier way(i think) would be to make this block you are placing a child of the asteroid. Set its localEulerAngles to 0,0,0 and snap it to the local grid (converting world position to local) and then updating the blocks position with block.localPosition = yournewposition

avatar image beau101023 b1gry4n · Aug 31, 2016 at 12:19 AM 0
Share

That's actually a much simpler and more efficient solution that what I had in $$anonymous$$d. I knew about the world space to local space conversion methods, but I didn't quite know how to use them. Thanks a lot!

Show more comments

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.

Welcome to Unity Answers

If you’re new to Unity Answers, please check our User Guide to help you navigate through our website and refer to our FAQ for more information.

Before posting, make sure to check out our Knowledge Base for commonly asked Unity questions.

Check our Moderator Guidelines if you’re a new moderator and want to work together in an effort to improve Unity Answers and support our users.

Follow this Question

Answers Answers and Comments

68 People are following this question.

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

Related Questions

Make Gameobject Stand On Surface Facing Certain Direction 0 Answers

How to get rotation relative to the ground normal? 0 Answers

Transform rapidly spins when flipped upside down. 2 Answers

Rotate a gameobject like car tire 2 Answers

Checking vector3 gameObject is about to move to (pathfinding collision detection) 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