- Home /
Smooth Orbit Round Object with Adjustable Orbit Radius
Hi,
I am trying to assign an object to rotate around another object and to be able to adjust the orbit radius. Also when the radius changes I am trying to get the object to smoothly adjust to the new orbit radius.
I've been searching for a while now and only had limited success. The best I have found is:
rotateTransform.RotateAround (objectToOrbit.position, Vector3.up, orbitAmount * Time.deltaTime);
But this does not allow me to change the actual radius. The orbitAmount value simply speeds up or down the orbit.
It does seems that RotateAround works with the initial distance from the object I want to rotate around and sets it as that, but I can't think of a way to exploit that fact.
Any suggestions on how to go about this?
Thanks
Paul
Answer by robertbu · May 27, 2013 at 01:32 AM
Here is a bit of code:
#pragma strict
public var center : Transform;
public var axis : Vector3 = Vector3.up;
public var radius = 2.0;
public var radiusSpeed = 0.5;
public var rotationSpeed = 80.0;
function Start() {
transform.position = (transform.position - center.position).normalized * radius + center.position;
}
function Update() {
transform.RotateAround (center.position, axis, rotationSpeed * Time.deltaTime);
var desiredPosition = (transform.position - center.position).normalized * radius + center.position;
transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * radiusSpeed);
}
Perfect Roberbu! And I am sure the C# conversion will be appreciated by others Le$$anonymous$$oine :)
I'll be looking more into normalized today after seeing it in use like that.
Thanks guys!
Just to share with everyone else, here is a modified version which makes the orbiting object face in the direction of travel, and to gradually move into the orbit from any position on start. I have also tried to implement good coding practice as I imagine people will just cut and paste this. Also just to clarify, I know that robertbu would have done the same, but obviously he was just throwing a quick example into the mix (thanks again robetbu!). Right here is the code:
#pragma strict
var objectToOrbit : Transform; //Object To Orbit
var orbitAxis : Vector3 = Vector3.up; //Which vector to use for Orbit
var orbitRadius : float = 75.0; //Orbit Radius
var orbitRadiusCorrectionSpeed : float = 0.5; //How quickly the object moves to new position
var orbitRoationSpeed : float = 10.0; //Speed Of Rotation arround object
var orbitAlignToDirectionSpeed : float = 0.5; //Realign speed to direction of travel
private var orbitDesiredPosition : Vector3;
private var previousPosition : Vector3;
private var relativePos : Vector3;
private var rotation : Quaternion;
private var thisTransform : Transform;
//---------------------------------------------------------------------------------------------------------------------
function Start() {
thisTransform = transform;
}
//---------------------------------------------------------------------------------------------------------------------
function Update() {
//$$anonymous$$ovement
thisTransform.RotateAround (objectToOrbit.position, orbitAxis, orbitRoationSpeed * Time.deltaTime);
orbitDesiredPosition = (thisTransform.position - objectToOrbit.position).normalized * orbitRadius + objectToOrbit.position;
thisTransform.position = Vector3.Slerp(thisTransform.position, orbitDesiredPosition, Time.deltaTime * orbitRadiusCorrectionSpeed);
//Rotation
relativePos = thisTransform.position - previousPosition;
rotation = Quaternion.LookRotation(relativePos);
thisTransform.rotation = Quaternion.Slerp(thisTransform.rotation, rotation, orbitAlignToDirectionSpeed * Time.deltaTime);
previousPosition = thisTransform.position;
}
@robertbu i don't really understand what the radiusSpeed is doing here. Is it simply making it lag from where it's supposed to be ?
The reason i ask is because i'm trying to make an object orbit an object that is orbiting something else (the moon orbiting the earth) and the position is not updating correctly. This post seems to have identified why.
I think if i remove the radiusSpeed then I have the solution I need?
Answer by LeMoine · May 27, 2013 at 02:58 AM
Wow, works perfectly! here is in C#, tested with a cube as the center of rotation :
using UnityEngine;
using System.Collections;
public class testRotate2 : MonoBehaviour {
GameObject cube;
public Transform center;
public Vector3 axis = Vector3.up;
public Vector3 desiredPosition;
public float radius = 2.0f;
public float radiusSpeed = 0.5f;
public float rotationSpeed = 80.0f;
void Start () {
cube = GameObject.FindWithTag("Cube");
center = cube.transform;
transform.position = (transform.position - center.position).normalized * radius + center.position;
radius = 2.0f;
}
void Update () {
transform.RotateAround (center.position, axis, rotationSpeed * Time.deltaTime);
desiredPosition = (transform.position - center.position).normalized * radius + center.position;
transform.position = Vector3.MoveTowards(transform.position, desiredPosition, Time.deltaTime * radiusSpeed);
}
}
If I could thumb up, I would really!
Hmm, I think I need more $$anonymous$$arma to be able to close a topic. I can't see any checkmark next to the answers and I can't vote up your answer :'(
Hi guys. It's my question lol! The answers look great and I will be checking them out in a few hours. As soon as I have I'll mark the question/answers accordingly. In the mean time have some up votes :)
Here is a face-towards-movement-direction-rotation if needed:
Vector3 tangentVector = Quaternion.Euler(0, 90,0) * (transform.position -
center.position);
transform.rotation = Quaternion.LookRotation (tangentVector);
Answer by aaronov · May 27, 2013 at 12:15 AM
You will probably need to use something like Mathf.SmoothStep to smooth the rotation angle argument of RotateAround and Transform.Translate to configure the distance (radius) between the two objects prior to applying rotation.
using FixedUpdate seemed to smooth out some of the choppiness, at least for me.
Answer by ssshake · Jan 06, 2014 at 06:25 AM
I noticed that the objects are jittery using this script but if you change update to fixedupdate it's smooth
Answer by deadshot · Oct 22, 2014 at 05:38 AM
using UnityEngine;
using UnityEngine;
using System.Collections;
//[AddComponentMenu("Camera-Control/Mouse drag Orbit with zoom")]
public class rotateonmouse : MonoBehaviour
{
public Transform target;
public float distance = 5.0f;
public float xSpeed = 120.0f;
public float ySpeed = 120.0f;
public float yMinLimit = -20f;
public float yMaxLimit = 80f;
public float distanceMin = .5f;
public float distanceMax = 15f;
public float smoothTime = 2f;
float rotationYAxis = 0.0f;
float rotationXAxis = 0.0f;
float velocityX = 0.0f;
float velocityY = 0.0f;
// Use this for initialization
void Start()
{
Vector3 angles = transform.eulerAngles;
rotationYAxis = angles.y;
rotationXAxis = angles.x;
// Make the rigid body not change rotation
if (rigidbody)
{
rigidbody.freezeRotation = true;
}
}
void LateUpdate()
{
if (target)
{
if (Input.GetMouseButton(1))
{
velocityX += xSpeed * Input.GetAxis("Mouse X") * 0.02f;
velocityY += ySpeed * Input.GetAxis("Mouse Y") * 0.02f;
}
rotationYAxis += velocityX;
rotationXAxis -= velocityY;
rotationXAxis = ClampAngle(rotationXAxis, yMinLimit, yMaxLimit);
Quaternion fromRotation = Quaternion.Euler(transform.rotation.eulerAngles.x, transform.rotation.eulerAngles.y, 0);
Quaternion toRotation = Quaternion.Euler(rotationXAxis, rotationYAxis, 0);
Quaternion rotation = toRotation;
Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
Vector3 position = rotation * negDistance + target.position;
transform.rotation = rotation;
transform.position = position;
velocityX = Mathf.Lerp(velocityX, 0, Time.deltaTime * smoothTime);
velocityY = Mathf.Lerp(velocityY, 0, Time.deltaTime * smoothTime);
}
}
public static float ClampAngle(float angle, float min, float max)
{
if (angle < -360F)
angle += 360F;
if (angle > 360F)
angle -= 360F;
return Mathf.Clamp(angle, min, max);
}
}
this should do it. It allows to set the max/min distance and the distance you want.
I've implemented your code into a prototype I'm working on, and when I run it the camera goes zoo$$anonymous$$g away in the negative z direction. This also happens when I try to use other mouse orbit examples around here. Is there anything obvious that I might be doing wrong?
fantastic script! best one out there!!
I've added distance control with mouse wheel, I've not added a new specific smooth value for distance but should be a breeze to add if needed. Really love your script.