Skip to main content

TPS with free look tutorial, version 2 (and bugs)

After working a bit to improve the third person camera system I mentioned a couple of days ago, I found a few problems that I could fix, and other I cant. Here is the updated code:

public class PlayerControl : MonoBehaviour {

    public GameObject pivot;
    Animator anim;
    int direction = 0;
    int FORWARD  = 1;
    int BACKWARD = 2;
    int LEFT = 3;
    int RIGHT = 4;

    // Use this for initialization
    void Start () {
        //cam = gameObject.GetComponent<Camera> ();
        //Cursor.visible = false;
        //Cursor.lockState = CursorLockMode.Locked;
        anim = gameObject.GetComponent<Animator> ();
    }
   
    // Update is called once per frame
    void Update () {
        Vector3 rot;

        if (Input.GetKeyDown (KeyCode.W)) {
            direction = FORWARD;
        } else if (Input.GetKeyDown (KeyCode.S)) {
            //go back
            direction = BACKWARD;
        } else if (Input.GetKeyDown (KeyCode.A)) {
            direction = LEFT;
        } else if (Input.GetKeyDown (KeyCode.D)) {
            direction = RIGHT;
        } else if (Input.GetKeyUp (KeyCode.W) || Input.GetKeyUp (KeyCode.S) || Input.GetKeyUp (KeyCode.A) || Input.GetKeyUp (KeyCode.D)) {
            direction = 0;
        }

        switch (direction) {
            case 0: //do nothing
                anim.SetInteger("State",0);
                break;
            case 1:        //forward
                rot = gameObject.transform.localEulerAngles;
                rot.y = pivot.transform.localEulerAngles.y;
                gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
                anim.SetInteger("State",1);
                gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);               
                pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
                break;
            case 2: //
                rot = gameObject.transform.localEulerAngles;
                rot.y = pivot.transform.localEulerAngles.y+180f;
                gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
                anim.SetInteger("State",1);
                gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);               
                pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
                break;
            case 3:
                rot = gameObject.transform.localEulerAngles;
                rot.y = pivot.transform.localEulerAngles.y-90f;
                gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
                anim.SetInteger("State",1);
                gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);               
                pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
            break;
            case 4:
                rot = gameObject.transform.localEulerAngles;
                rot.y = pivot.transform.localEulerAngles.y+90f;
                gameObject.transform.rotation = Quaternion.Slerp (gameObject.transform.rotation, Quaternion.Euler (rot), 5f * Time.deltaTime);
                anim.SetInteger("State",1);
                gameObject.transform.Translate (0, 0, 20 * Time.deltaTime);               
                pivot.transform.position = Vector3.Slerp(pivot.transform.position, gameObject.transform.position, 5f *Time.deltaTime);
            break;
        }
    }
}

The above code handles player movement, the next, handles camera free look:

public class PivotControl : MonoBehaviour {
    float rotationY = 0F;
    Camera cam;
    Text label;

    // Use this for initialization
    void Start () {
        cam = gameObject.GetComponentInChildren<Camera> ();
        label = GameObject.Find ("Label").GetComponent<Text>();;
    }
   
    // Update is called once per frame
    void Update () {       
        if (Input.GetAxis ("Mouse X") != 0 || Input.GetAxis ("Mouse Y") != 0) {
                       float rotationX = gameObject.transform.localEulerAngles.y + Input.GetAxis("Mouse X") * 2f;

            rotationY += Input.GetAxis("Mouse Y") * 5f;       
            gameObject.transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
            cam.transform.LookAt(cam.ViewportToWorldPoint(new Vector3(0.5f, 0.5f, cam.farClipPlane)));
            //check if we are looking at something we can interact with                
            RaycastHit hit; 
            Ray ray =  cam.ViewportPointToRay(new Vector3(0.5F, 0.5F, 0));
            if (Physics.Raycast (ray, out hit, 100)) {
                                    if (hit.collider.tag=="Interactable")
                    label.text = "Press E to interact with "+hit.collider.name;
            } else {
                label.text = "";
            }
        }
    }
}

Ok,  whats the problem here? Well, the camera free look works, but I find that the picking system is not precise. Also, the player is not being rotated exactly towards the camera direction when the angle between player and camera orientation is large (like, the camera is looking to the screen left side). I think Im missing something important here, like resynch the camera to the screen center or something. Also, I havent implemented yet a crosshair system.
Sure you can make a game with the current code, but it lacks the polish a professional title should have.

Comments

Popular posts from this blog

Unity3d isometric camera tutorial

I had pending this since a month ago, so Im forcing myself to post it today. The goal is to provide a fully functional isometric like system that you can use with few or none modifications in your own game. So, lets get started. Start Unity3d and in your scene, add an empty GameObject, we will call it target . Create a camera object and drag it to target to make it child. The result looks like this: Now select Camera and set the values to this: For a true isometric like feeling, ortho projection is essential. You could use perspective, but it is not the same. Play with Size to suit your needs (we will be using this later, when implementing zoom). Now, lets create an script named CameraController, or whatever, and drag it to target GameObject. Lets implement scrolling, the easier part: go to Update() and add the following code: if (Input.GetKeyDown(KeyCode.W)) {             dir = UP;         } else if (Input.GetKeyDown(KeyCode.S)) {             dir = DOWN;         } e

Isometric camera with Godot

Took some effort and some of my sleep hours, but at last, I made it. Here is my first videotutorial: implementing an isometric camera in 3D, with Godot. Useful if you want to emulate the look of old classics like Fallout 2, but with some extra features. Considering that my voice is not so nice, and my english pronounciation is even worse, I also added texts to help you underestand what Im saying. You will also notice some background noise, but cant do anything to solve that. Any suggestion is welcome. Expect another tutorial soon.... or sor tof. This time, will be about my AI system.

Testing animation retargeting in Godot 4

 We have finished the project and it is time tostart a new one. This time, I have convinced the team to work on a combat  prototype and try Godot 4. After a month, Im quite pleased with the progress. Specially, we have applied animation retargeting, which is a new feature in Godot 4. In previous project, our main artist devised a clever way to reuse animations, but now we have a native solution. Our first attemp didnt worked, but I found that remapping the armature starting by the feet solved the problem. Weird, isnt it? By the way, you can see the prototype here . WE are keeping it public to let people learn from our mistakes. And, if you need some animation retargeting tutorial, this is the guide we used: