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?

Why not just rotate the cube itself? Seems like a much easier solution.

Yeah, it's kind of a big problem that you can't just flip a few buttons and switch from Baked to Precomputed Realtime and get the same illumination, especially since Baked lighting takes forever to fully bake.

6 Answers

6

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);
}

seriously try this , you'll be amazed! I just uploaded a webpublish to demonstrate : http://www.alucardj.net16.net/unityanswers/RotateCamAround.html and the script on the camera (as above) : http://www.alucardj.net16.net/unityanswers/RotateCamAtOrigin.js

This script works extremely well! Is it possible to make it work with Windows 7 touchscreen computers? When I try the zoom feature works, but it doesn't allow me to rotate?

I have never coded for a Win7 touchscreen sorry. But if it is anything like coding for iOS, then the method HandlePlayerInput() would need to be rewritten for touch input. For example, detect any changes in touch position. Set the difference (the touch delta) to mouseX and mouseY. But that leaves me curious how the zoom works, again have never seen a win7 touch device. http://docs.unity3d.com/Documentation/ScriptReference/Input.html

Hi! I know this is incredibly old, but: I need something like this, but is there any way to do this without keeping the object in the center (not being able to move the camera) I have a big grid where you can place blocks (it is 3d) I want to be able to orbit around and zoom in, and this script works perfectly for it. Although i have another script that moves the camera with WASD, and it will not move, probably because this script ties it to that one gameobject in the center. Is there any way to modify this script for my needs?

Absolutely, just use your WASD script to move the CameraTarget. This came from a project where the CameraTarget was parented to the 3rd person player character (in his head) so as the player walked around, the CameraTarget moved also. So you do not need to modify this script at all, just move the CameraTarget around =]

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);
    }