Help with orbiting a fixed point

Hey, I’m playing about with controls for orbiting a fixed point, so for example I have a sphere which is my target as a sort of anchor point at 0,0,0 and a cube at 0,0 -10, what I’m wanting to to is when using WASD the cube can orbit the sphere 360 degrees and always remaining the same distance away. The problem I’m having is that my up down controls invert based on the positive or negative position of the cube, so at -Z the cube will go up and down but at +Z they switch to down up and the speed also changes based on the z position at +Z the speed goes really slow and at -Z the speed moves as set. I’m also using a more basic set of controls with if statements as I’m still getting used to unity and its also been quite a while since I last used c#.

My Code

using UnityEngine;
using System.Collections;

public class Cube: MonoBehaviour
{
  public GameObject target = null;
  public bool OrbitY = false; //Up/Down
  public bool OrbitX = false; //Left/Right
  public float speed = 0.5F;

  void Update ()
  {
  if (target != null)
  {
  transform.LookAt(target.transform);

  if (Input.GetKey(KeyCode.W) && OrbitY)
  {
  transform.RotateAround(target.transform.position, Vector3.left, speed);
  }

  if (Input.GetKey(KeyCode.A) && OrbitX)
  {
  transform.RotateAround(target.transform.position, Vector3.up, speed);
  }

  if (Input.GetKey(KeyCode.S) && OrbitY)
  {
  transform.RotateAround(target.transform.position, Vector3.right, speed);
  }

  if (Input.GetKey(KeyCode.D) && OrbitX)
  {
  transform.RotateAround(target.transform.position, Vector3.down, speed);
  }
  }
  }
  
}

So, the problems you are seeing are because you are always rotating around the world’s x-axis (that’s what Vector3.right and Vector3.left are). But since the cube always looks at the target, that means the cube has to turn around, which is why the controls seem backwards half the time.

What you really want to do is rotate around your own right/left axis, so instead of:

 transform.RotateAround(target.transform.position, Vector3.right, speed);

use

 transform.RotateAround(target.transform.position, transform.right, speed);

Here’s the whole script, I’ve re-organized the code a little to try and make in clearer for others, and I’ve added the use of deltaTime, so the orbit speed is now in degrees per second. Let me know if you have any questions about it:

using UnityEngine;
using System.Collections;

public class Cube : MonoBehaviour
{
    public GameObject target = null;
    public bool OrbitY = false; //Up/Down
    public bool OrbitX = false; //Left/Right
    public float speed = 180f; // degrees per second

    void Update()
    {
        if(target != null)
        {
            transform.LookAt(target.transform);

            if(OrbitY)
            {
                if(Input.GetKey(KeyCode.W))
                    transform.RotateAround(target.transform.position, transform.right, speed * Time.deltaTime);
                if(Input.GetKey(KeyCode.S))
                    transform.RotateAround(target.transform.position, -transform.right, speed * Time.deltaTime);
            }

            if(OrbitX)
            {
                if(Input.GetKey(KeyCode.A))
                    transform.RotateAround(target.transform.position, Vector3.up, speed * Time.deltaTime);
                if(Input.GetKey(KeyCode.D))
                    transform.RotateAround(target.transform.position, Vector3.down, speed * Time.deltaTime);
            }
        }
    }
}

Now, this is going to introduce a problem when you try and rotate over the north/south poles. As it rotates over the pole, the cube flips around, but because W/S always means up/down now, then it tries to go back and forth over the pole and just sticks there if you’re holding the up or down keys. There are solutions for this, but it would be better to know what exactly you’re trying to do before getting into that. For example, if this is for a camera, then you might not want the camera to get close to the poles, as going over the pole can be disorienting. So let me know if this helps and if you have any questions!

Thanks that worked really well, forgot to say that I have the camera as a child of the cube so the original idea was then for the camera to be able to orbit around the sphere 360 degrees at any angle, tho I did forget about that causing disorientation going over the poles. I’ve now attached the script to the sphere and made it a target of itself instead so that the sphere rotates 360 degrees on the spot with WASD. I now have the the cube moving up down left right with the mouse and clamped it to only move within so many degrees of the front of the sphere.

Here’s the code I used for the mouse movement, the movement is very juttery so I’m not sure if I’m implementing mathf.clamp correctly or not but I’m guessing the jumpyness is due to the cube attempting to go past the max/min values and jumping back to the allowed max/min limit. What would be the best way to have it stop smoothly once it hits its limit?

using UnityEngine;
using System.Collections;

public class Cube : MonoBehaviour
{
  public GameObject target = null;
  public bool OrbitY = false; //Up/Down
  public bool OrbitX = false; //Left/Right
  public float speed = 180.0f;

  void Update()
  {
  if (target != null)
  {
  transform.LookAt(target.transform);

  var xyrotation = transform.position;

  if (OrbitY)
  {
  if (Input.GetAxis("Mouse Y") > 0.0f)
  transform.RotateAround(target.transform.position, transform.right, speed * Time.deltaTime);
  if (Input.GetAxis("Mouse Y") < 0.0f)
  transform.RotateAround(target.transform.position, -transform.right, speed * Time.deltaTime);

  xyrotation.y = Mathf.Clamp(transform.position.y, -2.0f, 2.0f);
  transform.position = xyrotation;
  }

  if (OrbitX)
  {
  if (Input.GetAxis("Mouse X") > 0.0f)
  transform.RotateAround(target.transform.position, Vector3.up, speed * Time.deltaTime);
  if (Input.GetAxis("Mouse X") < 0.0f)
  transform.RotateAround(target.transform.position, Vector3.down, speed * Time.deltaTime);

  xyrotation.x = Mathf.Clamp(transform.position.x, -2.0f, 2.0f);
  transform.position = xyrotation;
  }
  }
  }

}

As for exactly what I’m trying to do I don’t really have any one idea at the minute and just experimenting around with various different types of control mechanics until I come up with some more ideas :stuck_out_tongue: