- Home /
Offset position to a target
Hello,
I am fairly new to Unity and muddling my way through. I am having trouble trying to position the camera to an offset position of its target. The code below puts the camera just behind the target and works well enough when translating. The problem I have is when rotating the object. I want the camera to remain in the offset position, based on the objects rotation.
While the camera stays with the target, if you rotate the camera position does not rotate with it (it should change the position of the camera based on the position and rotation of the target).
To put this in another context, think of missiles attached to the wings of a fighter craft which are offset to the fighter's body. When the fighter rotates I would want the missiles to stay attached, in the exact position, on the wings.
I hope this makes sense.
public class CameraView : MonoBehaviour {
public Transform target;
void Update() {
}
void LateUpdate () {
float pitchAngle = 0 * Mathf.Deg2Rad;
float yawAngle = 0 * Mathf.Deg2Rad;
float radius = 0;
float depth = -30;
transform.position = target.position + new Vector3(Mathf.Cos(pitchAngle + target.rotation.x),
Mathf.Sin(pitchAngle + target.rotation.y),
0) * radius;
transform.position = transform.position + new Vector3(0, 0,
Mathf.Cos(yawAngle + target.rotation.z)) * depth;
}
}
Answer by DaveA · Sep 22, 2011 at 11:09 PM
The easy thing would be to have the camera be a child of the object, then it will move/rotate with it. But short of that, if you want them separate, you could put an empty 'dummy' object there, and then in an Update function, read it's current world position/rotation and copy that to the camera's object's transform.
Parenting the camera to the player is the simplest way.
BUT if you don't want to:
Cam follows directly behind player (C#)
Vector3 baseOffset = new Vector3(x, y, z); // The offset you start with (cam postion - player position)
Vector3 staticOffset = Quaternion.AngleAxis(playerObj.transform.eulerAngles.y, Vector3.up) * baseOffset;
offset = staticOffset;
transform.position = playerObj.transform.position + offset;
transform.LookAt(playerObj.transform.position);
Answer by aldonaletto · Sep 22, 2011 at 11:33 PM
This will not work because you're using rotation components as if they were angles - and they aren't: rotation is a quaternion, and its (x y z w) components have nothing to do with the familiar angles we know. You should use localEulerAngles instead, but even this would not be the best way.
The easier way to do what you want is to child the camera to the target - it will follow the target position and rotation but always keeping its relative position and rotation. You can even rotate the camera if you want - child changes don't affect the parent object.
If you don't want to child the camera, however, use the target.forward vector as an initial reference, multiply by depth and apply a rotation based on your angles - that's your world displacement: add it to the target position and assign the result to the camera's position. You can just copy the target rotation to keep the camera aligned with the target direction.
public class CameraView : MonoBehaviour {
public Transform target;
void LateUpdate () { float pitchAngle = 0; float yawAngle = 0; float radius = 0; float depth = -30;
Vector3 displacement = target.forward * depth;
displacement = Quaternion.Euler(-pitchAngle, 0, -yawAngle) * displacement;
transform.position = target.position + displacement;
transform.rotation = target.rotation;
}
Answer by centaurianmudpig · Sep 23, 2011 at 03:34 PM
Thanks to both for your answers. I tried parenting the camera and it works for what I need.