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
1
Question by Tyler 2 · Jan 03, 2011 at 06:26 AM · movementspherical

How can I make movement on a sphere?

Hello. I want to make a game like Super Stardust HD.

Super Stardust HD screenshot
Super Stardust HD

The game takes place on a large sphere that the player travels around. But the trick is, the player doesnt actually move, they spaceship is always in the same place, everything else just rotates. I have scripts for things like the movement, firing, etc. but I cannot figure out how to create the illusion of moving around the sphere (currently the movement is just on a 2D plane like geometry wars, etc., and it cannot be on a sphere for obvious physics reasons).

How would I create (or at least create the illusion of) a sphere that the player can move around?
Thanks.

Comment
Add comment · Show 3
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 Anton Petrov · Jan 03, 2011 at 06:37 AM 0
Share

can you just create a sphere? or your world is large while the sphere is obviously smaller?

avatar image Proclyon · Jan 03, 2011 at 08:56 AM 0
Share

sounds like the bonus level in the 3rd sonic game on the genesis. Something like that?

avatar image Peter G · Jan 08, 2011 at 01:47 PM 0
Share

I'm not sure what obvious reason that it cannot be on a sphere. I guess you are referring to the fact that gravity only pulls down in Physx, but it is much easier than it sounds to add spherical gravity. The trickier part is aligning the object with the spheres normal, or if you are on a perfectly rounds sphere, you can do some trig to get the angle of rotation.

4 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer Wiki

Answer by Statement · Jan 08, 2011 at 12:25 PM

I thought it was a fun thing to attempt to create from scratch. Here's my stab at it.
In my scene, I set up a sphere and a cube such that the cube is parented to the sphere and that the cube has 0.1 scale. Then I apply the script to the cube. Now you can control it running along the sphere.

It works like having a 2d coordinate system but instead of dealing with vectors, we're dealing with quaternions. I use a float angle to determine which way the player is facing on the sphere and then rotate the player around the midpoint of the planet in the direction expressed by cos angle and sin angle. Sideways movement is achieved by taking the perpendicular vector and rotating with respect to that axis.

It can feel a bit daunting at first but if you just look at the functions one at a time, you'll see there isn't too much wierd stuff going on. My hardest problem was figuring out the proper up and forward vector so I can rotate the object properly (without up vector, the object would flip 180 degrees at some places). :)

Script in action with bullets Script in action with bullets.

With trails! Bullets with trail particles.

Here is my game object hierarchy with annotations:

  • Sphere [Scale 1]
    • Cube [Scale 0.1] [SphericController]
      • Camera (Looking down at Cube)

List of controls:

  • Up - Go forward.

  • Down - Go backward.

  • Left - Rotate left.

  • Right - Rotate right.

  • A - Go left.

  • D - Go right.

  • Left Control - Shoot.

Controller

 using UnityEngine;
 
 public class SphericController : MonoBehaviour
 {
     public SphericProjectile prefab;
 
     public float radius = 0.6f;
     public float translateSpeed = 180.0f;
     public float rotateSpeed = 360.0f;
     public float fireInterval = 0.05f;
 
     float angle = 0.0f;
     Vector3 direction = Vector3.one;
     Quaternion rotation = Quaternion.identity;
 
     void Fire()
     {
         var clone = (SphericProjectile)Instantiate(prefab);
         clone.transform.position = transform.position;
         clone.transform.rotation = transform.rotation;
         clone.transform.parent = transform.parent;
         clone.angle = angle;
         clone.rotation = rotation;
     }
 
     void Update()    
     {
         direction = new Vector3(Mathf.Sin(angle), Mathf.Cos(angle));
 
         // Fire bullet code
         if (Input.GetKeyDown(KeyCode.LeftControl))
             InvokeRepeating("Fire", float.Epsilon, fireInterval);
         if (Input.GetKeyUp(KeyCode.LeftControl))
             CancelInvoke("Fire");
 
         // Rotate with left/right arrows
         if (Input.GetKey(KeyCode.LeftArrow))  Rotate( rotateSpeed);
         if (Input.GetKey(KeyCode.RightArrow)) Rotate(-rotateSpeed);
 
         // Translate forward/backward with up/down arrows
         if (Input.GetKey(KeyCode.UpArrow))    Translate(0,  translateSpeed);
         if (Input.GetKey(KeyCode.DownArrow))  Translate(0, -translateSpeed);
 
         // Translate left/right with A/D. Bad keys but quick test.
         if (Input.GetKey(KeyCode.A))          Translate( translateSpeed, 0);
         if (Input.GetKey(KeyCode.D))          Translate(-translateSpeed, 0);
 
         UpdatePositionRotation();
     }
 
     void Rotate(float amount)
     {
         angle += amount * Mathf.Deg2Rad * Time.deltaTime;
     }
 
     void Translate(float x, float y)
     {
         var perpendicular = new Vector3(-direction.y, direction.x);
         var verticalRotation = Quaternion.AngleAxis(y * Time.deltaTime, perpendicular);
         var horizontalRotation = Quaternion.AngleAxis(x * Time.deltaTime, direction);
         rotation *= horizontalRotation * verticalRotation;
     }
 
     void UpdatePositionRotation()
     {
         transform.localPosition = rotation * Vector3.forward * radius;
         transform.rotation = rotation * Quaternion.LookRotation(direction, Vector3.forward);
     }
 }

Projectile

 using UnityEngine;
 
 public class SphericProjectile : MonoBehaviour
 {
     public float radius = 0.6f;
     public float translateSpeed = 270.0f;
     public float angle = 0.0f;
     public Quaternion rotation = Quaternion.identity;
 
     Vector3 direction = Vector3.one;
 
     void Start()
     {
         Destroy(gameObject, 1.0f);
     }
 
     void Update()
     {
         direction = new Vector3(Mathf.Sin(angle), Mathf.Cos(angle));
         Translate(0, translateSpeed);
         UpdatePositionRotation();
     }
 
     void Translate(float x, float y)
     {
         var perpendicular = new Vector3(-direction.y, direction.x);
         var verticalRotation = Quaternion.AngleAxis(y * Time.deltaTime, perpendicular);
         var horizontalRotation = Quaternion.AngleAxis(x * Time.deltaTime, direction);
         rotation *= horizontalRotation * verticalRotation;
     }
 
     void UpdatePositionRotation()
     {
         transform.localPosition = rotation * Vector3.forward * radius;
         transform.rotation = rotation * Quaternion.LookRotation(direction, Vector3.forward);
     }
 }
Comment
Add comment · Show 7 · 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 Statement · Jan 08, 2011 at 07:35 PM 0
Share

Apparently I checked "community wiki" and so no rep is awarded. sob sob :)

avatar image Peter G · Jan 09, 2011 at 01:06 PM 0
Share

After 8 revisions I believe it becomes a community wiki.

avatar image Statement · Jan 09, 2011 at 01:28 PM 0
Share

That explains a lot.

avatar image zombience · Mar 07, 2014 at 05:11 PM 0
Share

Hey so, I updated your script to work for a first person camera walking on a planet. $$anonymous$$ove and Rotate speed are variable, and I've included jumping with variable "gravity".

The planet must be its own transform with a collider, and the Camera must be the child of an empty game object that is in the same location as the planet. I made this for fairly large planets (I tested it on a standard sphere with a scale of 1500).

Hope someone finds this useful. I'll probably post it on the unify wiki as well.

 using UnityEngine;
 using System.Collections;
 
 public class SphereNavigator : $$anonymous$$onoBehaviour 
 {
     #region vars
     public float rotSpeed;
     public float moveSpeed;
     public float rotDamp;
     public float moveDamp;
     public float height;
     public float jumpHeight;
     [Range(.1f, 10f)]
     public float gravity;
     public float radius;
 
     public Transform planet;
     protected Transform trans;
     protected Transform parent;
 
     protected float angle = 90f;
     public float curJumpHeight = 0;
     protected float jumpTimer;
     protected bool jumping;
 
 
 
     protected Vector3 direction;
     protected Quaternion rotation = Quaternion.identity;
 
     #endregion
     
     #region Unity methods
     void Start () 
     {    
         trans = transform;
         parent = transform.parent;
     }
     
     void Update () 
     {
 
         //parent.position = planet.position; // If you want to have a moving planet
 
         direction = new Vector3($$anonymous$$athf.Sin(angle), $$anonymous$$athf.Cos(angle));
 
         if(Input.Get$$anonymous$$ey($$anonymous$$eyCode.LeftShift))
             Position(Input.GetAxis("Horizontal") * -moveSpeed, 0);
         else
             Rotation(Input.GetAxis("Horizontal") * -rotSpeed);
 
         if(Input.GetButtonDown("Jump") && !jumping)
         {
             jumping = true;
             jumpTimer = Time.time;
         }
 
         if(jumping)
         {
             curJumpHeight = $$anonymous$$athf.Sin((Time.time - jumpTimer) * gravity) * jumpHeight; 
             if(curJumpHeight <= -.01f)
             {
                 curJumpHeight = 0;
                 jumping = false;
             }
         }
 
         Position (0, Input.GetAxis("Vertical") * moveSpeed);
         $$anonymous$$ovement();
     }
     #endregion
 
     #region Actions
     protected void Rotation(float amt)
     {
         angle += amt * $$anonymous$$athf.Deg2Rad * Time.fixedDeltaTime;
     }
 
     protected void Position(float x, float y)
     {
         Vector2 perpendicular = new Vector2(-direction.y, direction.x);
         Quaternion vRot = Quaternion.AngleAxis(y, perpendicular);
         Quaternion hRot = Quaternion.AngleAxis(x, direction);
         rotation *= hRot * vRot;
     }
 
     protected void $$anonymous$$ovement()
     {
         trans.localPosition = Vector3.Lerp(trans.localPosition, rotation * Vector3.forward * GetHeight(), Time.fixedDeltaTime * moveDamp);
         trans.rotation = Quaternion.Lerp(trans.rotation, rotation * Quaternion.LookRotation(direction, Vector3.forward), Time.fixedDeltaTime * rotDamp);
     }
 
     protected float GetHeight()
     {
         Ray ray = new Ray(trans.position, planet.position - trans.position);
         RaycastHit hit;
 
         if(Physics.Raycast(ray, out hit))
             radius = Vector3.Distance(planet.position, hit.point) + height + curJumpHeight;
 
         return radius;
     }
 
     #endregion
 }
 
avatar image zombience · Mar 07, 2014 at 05:14 PM 0
Share

oh, also i included raycasting, so it can work on irregular shaped planets as well. for example, you may have small hills or a low-poly style planet. large mountains won't work well, however, because the camera always orients to the center of the planet rather than approximating the normal of the ground beneath your feet.

Show more comments
avatar image
3

Answer by Jesse Anders · Jan 03, 2011 at 09:00 AM

Why do you think the player doesn't move? That seems unlikely to me. I'd be willing to bet the player does move, and that the camera simply adjusts so as to keep the player at the center of the screen.

Also, I doubt it's an illusion per se. I think it's more likely that the player and other game entities actually do move around the surface of the sphere in a more or less physically correct manner. (Keep in mind though that I'm just speculating - I haven't played the game, and I don't know for sure how it's implemented.)

As for moving on the surface of a sphere, this is discussed fairly frequently on the forums. The basic idea is:

  • Translate the player the desired direction and distance (tangent to the sphere)

  • Move the player to the closest point on the sphere to the player

  • Correctively align the player with the normal to the sphere at that point

Another option would be to actually move the player 'correctly' along an arc on the sphere's surface (I haven't tried that method myself though).

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 Statement · Jan 08, 2011 at 02:10 PM 0
Share

Yeah I doubt the scene moves according to the player but hey! We live in a relativistic world! :) I managed to solve the problem without having to toss around the scene. I did parent the camera to the player, so it appears as if the world revolves around the player. (History repeats itself).

avatar image DaveA · Jan 08, 2011 at 07:22 PM 0
Share

Yeah that sounds good

avatar image deathripper · Mar 25, 2015 at 10:32 AM 0
Share

I have a question regarding the script mentioned above. I tried it out and it worked quit nice, however if I spawn a character using Unitys "Random.onUnitSphere" the player was reset to position 0,0. I figured out that the reason for that was the rotation variable.

Random.onUnitSphere seems to give me a Vector3, is there a way I can use that Vector3 in order to calculate the right Quaternion for the rotation variable ?

avatar image
0

Answer by DaveA · Jan 08, 2011 at 07:21 PM

What if you put all the world (except the ship or character) under one game object, call it 'world' and rotate that? The ship or character would not be moving but everything else would.

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 Jesse Anders · Jan 08, 2011 at 07:30 PM 0
Share

I think what it comes down to is, what's the point in doing that? What does it gain you over simply moving the ship/character itself and letting stationary objects be stationary?

avatar image burtonposey · Jan 08, 2013 at 07:49 PM 0
Share

I started my game doing this as well (rotating the world and leaving the character stationary), but you lose the ability to mark any of that stuff as static, which is a big loss for performance.

I ended up doing the opposite. Everything is marked static in the environment that isn't animating and I have the game camera following the character.

avatar image
0

Answer by deathripper · Mar 27, 2015 at 10:20 AM

I have a question regarding the script mentioned above. I tried it out and it worked quit nice, however if I spawn a character using Unitys "Random.onUnitSphere" the player was reset to position 0,0. I figured out that the reason for that was the rotation variable.

Random.onUnitSphere seems to give me a Vector3, and rotation needs a Quaternion. Is there a way I can use that Vector3 in order to calculate the right Quaternion for the rotation variable ?

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Make one GameObject look at, move toward another across a sphere 1 Answer

"Chasing" object around a sphere 0 Answers

The name 'Joystick' does not denote a valid type ('not found') 2 Answers

Making a bubble level (not a game but work tool) 1 Answer

Why does my character only dash forward and not in the moving direction? 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