- Home /
How do I translate around a circle?
Hello. First time posting here and fairly new to code. I'm working on a game and for one of the camera views I have an point oriented camera that I need to be able to rotate around that point. I need to do a Translate rather than a transform because of how the other coder has the terrain collider set up. The code below in an Update loop. My problem is with translating, it continues to spiral outward in the x and z coordinates. The y system works perfectly. I'm guessing I need to use Slerp or Lerp, but as I'm new to all of this, I need a little help.
Thanks.
if (camType == 1) {lastWorldCamPos=Camera.main.transform.position;
float length = Mathf.Cos(centerAng.y*0.0174532925f)*centerDist;
if (isLeftKeyDown) {
centerAng.x -= centRotSens;
// Avoid rotation below 0 degrees
while (centerAng.x < 0) {
centerAng.x = 360.0f - Mathf.Abs(centerAng.x);
}
dX=-Mathf.Cos(-centRotSens*0.0174532925f)*length;
dZ=Mathf.Sin(-centRotSens*0.0174532925f)*length;
Debug.Log(dX + " " + dY + " " + dZ + " " + length);
}
if (isRightKeyDown) {
centerAng.x += centRotSens;
// Avoid rotation above 360 degrees
while (centerAng.x > 360) {
centerAng.x = 0.0f + (Mathf.Abs(centerAng.x) - 360.0f);
}
dX=Mathf.Cos(centRotSens*0.0174532925f)*length;
dZ=-Mathf.Sin(centRotSens*0.0174532925f)*length;
Debug.Log(dX + " " + dY + " " + dZ + " " + length);
}
if (isUpKeyDown) {
centerAng.y += centPitSens;
// Avoid pitch above 90 degrees
if (centerAng.y > 90) {
centerAng.y = 90.0f;
}
dY=Mathf.Sin(centPitSens*0.0174532925f)*centerDist;
Debug.Log(dX + " " + dY + " " + dZ + " " + length);
}
if (isDownKeyDown) {
centerAng.y -= centPitSens;
// Avoid pitch below 0 degrees
if (centerAng.y < 0) {
centerAng.y = 0.0f;
}
dY=Mathf.Sin(-centPitSens*0.0174532925f)*centerDist;
Debug.Log(dX + " " + dY + " " + dZ + " " + length);
}
// Control zoom
if (Input.GetAxis("Mouse ScrollWheel")<0) {
centerDist += 20.0f;
if (centerDist > 2000) {
centerDist = 2000.0f;
}
}
if (Input.GetAxis("Mouse ScrollWheel")>0) {
centerDist -= 20.0f;
if (centerDist < 100) {
centerDist = 100.0f;
}
}
if (mouse1IsDown) {
// Listen for mouse x/y, change x/z center position depending on rotation angle
float transX = Input.GetAxis("Mouse X")*15.0f;
float transZ = Input.GetAxis("Mouse Y")*15.0f;
centerPos.x += Mathf.Sin(centerAng.x*0.0174532925f)*transX + Mathf.Cos(centerAng.x*0.0174532925f)*transZ;
centerPos.z += -Mathf.Cos(centerAng.x*0.0174532925f)*transX + Mathf.Sin(centerAng.x*0.0174532925f)*transZ;
}
Camera.main.transform.Translate(Vector3.up*dY,Camera.main.transform);
Camera.main.transform.Translate(Vector3.right*dX,Camera.main.transform);
Camera.main.transform.Translate(Vector3.forward*dZ,Camera.main.transform);
Camera.main.transform.LookAt(centerPos);
}
Answer by SikoraP13 · Mar 11, 2013 at 11:39 PM
I managed to solve the problem. I remade the code entirely using a Lerp function to modify the position if the old position was not the same as the new position and realized that making the camera position a camera rigidbody position change would prevent it from colliding with the terrain. I then turned on extrapolate in the rigidbody menu on the unity inspector. The code is included for anyone who's looking for it. This allows for both zoom and panning around the center point.
Thanks to everyone who tried to help out!
if (camType==1){
float length = Mathf.Cos(centerAng.y*0.0174532925f)*centerDist;
if ((isLeftKeyDown)&&(isMove=true)){
centerAng.x -= centRotSens;
// Avoid rotation below 0 degrees
while (centerAng.x < 0) {
centerAng.x = 360.0f - Mathf.Abs(centerAng.x);
}
}
if ((isRightKeyDown)&&(isMove=true)) {
centerAng.x += centRotSens;
// Avoid rotation above 360 degrees
while (centerAng.x > 360) {
centerAng.x = 0.0f + (Mathf.Abs(centerAng.x) - 360.0f);
}
}
if ((isUpKeyDown)&&(isMove=true)) {
centerAng.y += centPitSens;
// Avoid pitch above 90 degrees
if (centerAng.y > 90) {
centerAng.y = 90.0f;
}
}
if ((isDownKeyDown)&&(isMove=true)) {
centerAng.y -= centPitSens;
// Avoid pitch below 0 degrees
if (centerAng.y < 0) {
centerAng.y = 0.0f;
}
}
// Control zoom
if (Input.GetAxis("Mouse ScrollWheel")<0) {
centerDist += 20.0f;
if (centerDist > 2000) {
centerDist = 2000.0f;
}
}
if (Input.GetAxis("Mouse ScrollWheel")>0) {
centerDist -= 20.0f;
if (centerDist < 100) {
centerDist = 100.0f;
}
}
if (mouse1IsDown) {
// Listen for mouse x/y, change x/z center position depending on rotation angle
float transX = Input.GetAxis("Mouse X")*15.0f;
float transZ = Input.GetAxis("Mouse Y")*15.0f;
centerPos.x += Mathf.Sin(centerAng.x*0.0174532925f)*transX + Mathf.Cos(centerAng.x*0.0174532925f)*transZ;
centerPos.z += -Mathf.Cos(centerAng.x*0.0174532925f)*transX + Mathf.Sin(centerAng.x*0.0174532925f)*transZ;
}
// Convert centerPos, centerAng, centerDist to Camera position
float posX = centerPos.x+ Mathf.Cos(centerAng.x*0.0174532925f)*length;
float posZ = centerPos.z+ Mathf.Sin(centerAng.x*0.0174532925f)*length;
float posY = Mathf.Sin(centerAng.y*0.0174532925f)*centerDist+centerPos.y;
//Change Camera to a rigid body
Camera.main.transform.rigidbody.position=Vector3.Lerp(Camera.main.transform.position, new Vector3(posX,posY,posZ),60*Time.deltaTime);
Camera.main.transform.LookAt(centerPos);
}
That's a known, fragile hack. Rigidbodies are meant to move by setting their speed (various ways) and allowing the physics steps to move them.
BUT, any method that moves them 1) not-too-much, 2) from their current position (like your lerp, but Translate and many other ways) will sort of work on any collider+RB. As long as they never overlap too much, the physics step will pop them apart (the same way that overlapping cubes will when you press Play.)
Answer by DaveA · Mar 11, 2013 at 06:46 PM
Assets/Import package/Scripts Find Standard Assets/Camera Scripts/MouseOrbit. Drop that on your camera. Drop the target object on the target of that script.
Answer by Owen-Reynolds · Mar 11, 2013 at 08:40 PM
If this is non-standard enough that it can't be a predone orbit script...:
Translate is just a conveniance function to apply a local motion. It looks like you know exactly where you want to be (aimed at centerPos, offset by dX, dY and dZ based on the angles?) In that case, you can just put the camera there directly: Camera.main.transform.position = new Vector(centerPos.x+dx, ...);
.
The cos/sins could be replaced by a Quaternion times a vector, which does the math for you. All of the dx/y/z stuff would become something like: Vector3 fromCenter = Quaternion.Euler(xSpin, ySpin, 0)*Vector3.forwards;
Then, so I don't lose my license, consider using Mathf.Deg2Rad
instead of 0.017, or at least const float C1 = 0.017;
We had it working with a transform position, but with the way that the code is set up for the terrain collider, which uses OnCollision, the transform function allows it to go through the world. Here's the code for the collider that we're currently using. So essentially, it only works when there's an actual collision. For there to be a collision, to my understanding, it needs to be a Translate not a transform. I don't know enough about how Quaternions work, but any help on that would be appreciated.
void OnCollision(Collision collisionInfo) { Debug.Log("Collision Detected"); Camera.main.transform.Translate(collisionInfo.contacts[0].normal*5.0f); }
Translate
and position=
each go through solid objects, but will trigger OnCollision (but not if you teleport deep under a hill.)
But, to avoid an underground camera (is that the issue?) might be easier to look up the ground height.
That's the issue, yes. We've got a terrain generated. The camera needs to focus on and stay looking at a center point and be able to rotate 360 degrees around that point (X-Z plane) and up from 0 to 90 degrees on the Y axis. Currently the Y axis collision seems to work, but the X-Z plane collision doesn't work with the old transform code, essentially allowing the camera to fly through the side of a mountain.
Your answer
Follow this Question
Related Questions
Transition current camera rotation to 0,0,0 1 Answer
Changing camera position to shoot through scope on gun 1 Answer
Movement Smoothing Script not Working 2 Answers
Smooth Camera/Object Movement 1 Answer
[QuaternionSlerp] Lookback script 1 Answer