0
\$\begingroup\$

I am building a space game that I would like to be controlled in third person.

Basically I would like the camera and the ship to remain tied together and remain the same distance from each other but for the camera to remain in the same position relative to the ship from the world perspective. This position of the camera relative to the ship can only be altered by mouse movement and not by ship movements.

Example of the functionality required would be:

  • User can rotate the the ship on the x, y, z axis and the camera can observe these rotations
  • User can position the camera on the right side of the ship using mouse movements and activate thrusters to observe the ship in the center of the screen and the background objects passing
  • User can fly ship into an asteroid and observe rigidbody collider cause the ship to bounce back and start to rotate violently in a direction but the camera will remain stable and at a constant distance to the ship

Explanation from technical sense:

  • The camera must remain at (0,0,-100) from the ship in world coordinates and this position only changed using mouse movement using local position
  • Putting camera and ship in the same player object allows to control local coordinate to (0,0,-100) but from world perspective the positing of the camera to ship actually changes

Currently the main problem is that I can only either have the camera stuck in a constant position relative to the ship (cannot change perspective with mouse) OR I can change perspective with mouse but the rigitbody physics get applied to camera (if I hit an asteroid the camera rotates with the ship)

I also tried to use a dummy camera to track mouse movements and to just add it to the constant camera but when the ship rotated very quickly it wasn't very accurate.

Any suggestions for what I could use in order to get accurate response?

\$\endgroup\$
4
  • 1
    \$\begingroup\$ This question appears to be off-topic because it is about debugging your code for you. Could you describe more what you're trying to do and less how you're trying to do it? \$\endgroup\$
    – Anko
    Feb 12, 2014 at 13:40
  • \$\begingroup\$ Thanks, I updated the post. Let me know if you have any suggestions. \$\endgroup\$ Feb 12, 2014 at 20:52
  • \$\begingroup\$ I see a contradiction: It seems you'd like to have a camera that the player can freely rotate around a spaceship, like in this picture, but at the same time, you'd like the camera to rotate along with the ship. You can't have both, though you could could give each influence a different weight and calculate their influence based on those. Is that what you mean? \$\endgroup\$
    – Anko
    Feb 12, 2014 at 21:21
  • \$\begingroup\$ No, the camera should not rotate along with the ship, only around it while keeping consistent distance. \$\endgroup\$ Feb 13, 2014 at 1:26

1 Answer 1

1
\$\begingroup\$

I think that you need is this:

//Calculate the vector between the camera and the ship
Vector3 direction = shipRef.position - transform.position;
//Assigns the vector to the camera
transform.forward = direction;
//Calculate the projection vector
Vector3 vpp = shipRef.position - shipRef.forward * CameraDistanceFromShip;
//calculate the new direction of the camera
Vector3 direction2 = vpp - transform.position;
//Apply the movement
transform.position += direction2 * CameraVelocity * Time.deltaTime;

This script is attached to the camera. You don't need to make the camera child of the ship

///* EDITED *///

So, I found This Orbit Camera.

I converted to c#, I think it is what you want.

public Transform target;
public float distance = 10.0f;

public float xSpeed = 250.0f;
public float ySpeed = 120.0f;

public float yMinLimit = -20;
public float yMaxLimit = 80;

private float x = 0.0f;
private float y = 0.0f;


public float smoothTime = 0.3f;

private float xSmooth = 0.0f;
private float ySmooth = 0.0f; 
private float xVelocity = 0.0f;
private float yVelocity = 0.0f;

private Vector3 posSmooth = Vector3.zero;
private Vector3 posVelocity = Vector3.zero;

void Start ()
{
    Vector3 angles = transform.eulerAngles;
    x = angles.y;
    y = angles.x;

    // Make the rigid body not change rotation
    if (rigidbody)
        rigidbody.freezeRotation = true;
}

void Update()
{
    //Calculate the vector between the camera and the ship
    Vector3 direction = target.position - transform.position;
    //Assigns the vector to the camera
    transform.forward = direction;
    //Calculate the projection vector
    Vector3 vpp = target.position - target.forward;
    //calculate the new direction of the camera
    Vector3 direction2 = vpp - transform.position;
    //Apply the movement
    transform.position += direction2 * 5 * Time.deltaTime;
}

void LateUpdate ()
{
    if (target)
    {
        x += Input.GetAxis("Mouse X") * xSpeed * 0.02f;
        y -= Input.GetAxis("Mouse Y") * ySpeed * 0.02f;

        xSmooth = Mathf.SmoothDamp(xSmooth, (float) x, ref xVelocity, smoothTime);
        ySmooth = Mathf.SmoothDamp(ySmooth, (float) y, ref yVelocity, smoothTime);

        ySmooth = ClampAngle(ySmooth, yMinLimit, yMaxLimit);

        var rotation = Quaternion.Euler(ySmooth, xSmooth, 0);

        // posSmooth = Vector3.SmoothDamp(posSmooth,target.position,posVelocity,smoothTime);

        posSmooth = target.position; // no follow smoothing

        transform.rotation = rotation;
        transform.position = rotation * new Vector3(0.0f, 0.0f, -distance) + posSmooth;
    }
}

static float ClampAngle (float angle, float min, float max)
{
    if (angle < -360)
        angle += 360;
    if (angle > 360)
        angle -= 360;

    return Mathf.Clamp (angle, min, max);
}
\$\endgroup\$
2
  • \$\begingroup\$ How would you add mouse movement to the equation in order to allow it to rotate around the ship? i.imgur.com/kgWn0zs.png \$\endgroup\$ Feb 14, 2014 at 16:56
  • \$\begingroup\$ I edited my answer @RomanKhrystynych. See if it is what you want. \$\endgroup\$
    – Dyego
    Feb 15, 2014 at 19:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .