2
\$\begingroup\$

I'm trying to write a solar system with Unity3D. Planets are sphere game objects rotating around another sphere game object representing the star.

What i want to achieve is let the user click on a planet and then zoom the camera on this planet and then make the camera follow and keep it centered on the screen while it keep moving around the star.

I decided to use iTween library and so far i was able to create the zoom effect using iTween.MoveUpdate. My problem is that the focused planet does not say properly centered as it moves.

Here is the relevant part of my script:

void Update () {
    if (Input.GetButtonDown("Fire1"))
    {
            Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(ray, out hit, Mathf.Infinity, concernedLayers))
            {
                    selectedPlanet = hit.collider.gameObject;
            }
    }
}

void LateUpdate() {
    if (selectedPlanet != null)
    {
            Vector3 pos = selectedPlanet.transform.position;
            pos.z = selectedPlanet.transform.position.z - selectedPlanet.transform.localScale.z;
            pos.y = selectedPlanet.transform.position.y;

            iTween.MoveUpdate(Camera.main.gameObject, pos, 2);
    }
}

What do i need to add to this script to make the selected planet stay centered on the screen?

I hosted my current project as a webplayer application so you see what's going wrong. You can access it here.

\$\endgroup\$
2
\$\begingroup\$

What you may be missing is the center point of the planets. The position may be a handle at the right of the planet (and so it is pushed off to the left.)

Use the mesh itself to find the center point. As you have very low poly meshes on that example this shouldn't be any strain at all:

using UnityEngine;
using System.Collections;

public class Example : MonoBehaviour {

    void Update () {
        if (Input.GetButtonDown("Fire1"))
        {
                Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
                RaycastHit hit;

                if (Physics.Raycast(ray, out hit, Mathf.Infinity, concernedLayers))
                {
                    selectedPlanet = hit.collider.gameObject;
                }
        }
    }

    void LateUpdate() {
        if (selectedPlanet != null)
        {
            Vector3 pos = GetCenterPoint(selectedPlanet);
            pos.z = selectedPlanet.transform.position.z - selectedPlanet.transform.localScale.z;
            pos.y = selectedPlanet.transform.position.y;

            iTween.MoveUpdate(Camera.main.gameObject, pos, 2);
        }
    }

    Vector3 GetCenterPoint(GameObject gameObj) {
        Mesh mesh = gameObj.GetComponent<MeshFilter>().mesh;
        Vector3[] vertices = mesh.vertices;
        float
            xMax = float.NegativeInfinity,
            yMax = float.NegativeInfinity,
            zMax = float.NegativeInfinity;
        float 
            xMin = float.PositiveInfinity,
            yMin = float.PositiveInfinity,
            zMin = float.PositiveInfinity;
        //Time to loop through and find the min and max x,y,z
        int i = 0;
        while (i < vertices.Length) {
            xMin = Mathf.Min(xMin, vertices[i].position.x);
            yMin = Mathf.Min(yMin, vertices[i].position.y);
            zMin = Mathf.Min(zMin, vertices[i].position.z);

            xMax = Mathf.Max(xMax, vertices[i].position.x);
            yMax = Mathf.Max(yMax, vertices[i].position.y);
            zMax = Mathf.Max(zMax, vertices[i].position.z);
        }
        //avg out the points to get the center
        Vector3 centerPoint = 
            new Vector3((xMin+xMax)/2,(yMin+yMax)/2,(zMin+zMax)/2);
        return centerPoint;
    }
}

Edit:

I have also noticed that you have not taken into account the X position of the planet, only the Y and z. This would make the planet offset if the camera was at a certain rotation to the planet but not adjusted for the x AND z then you would have it not centered on screen:

enter image description here

Notice the top one, ideal situation with your current setup. Bottom left is what can happen if your camera is rotated on it's Y axis slightly but you are tracking directly on x,y,z. Using the above should solve this issue but I believe this is the origin of the offset camera.

|improve this answer|||||
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.