playMaker

Author Topic: Camera lock vertical look when rotate animation  (Read 5088 times)

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Camera lock vertical look when rotate animation
« on: October 19, 2018, 03:44:26 PM »
Hi there,

I have a camera problem when I do an animation. I use the SimpleSmoothMouseLook script which works very well but as soon as I want to make a camera animation by giving it a rotation, when I run the game I can not look up and down anymore.
The problem comes from the rotation animation of the camera but I do not know how to adjust it.

An idea?

Here is the script:

Code: [Select]
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[AddComponentMenu("Camera/Simple Smooth Mouse Look ")]
public class SimpleSmoothMouseLook : MonoBehaviour
{
    Vector2 _mouseAbsolute;
    Vector2 _smoothMouse;

    public Vector2 clampInDegrees = new Vector2(360, 180);
    public bool lockCursor;
    public Vector2 sensitivity = new Vector2(2, 2);
    public Vector2 smoothing = new Vector2(3, 3);
    public Vector2 targetDirection;
    public Vector2 targetCharacterDirection;

   
    // Assign this if there's a parent object controlling motion, such as a Character Controller.
    // Yaw rotation will affect this object instead of the camera if set.
    public GameObject characterBody;

    void Start()
    {
        // Set target direction to the camera's initial orientation.
        targetDirection = transform.localRotation.eulerAngles;

        // Set target direction for the character body to its inital state.
        if (characterBody)
            targetCharacterDirection = characterBody.transform.localRotation.eulerAngles;
    }

    void Update()
    {
        // Ensure the cursor is always locked when set
        if (lockCursor)
        {
            Cursor.lockState = CursorLockMode.Locked;
        }

        // Allow the script to clamp based on a desired target value.
        var targetOrientation = Quaternion.Euler(targetDirection);
        var targetCharacterOrientation = Quaternion.Euler(targetCharacterDirection);

        // Get raw mouse input for a cleaner reading on more sensitive mice.
        var mouseDelta = new Vector2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y"));

        // Scale input against the sensitivity setting and multiply that against the smoothing value.
        mouseDelta = Vector2.Scale(mouseDelta, new Vector2(sensitivity.x * smoothing.x, sensitivity.y * smoothing.y));

        // Interpolate mouse movement over time to apply smoothing delta.
        _smoothMouse.x = Mathf.Lerp(_smoothMouse.x, mouseDelta.x, 1f / smoothing.x);
        _smoothMouse.y = Mathf.Lerp(_smoothMouse.y, mouseDelta.y, 1f / smoothing.y);

        // Find the absolute mouse movement value from point zero.
        _mouseAbsolute += _smoothMouse;

        // Clamp and apply the local x value first, so as not to be affected by world transforms.
        if (clampInDegrees.x < 360)
            _mouseAbsolute.x = Mathf.Clamp(_mouseAbsolute.x, -clampInDegrees.x * 0.5f, clampInDegrees.x * 0.5f);

        // Then clamp and apply the global y value.
        if (clampInDegrees.y < 360)
            _mouseAbsolute.y = Mathf.Clamp(_mouseAbsolute.y, -clampInDegrees.y * 0.5f, clampInDegrees.y * 0.5f);

        transform.localRotation = Quaternion.AngleAxis(-_mouseAbsolute.y, targetOrientation * Vector3.right) * targetOrientation;

        // If there's a character body that acts as a parent to the camera
        if (characterBody)
        {
            var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, Vector3.up);
            characterBody.transform.localRotation = yRotation * targetCharacterOrientation;
        }
        else
        {
            var yRotation = Quaternion.AngleAxis(_mouseAbsolute.x, transform.InverseTransformDirection(Vector3.up));
            transform.localRotation *= yRotation;
        }

        // Hide cursor
        Cursor.visible = false;
    }
}

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #1 on: October 22, 2018, 09:06:17 AM »
Help Please :)

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #2 on: October 22, 2018, 05:39:26 PM »
Hi. you probably need to make a parent and drop in you character, then do the mouselook on the parent

What kind of setup do you have (first person, third person, 2d,..)

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #3 on: October 23, 2018, 02:04:34 AM »
Hi djaydino,

it's a first person. I don't use standard assets for the controller.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #4 on: October 23, 2018, 03:21:50 AM »
Hi.
Are you using the movement on the character itself or on a empty parent.

Also it better to separate the camera and use get/set position to follow the player.

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #5 on: October 23, 2018, 09:48:07 AM »
For the movement, I use the FPSWalkerEnhanced script:

Code: [Select]
using UnityEngine;
using System.Collections;

[RequireComponent(typeof(CharacterController))]
public class FPSWalkerEnhanced : MonoBehaviour
{

    public float walkSpeed = 6.0f;

    public float runSpeed = 11.0f;

    // If true, diagonal speed (when strafing + moving forward or back) can't exceed normal move speed; otherwise it's about 1.4 times faster
    public bool limitDiagonalSpeed = true;

    // If checked, the run key toggles between running and walking. Otherwise player runs if the key is held down and walks otherwise
    // There must be a button set up in the Input Manager called "Run"
    public bool toggleRun = false;

    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;

    // Units that player can fall before a falling damage function is run. To disable, type "infinity" in the inspector
    public float fallingDamageThreshold = 10.0f;

    // If the player ends up on a slope which is at least the Slope Limit as set on the character controller, then he will slide down
    public bool slideWhenOverSlopeLimit = false;

    // If checked and the player is on an object tagged "Slide", he will slide down it regardless of the slope limit
    public bool slideOnTaggedObjects = false;

    public float slideSpeed = 12.0f;

    // If checked, then the player can change direction while in the air
    public bool airControl = false;

    // Small amounts of this results in bumping when walking down slopes, but large amounts results in falling too fast
    public float antiBumpFactor = .75f;

    // Player must be grounded for at least this many physics frames before being able to jump again; set to 0 to allow bunny hopping
    public int antiBunnyHopFactor = 1;

    private Vector3 moveDirection = Vector3.zero;
    private bool grounded = false;
    private CharacterController controller;
    private Transform myTransform;
    private float speed;
    private RaycastHit hit;
    private float fallStartLevel;
    private bool falling;
    private float slideLimit;
    private float rayDistance;
    private Vector3 contactPoint;
    private bool playerControl = false;
    private int jumpTimer;

    void Start()
    {
        controller = GetComponent<CharacterController>();
        myTransform = transform;
        speed = walkSpeed;
        rayDistance = controller.height * .5f + controller.radius;
        slideLimit = controller.slopeLimit - .1f;
        jumpTimer = antiBunnyHopFactor;
    }

    void FixedUpdate()
    {
        float inputX = Input.GetAxis("Horizontal");
        float inputY = Input.GetAxis("Vertical");
        // If both horizontal and vertical are used simultaneously, limit speed (if allowed), so the total doesn't exceed normal move speed
        float inputModifyFactor = (inputX != 0.0f && inputY != 0.0f && limitDiagonalSpeed) ? .7071f : 1.0f;

        if (grounded)
        {
            bool sliding = false;
            // See if surface immediately below should be slid down. We use this normally rather than a ControllerColliderHit point,
            // because that interferes with step climbing amongst other annoyances
            if (Physics.Raycast(myTransform.position, -Vector3.up, out hit, rayDistance))
            {
                if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    sliding = true;
            }
            // However, just raycasting straight down from the center can fail when on steep slopes
            // So if the above raycast didn't catch anything, raycast down from the stored ControllerColliderHit point instead
            else
            {
                Physics.Raycast(contactPoint + Vector3.up, -Vector3.up, out hit);
                if (Vector3.Angle(hit.normal, Vector3.up) > slideLimit)
                    sliding = true;
            }

            // If we were falling, and we fell a vertical distance greater than the threshold, run a falling damage routine
            if (falling)
            {
                falling = false;
                if (myTransform.position.y < fallStartLevel - fallingDamageThreshold)
                    FallingDamageAlert(fallStartLevel - myTransform.position.y);
            }

            // If running isn't on a toggle, then use the appropriate speed depending on whether the run button is down
            if (!toggleRun)
                speed = Input.GetButton("Run") ? runSpeed : walkSpeed;

            // If sliding (and it's allowed), or if we're on an object tagged "Slide", get a vector pointing down the slope we're on
            if ((sliding && slideWhenOverSlopeLimit) || (slideOnTaggedObjects && hit.collider.tag == "Slide"))
            {
                Vector3 hitNormal = hit.normal;
                moveDirection = new Vector3(hitNormal.x, -hitNormal.y, hitNormal.z);
                Vector3.OrthoNormalize(ref hitNormal, ref moveDirection);
                moveDirection *= slideSpeed;
                playerControl = false;
            }
            // Otherwise recalculate moveDirection directly from axes, adding a bit of -y to avoid bumping down inclines
            else
            {
                moveDirection = new Vector3(inputX * inputModifyFactor, -antiBumpFactor, inputY * inputModifyFactor);
                moveDirection = myTransform.TransformDirection(moveDirection) * speed;
                playerControl = true;
            }

            // Jump! But only if the jump button has been released and player has been grounded for a given number of frames
            if (!Input.GetButton("Jump"))
                jumpTimer++;
            else if (jumpTimer >= antiBunnyHopFactor)
            {
                moveDirection.y = jumpSpeed;
                jumpTimer = 0;
            }
        }
        else
        {
            // If we stepped over a cliff or something, set the height at which we started falling
            if (!falling)
            {
                falling = true;
                fallStartLevel = myTransform.position.y;
            }

            // If air control is allowed, check movement but don't touch the y component
            if (airControl && playerControl)
            {
                moveDirection.x = inputX * speed * inputModifyFactor;
                moveDirection.z = inputY * speed * inputModifyFactor;
                moveDirection = myTransform.TransformDirection(moveDirection);
            }
        }

        // Apply gravity
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller, and set grounded true or false depending on whether we're standing on something
        grounded = (controller.Move(moveDirection * Time.deltaTime) & CollisionFlags.Below) != 0;
    }

    void Update()
    {
        // If the run button is set to toggle, then switch between walk/run speed. (We use Update for this...
        // FixedUpdate is a poor place to use GetButtonDown, since it doesn't necessarily run every frame and can miss the event)
        if (toggleRun && grounded && Input.GetButtonDown("Run"))
            speed = (speed == walkSpeed ? runSpeed : walkSpeed);
    }

    // Store point that we're in contact with for use in FixedUpdate if needed
    void OnControllerColliderHit(ControllerColliderHit hit)
    {
        contactPoint = hit.point;
    }

    // If falling damage occured, this is the place to do something about it. You can make the player
    // have hitpoints and remove some of them based on the distance fallen, add sound effects, etc.
    void FallingDamageAlert(float fallDistance)
    {
        print("Ouch! Fell " + fallDistance + " units!");
    }
}

I have the parent FPSCharacter, and in it I have 2 cameras. One (the main camera) for all, except weapons and one just for Weapons in order to hide the clipping with walls.

In the main camera I have my WeaponHolder. And the script for the camera is on the main camera and the camera for weapons.

Is it good or not?

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #6 on: October 23, 2018, 10:02:12 AM »
Hi.
It might be better to separate the camera and use a simple fsm to follow the weapon holder

Using Get / Set position and Check Late Update

For the rotation i usually do this on the separated camera and if to object needs to be rotated with the camera i use get / set rotation but then get rot from camera and set rot to object.

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #7 on: October 23, 2018, 10:59:51 AM »
Hi djaydino,

do you have examples of tutorials to get this result?

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #8 on: October 23, 2018, 05:24:26 PM »
Hi.
If you have my PlayMaker Sample Asset, on the bullet hole sample i have a separate camera.

I do have plans for character setup tutorials but i have to much other work at the moment, but its in the top 3 of my upcoming tutorials list

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #9 on: October 24, 2018, 05:09:18 AM »
Hi djaydino,

I bought your asset. It is especially to support you with all the help that you bring here.
I'm going to take a look at the camera in the bullet hole scene.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #10 on: October 24, 2018, 06:24:09 AM »
Hi.
Thanks!
If you have questions, let me know.

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #11 on: October 25, 2018, 10:28:53 AM »
Hi djaydino,

it works with your method.
But now I try to make my Character lean right and left, I don't know how to do it with this method.

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #12 on: October 25, 2018, 12:31:28 PM »
Hi.
You you mean like standing in front of a wall and then look on the side of it?

There are 2 ways i can think of to manipulate the camera :

1 : if camera is set as a child and the parent handles the movement you could move the camera left/right in local space.

2 : have a dedicated follow (empty) object on the player that is a child to the player object that handles the movement.
and set the camera handler to follow that object.
Then move the dedicated follow (empty) object left/right in local space.


2nd option you could maybe even give a collider to the dedicated follow (empty) object as a 'Head' collider if you want the enemy to be able to hit the player.

Franck

  • Junior Playmaker
  • **
  • Posts: 91
Re: Camera lock vertical look when rotate animation
« Reply #13 on: October 25, 2018, 12:40:14 PM »
I have the Camera Holder as parent and the Main Camera as Child.
I try to create an animation on the Camera Holder. In this animation I set the Main Camera and move on X.

But when I play this animation the X is taken as Global and not Local. How can I use the Local transform in animation?

djaydino

  • Administrator
  • Hero Member
  • *****
  • Posts: 7616
    • jinxtergames
Re: Camera lock vertical look when rotate animation
« Reply #14 on: October 25, 2018, 12:45:23 PM »
Hi.
the animation should probably be on the camera or a child of the camera holder where you can place the camera in.