Odd camera behavior

When I target an enemy and then cancel the target if i haven’t moved much the camera snaps back to looking at my character kind of how you would expect, however if i target an enemy and then move/circle around them and then cancel it my free look camera doesn’t snap in to position looking at the back of my character again. Maybe this is something adjusted later in the course?

Heres a tiny 10sec clip i took of the issue i’m talking about: https://imgur.com/a/fDImIlj

And a screenshot of my settings:

I also tried implementing this as it seemed to be the only post discussing this but it did nothing:

EDIT: after changing the wait time for the recentering to 0 it performs more like expected, still not quite 100% but alot closer.

EDIT 2: The changes to transitions for the freelook camera in the combat polishing section fix this.

I believe Nathan covers this issue in a later lecture.

You are correct, the combat polishing section had the fix for it, simple and easy with the transition settings.

1 Like

I have a couple more issues i’ve discovered with some playtesting, figured better to reply here instead of open another topic since they are still odd camera behaviors. I’ve pinned down the source of the first issue at least, but i’m unsure of how i would go about fixing (or debugging) it.

  1. If I am target locked and cancel the target to go back to free look while I am moving backwards directly towards the camera while using the ease in(or out or in/out) for the default blend the camera will spin extremely fast over the duration of the blend before settling in the correct location. If i use cut for the default blend it doesn’t do this so it is definitely something to do with using the blend reacting poorly to something else, but having ease value is very nice and improves feel substantially so i would like to figure out why.

Clip demonstrating: https://imgur.com/a/pO0wUDw

  1. When i switch back and forth between targeting and free look while moving backwards directly towards the camera the position of the free look camera is oddly offset from where it is expected to be, it works as expected moving in any other direction (seemingly including back-right/back-left) reliably reaching the same position with multiple toggles.

Clip demonstrating: https://imgur.com/a/UYrY1MK

Since they both only occur when the character is running towards the camera logically it would seem that they are linked to the same source issue, but where that source is i can’t seem to find. I’ve combed through basically every parameter for the cameras and can’t find a seemingly relevant setting except maybe the Heading Definition but none of the options make a difference. I have a feeling it has to do with calculate movement in the freelookstate, but i don’t understand the relation between the camera and the movement well enough to pin it down.

My free look cam:

My State Driven cam:

And my freelookstate script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Cinemachine;

public class PlayerFreeLookState : PlayerBaseState
{
    private readonly int FreeLookBlendTreeHash = Animator.StringToHash("FreeLookBlendTree");
    private readonly int FreeLookSpeedHash = Animator.StringToHash("FreeLookSpeed");

    private const float AnimatorDampTime = 0.1f;
    private const float CrossFadeDuration = .1f;

    private Vector2 dodgingDirectionInput;
    private float remainingDodgeTime;
    

    public PlayerFreeLookState(PlayerStateMachine stateMachine) : base(stateMachine) { }

    public override void Enter()
    {
        stateMachine.InputReader.TargetEvent += OnTarget;
        stateMachine.InputReader.JumpEvent += OnJump;
        stateMachine.InputReader.DodgeEvent += OnDodge;

        stateMachine.Animator.CrossFadeInFixedTime(FreeLookBlendTreeHash, CrossFadeDuration);
    }

    public override void Tick(float deltaTime)
    {
        if (stateMachine.InputReader.IsAttacking)
        {
            stateMachine.SwitchState(new PlayerAttackingState(stateMachine, 0));
            return;
        }

        Vector3 movement = CalculateMovement();

        Move(movement * stateMachine.FreeLookMovementSpeed, deltaTime);

        if (stateMachine.InputReader.MovementValue == Vector2.zero)
        {
            stateMachine.Animator.SetFloat(FreeLookSpeedHash, 0, AnimatorDampTime, deltaTime);
            return;
        }

        stateMachine.Animator.SetFloat(FreeLookSpeedHash, 1, AnimatorDampTime, deltaTime);

        FaceMovementDirection(movement, deltaTime);
    }

    private void OnTarget()
    {
        if (!stateMachine.Targeter.SelectTarget()) { return; }

        stateMachine.SwitchState(new PlayerTargetingState(stateMachine));
    }

    private void OnDodge()
    {
        if (stateMachine.InputReader.MovementValue == Vector2.zero) { return; }

        stateMachine.SwitchState(new PlayerDodgingState(stateMachine, stateMachine.InputReader.MovementValue, null));
    }

    private void OnJump()
    {
        stateMachine.SwitchState(new PlayerJumpingState(stateMachine));
    }

    private Vector3 CalculateMovement()
    {
        Vector3 movement = new Vector3();

        Vector3 forward = stateMachine.MainCameraTransform.forward;
        Vector3 right = stateMachine.MainCameraTransform.right;

        forward.y = 0f;
        right.y = 0f;

        forward.Normalize();
        right.Normalize();
        movement = forward * stateMachine.InputReader.MovementValue.y + right * stateMachine.InputReader.MovementValue.x;

        return movement;
    }

    private void FaceMovementDirection(Vector3 movement, float deltaTime)
    {
        stateMachine.transform.rotation = Quaternion.Lerp(
            stateMachine.transform.rotation,
            Quaternion.LookRotation(movement),
            deltaTime * stateMachine.RotationDamping);
    }

    public override void Exit()
    {
        stateMachine.InputReader.TargetEvent -= OnTarget;
        stateMachine.InputReader.JumpEvent -= OnJump;
        stateMachine.InputReader.DodgeEvent -= OnDodge;
    }
}

I believe they are as well. The difference between the camera angle of the Targetting camera and the Free Look Camera at the time you switch are in both cases approaching 180, and the camera is trying to correct this imbalance too quickly.

The Freelook Camera is going to do everything in it’s power to keep the camera behind the player. Since the player’s 180 is actually rather rapid, the transition is fairly rapid as well…

In the course project, this turn is still rapid, but without the apparent jarring from your images… You might consider downloading the course repo at GameDev.tv / Unity 3rd Person Combat and Traversal / Third-Person-Combat-and-Traversal · GitLab and comparing the camera setups and code (I don’t think this is a code issue, actually) between your project and Nathans.

This ended up being a really silly one too, that I am astounded I didn’t catch. I had been using .5 for the ease time, i even went back to the videos where we set up the camera and somehow didn’t catch it there. It works perfectly fine at .25 like the video, and is broken at .5. After downloading the project repo and testing there the second odd behavior is similar, maybe not quite 1:1 but it’s hard to say it’s at least also present so that may be something to do with how the new state is interpreting the leftover rotation/position from the transition, but honestly that’s an insanely tiny detail that i doubt anyone would ever even notice.

Thanks for the pointers, downloading the repo and testing it out directly was definitely the way to go.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.

Privacy & Terms