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
0
Question by cameo24 · Nov 08, 2013 at 12:33 PM · rotate objectmove an objectsurface normal

Issue moving Object around surface of sphere

I have a sphere and I am trying to control a cube moving around the surface of the sphere. So far everything is working perfectly, the only thing I can't figure out is when it gets to the top and bottom of the sphere, the cube rotates left and right by itself and fights my horizontal input.

I think it has to do with how i'm calculating the surface normal. I only want to rotate the cube along the local x-axis and z-axis and I thought Lerping between the surface normal and cube normal would be an easy solution.

When the cube is moving to the right in a straight line following sphere surface. Perfect. Now if I turn left to the top, it gets weird...

alt text

Blue line is the intended direction I have pointed the cube in, the Red line is the direction it is forcing me to go in. Almost following the lines on the sphere.

Update:

Basically what i'm trying to do is get the GameObject normal to align with the surfaceNormal from the Raycast, without rotating around the y-axis.

alt text

I'm trying to get the the red line (myNormal) to align with the green line (surfaceNormal) without causing the cube to turn left or right (rotate around the y-axis).

 void MyRaycast(GameObject other)
     {
         RaycastHit hit;
         Ray ray;
         
         Vector3 myNormal = other.transform.up;
         
         ray = new Ray(other.transform.position, -myNormal);
         if (Physics.Raycast(ray, out hit))
         {    
             surfaceNormal = hit.normal;
         }

         //lerp between cube normal and sphere surface normal
         myNormal = Vector3.Lerp(myNormal, surfaceNormal, lerpSpeed*Time.deltaTime);
         //find the target forward direction
         Vector3 myForward = Vector3.Cross(other.transform.right, myNormal);
         //get quaternion target rotation
         Quaternion targetRotation = Quaternion.LookRotation(myForward, myNormal);
         //rotate cube
         other.transform.rotation = Quaternion.Lerp(other.transform.rotation, targetRotation, lerpSpeed*Time.deltaTime);
 
         if(hit.distance > playerDistance)
         {
             //if cube is leaving sphere apply small force to keep along the surface
             other.rigidbody.AddForce(-gravity * surfaceNormal);
         }
     }

I tried a whole bunch of different combinations of code and tried getting the angle between myNormal and surfaceNormal but I can't get it to work right.

Am I missing something obvious? I'm kind of stuck now. Any help would be greatly appreciated as I am very new to Unity.

capture2.png (23.4 kB)
capture.png (115.6 kB)
Comment
Add comment · Show 4
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 tanoshimi · Nov 15, 2013 at 07:45 AM 0
Share

It looks like you're trying to implement gravity mechanics similar to those in Super $$anonymous$$ario Galaxy:- have you searched existing posts for implementations of that? e.g.

  • http://answers.unity3d.com/questions/25507/How-to-rotate-a-player-when-using-$$anonymous$$ario-Galaxy-style-gravity.html

  • http://forum.unity3d.com/threads/8873-Faux-Gravity-making-my-brain-spin-Help!

  • http://www.gamasutra.com/view/feature/131997/games_demystified_super_mario_.php

avatar image cameo24 · Nov 15, 2013 at 09:36 AM 0
Share

Omg you are a genius! Never even thought of that. Thanks I'll look at the links tomorrow morning!

avatar image MrVerdoux · Nov 15, 2013 at 09:54 AM 0
Share

Could it be that hit.normal is not calculatin its values very well? Have you debugged looking at hit.normal values? Also, near to the top of the sphere there are many triangles, that could be a reason but I´m not quite sure of it.

avatar image DHARMAKAYA · Dec 23, 2015 at 04:39 PM 0
Share

Hi,

Have been wanting to have good scripts to do this properly for about a year or more now. $$anonymous$$ost of the scripts have been incomplete and didn't include a way to jump to another object.

Can post the final complete scripts?

Thanks in advance!

2 Replies

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

Answer by cameo24 · Dec 10, 2013 at 09:02 AM

Hi everyone, thanks for the answers and sorry for the lack of updates. I checked out the links and I noticed in this answer http://forum.unity3d.com/threads/8873-Faux-Gravity-making-my-brain-spin-Help!

It checked to see if r.freezeRotation was set

I copied some of the code and set

 other.rigidbody.freezeRotation = true;

And then used:

 if(hit.distance > playerDistance)
         {
             other.rigidbody.AddForce(-gravity * surfaceNormal);
         }
         
         Quaternion q = Quaternion.FromToRotation(myNormal, surfaceNormal);
         q = q*other.transform.rotation;
         other.transform.rotation = Quaternion.Slerp(other.transform.rotation, q, lerpSpeed*Time.deltaTime);

And it worked!

I was curious about the freezeRotation property so I tried that with my original code above and it worked as well!

So the only thing I was missing was this freezeRotation property of the rigidbody. http://docs.unity3d.com/Documentation/ScriptReference/Rigidbody-freezeRotation.html

I tried freezing the axis in the inspector of the cube, but that caused my cube/snake to not rotate on arrow key input.

Comment
Add comment · Show 2 · 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 NGC6543 · Dec 23, 2015 at 09:45 AM 0
Share

THAN$$anonymous$$ YOU!

avatar image DHARMAKAYA · Dec 23, 2015 at 09:54 AM 0
Share

Can post complete scripts that include jumping from object to object? Thanks in advance!

avatar image
0

Answer by robertbu · Nov 09, 2013 at 01:59 AM

I'm confused about your code, so I may be missing something critical. But to move an object around a sphere, I'd make the object a child of a game object at the same position as the sphere, then I'd use Quaternion.AngleAxis() to rotate the object at the center. Here is an example script. In order to make it work, the cube must have a correct rotation to start (i.e. forward must be tangent to the sphere). Attach the script to the cube and drag and drop the sphere on the 'sphere' variable.

 using UnityEngine;
 using System.Collections;
 
  public class BlockWalker : MonoBehaviour {
     
     public Transform sphere;
     public float turnSpeed = 45.0f;
     public float moveSpeed = 45.0f;
     private Transform center;
 
     void Start () {
         
         center = new GameObject().transform;
         center.parent = sphere;
         transform.parent = center;
     }
     
     void Update() {
         
         if (Input.GetKey(KeyCode.LeftArrow)) {
             transform.Rotate (0.0f, -turnSpeed * Time.deltaTime, 0.0f);        
         }
         if (Input.GetKey(KeyCode.RightArrow)) {
             transform.Rotate (0.0f, turnSpeed * Time.deltaTime, 0.0f);        
         }
         else if (Input.GetKey (KeyCode.UpArrow)) {
             Vector3 v3Axis = -Vector3.Cross (center.position - transform.position, transform.forward);
             center.rotation = Quaternion.AngleAxis(moveSpeed    * Time.deltaTime, v3Axis) * center.rotation;
         }
         else if (Input.GetKey (KeyCode.DownArrow)) {
             Vector3 v3Axis = Vector3.Cross (center.position - transform.position, transform.forward);
             center.rotation = Quaternion.AngleAxis(moveSpeed * Time.deltaTime, v3Axis) * center.rotation;
         }
     }
 }
Comment
Add comment · Show 2 · 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 cameo24 · Nov 15, 2013 at 07:20 AM 0
Share

Please see my update. I am trying to get an object to move around any surface, not just a perfect sphere so I don't want to hardcode it a certain distance away from the center of the sphere. thanks

avatar image robertbu · Nov 15, 2013 at 04:26 PM 0
Share

I've see two approaches to the problem of walking on arbitrary meshes. Both have issues. The first is to move the object on its local forward, raycast the direction of the local down of the object, then realign and reposition the object with the underlying mesh. The problem with this solution is transitions. As you cross a peak, your object often loses contact with the mesh and heads off into space (drawing). The other approach is to raycast towards some center of the object. This works well for sphere-like objects, but fails for many arbitrary meshes. There are ways of mitigating both problems, but I don't know of a perfect fix. In theory, you could align your character with the nearest triangle, but Unity does not give you built-in support for this calculation.

alt text

meshwalk.png (9.0 kB)

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

19 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

Related Questions

Is it better to make the Player in FPS be a Rigidbody or a characterController? 1 Answer

Object Rotating around center from Mouse Movement 1 Answer

Object rotating around object at two levels 1 Answer

Rotate a spawned object whith onmousedrag and move it with onmousedown 0 Answers

Two problems One code 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