Rotate around the center of the world with Mouse

I am creating a rubik’s cube game for practice and I want to be able to freely rotate around the cube (located at the center of the world) by doing mouse click and drag.

I was using the mouse orb script but there are problems in that the left and right is backward when you are looking at the back of the cube.

Can someone point me towards the correct answer?

Try this - I adapted this from the 3D Buzz tutorial 3rd Person Character Controller. I can give you the full scripts if you want to include Y-axis movement.

  • EDIT : the below script now has X and Y mouse movement , and Z zoom with mouse scrollwheel =]

This needs a special setup to work. Create an empty gameObject , place it at (0,0,0) or where you want the camera to centre to. Then attach the following script to the camera.

Select the camera , in the inspector drag and drop the empty gameObject to “Target Look At”

Then when playing the scene , hold the right-mouse-button and you should be rotating around the empty gameObject =]

  • EDIT 2 : I want to clarify this is from an excellent tutorial by 3D Buzz in C#, I have simply converted it to unityJavaScript. (and moved a function to make one script)

Link : http://www.3dbuzz.com/vbforum/content.php?212

At the end of Section 2, you get this free-roaming Camera Controller, with many customizable settings (check all the public vars, or in the Inspector).

Finish Section 3 , and you’ll have a cool Camera controller that can also check for collisions and occlusions.

SO if you have any questions on this, go to the 3D Buzz above link and do the tutorial. The blackboard theory sessions are good enough alone as a resource and insight to how some things can be done with coding.

Many thanks again Zak and Lee (I already p.m.'d them to say thanks, really enjoyed the tutorial =] )

More on the camera : to adjust the camera’s TargetLookAt point , you could put a script on the empty gameObject this script is looking at , and move it or attach it to other gameObjects. Or you can reform the script back to a class (or Singleton for using just one camera), then call on it’s Instance and change the transform stored in the TargetLookAt var that way. Definitely , check the original 'site =]

now the script :

#pragma strict

public var TargetLookAt : Transform;

public var Distance : float = 5.0;
public var DistanceMin : float = 3.0;
public var DistanceMax : float = 10.0;	
private var mouseX : float = 0.0;
private var mouseY : float = 0.0;
private var startingDistance : float = 0.0;	
private var desiredDistance : float = 0.0;	
public var X_MouseSensitivity : float = 5.0;
public var Y_MouseSensitivity : float = 5.0;
public var MouseWheelSensitivity : float = 5.0;
public var Y_MinLimit : float = -40.0;
public var Y_MaxLimit : float = 80.0;	
public var DistanceSmooth : float = 0.05;	
private var velocityDistance : float = 0.0;	
private var desiredPosition : Vector3 = Vector3.zero;	
public var X_Smooth : float = 0.05;
public var Y_Smooth : float = 0.1;
private var velX : float = 0.0;
private var velY : float = 0.0;
private var velZ : float = 0.0;
private var position : Vector3 = Vector3.zero;	

function Start() 
{
	Distance = Mathf.Clamp(Distance, DistanceMin, DistanceMax);
	startingDistance = Distance;
	Reset();
}

function LateUpdate()
{
	if (TargetLookAt == null)
		return;
		
	HandlePlayerInput();
		
	CalculateDesiredPosition();
		
	UpdatePosition();
}

function HandlePlayerInput()
{
	var deadZone = 0.01; // mousewheel deadZone
	
	if (Input.GetMouseButton(1))
	{
		mouseX += Input.GetAxis("Mouse X") * X_MouseSensitivity;
		mouseY -= Input.GetAxis("Mouse Y") * Y_MouseSensitivity;
	}
	
	// this is where the mouseY is limited - Helper script
	mouseY = ClampAngle(mouseY, Y_MinLimit, Y_MaxLimit);
	
	// get Mouse Wheel Input
	if (Input.GetAxis("Mouse ScrollWheel") < -deadZone || Input.GetAxis("Mouse ScrollWheel") > deadZone)
	{
		desiredDistance = Mathf.Clamp(Distance - (Input.GetAxis("Mouse ScrollWheel") * MouseWheelSensitivity), 
																			DistanceMin, DistanceMax);
	}
}

function CalculateDesiredPosition()
{
	// Evaluate distance
	Distance = Mathf.SmoothDamp(Distance, desiredDistance, velocityDistance, DistanceSmooth);
	
	// Calculate desired position -> Note : mouse inputs reversed to align to WorldSpace Axis
	desiredPosition = CalculatePosition(mouseY, mouseX, Distance);
}

function CalculatePosition(rotationX : float, rotationY : float, distance : float)
{
	var direction : Vector3 = Vector3(0, 0, -distance);
	var rotation : Quaternion = Quaternion.Euler(rotationX, rotationY, 0);
	return TargetLookAt.position + (rotation * direction);
}

function UpdatePosition()
{
	var posX = Mathf.SmoothDamp(position.x, desiredPosition.x, velX, X_Smooth);
	var posY = Mathf.SmoothDamp(position.y, desiredPosition.y, velY, Y_Smooth);
	var posZ = Mathf.SmoothDamp(position.z, desiredPosition.z, velZ, X_Smooth);
	position = Vector3(posX, posY, posZ);
	
	transform.position = position;
	
	transform.LookAt(TargetLookAt);
}

function Reset() 
{
	mouseX = 0;
	mouseY = 10;
	Distance = startingDistance;
	desiredDistance = Distance;
}

function ClampAngle(angle : float, min : float, max : float)
{
	while (angle < -360 || angle > 360)
	{
		if (angle < -360)
			angle += 360;
		if (angle > 360)
			angle -= 360;
	}
	
	return Mathf.Clamp(angle, min, max);
}

If you’re wanting to rotate the world for effect, I’d use the horizontal mouse drag to rotate the world around the cube, and use the mouse drag vertical axis to rotate the cube itself vertically (top to bottom)

Depending on your scenery and view, it would give you a nice omni-orbital effect as you panned around the cube and would flip the cube around with vertical movement much like a real world object.

It would make the view less confusing and give the player a lot more play with the view.

I thought about rotating the cube instead of the world and I may still try that. I just want to make sure that when I get to the step of actually rotating the individual slices, I don’t over complicate that part.

Justin, I don’t full understand your response. I believe that is what the standard orb script is doing. Maybe I misunderstood.

BTW, I attached a screen shot to show the cube.[784-rubiks.jpg|784]

@hiTo: that might fix my immediate problem, but when I go to actually rotate the individual slices, I feel like it would over complicate things.

@JustinMyers: I am not sure I understand your solution or at least I dont see how that is different than what I am doing? Can you please explain?

I attached a screen shot just to make sure we are on the same page.[785-rubiks.jpg|785]

Just add a single empty GameObject as a parent to all the small cubes. Make sure it’s in the center. Then just rotate that transform. Everything else will follow smoothly.

In Update.
affectedObject - object you whant to rotate.

Ray ray = camera.ScreenPointToRay (Input.mousePosition);
    RaycastHit hit = new RaycastHit();
    if (Physics.Raycast (ray, out hit))
    {
        Vector3 rot = affectedObject.transform.eulerAngles;
        affectedObject.transform.LookAt(hit.point);
        affectedObject.transform.eulerAngles = new Vector3(rot.x, affectedObject.transform.eulerAngles.y, rot.z);
    }