The simplest orbit camera that can be made in C#

I am using a pre-made asset, but it is too big and has features that I do not really need.

I need to be able to rotate the camera with the mouse button pressed, and scroll when hitting the borders with the pointer. I can live without the scrolling part, using the keyboard to move in the 4 directions.
Last but not least; zoom in and out.

Would this be enough to make an orbit camera? I am looking for the smallest implementation possible, so I can minimize the codebase and the footprint of the application (less code, less bugs!).

Since I never wrote a camera from scratch; I am not sure if I am missing something or not. Would be great if Unity would add a prefab in its standard assets, to cover such case :slight_smile:

I think I have something that does what I need.

The only issue that I have is that the camera, when at an angle (say 25 on X axis), when I move forward, after a rotation; it continue to move to where the “forward” is, instead than the “forward” of the object. To fix this I do a translate using Space.Self.

The downside is that if I move the camera forward now, it will act like the zoom.

How do you tell the camera, to move on the X and Z axis, so it act like if the camera is nailed to the ceiling of a room, but at the same time, if there is a rotation, say 90 degree on X, when I go forward , it should follow forward, relative to where the camera is pointing at.

I am aiming at a standard Orbit camera, exactly like a standard RTS (C&C).

There’s an exact implementation in my book; maybe later I’ll be able to post the entire explanation here. In the meantime, the most important part is that you aren’t moving the camera directly when you press forward; instead, move the object it is orbiting around. That of couse means there should be an object (possibly an empty gameobject) that the camera is attached to.

3 Likes

Thanks; I didn’t know that there was a difference between moving the camera itself and when it is the child of another GO.

I will try in that way and see if I can get something that fit my need; Thanks!

So the tip is correct :slight_smile: creating an empty object, you have to reset to 0 though; in this way when I move forward, it will be parallel to the ground plane.
Once I set the camera as child, I can change rotation and inclination of the camera viewpoint, and it will move as expected. Thanks!

This is the whole script, in case someone may find it useful.

using UnityEngine;

public class RtsCamera : MonoBehaviour
{

    public float speed = 2.0f;                  // movement speed when scrolling on the side of the screen
    public float zoom_speed = 2.0f;             // zoom speed
    public float speed_x = 200.0f;              // Rotation speed
    float rotation_y = 0.0f;                    // variable used for rotation function
    private int edge_threshold = 5;             // area before the end of the screen where scrolling activate
    // limits
    public float scroll_limit_x = 5f;                // how much you can scroll from the center of the scene on the X axis.
    public float scroll_limit_z = 5f;                // how much you can scroll from the center of the screen on the Y axis.


    void Start()
    {
        // adapt the limits based on the starting position of the camera.
        // in this way, there will always be an equal amount to the limit value
        // independently from where the starting position is.
        if (transform.position.x > 0)
            scroll_limit_x += transform.position.x;
        else
            scroll_limit_x -= transform.position.x;

        if (transform.position.z > 0)
            scroll_limit_z += transform.position.z;
        else
            scroll_limit_z -= transform.position.z;
    }

    void Update()
    {
        float scrollwheel = Input.GetAxis("Mouse ScrollWheel");
        float mouse_x = Input.mousePosition.x;
        float mouse_y = Input.mousePosition.y;

        //zoom with scroll wheel; forward to zoom in, backward to scroll out.
        transform.Translate(0, -scrollwheel * zoom_speed, scrollwheel * zoom_speed, Space.World);

        // Orbit function using right mouse button pressed.
        if (Input.GetMouseButton(1))
        {
            rotation_y += Input.GetAxis("Mouse X") * speed_x * Time.deltaTime;
            transform.localEulerAngles = new Vector3(0, rotation_y, 0);
        }

        // movement scrolling on the side of the screen; the threshold define how far to the border
        // is the scrolling activating.
        if (mouse_x >= Screen.width - edge_threshold && transform.position.x <= scroll_limit_x)
        {
            transform.Translate((Vector3.right * speed * Time.deltaTime), Space.Self);
        }
        else if (mouse_x < edge_threshold && transform.position.x >= -scroll_limit_x)
        {
            transform.Translate((Vector3.left * speed * Time.deltaTime), Space.Self);
        }
        else if (mouse_y >= Screen.height - edge_threshold && transform.position.z <= scroll_limit_z)
        {
            transform.Translate((Vector3.forward * speed * Time.deltaTime), Space.Self);
        }
        else if (mouse_y < edge_threshold && transform.position.z >= -scroll_limit_z)
        {
            transform.Translate((Vector3.back * speed * Time.deltaTime), Space.Self);
        }

    }
}
2 Likes