playMaker

Author Topic: Jittery camera movement with Mouse Look  (Read 547 times)

SawyerK

  • Junior Playmaker
  • **
  • Posts: 93
Jittery camera movement with Mouse Look
« on: April 22, 2023, 12:21:35 PM »
Hi!

I made a rigidbody character controller. I use Mouse Look to rotate the character around and rotate the head (camera attached as a child to the main character object) up and down. Movement is done by Set Velocity.
The rigidbody character is set to interpolate which solves some of the problems but not all. Tried extrapolate it does the same.

- When the character moves forward, backward, left, right no jittering.
- When it turns around with the mouse look left, right, up and down no jittering.
- But when the character is moving sideways and turning at the same time it's start jittering.

Both Mouse Look and Set Velocity is set to every frame but there is not fixed update or late update settings for it, my guess is this is the cause of the problem.
I tried to find Mouse look and set velocity actions with fixed/late update settings but I didn't find any.

Does anyone know a possible solution for this?

Thank you in advance!

Christoph

  • Beta Group
  • Sr. Member
  • *
  • Posts: 254
Re: Jittery camera movement with Mouse Look
« Reply #1 on: April 26, 2023, 07:36:56 AM »
Have you checked the action’s code? Mind to copy paste it here? Since it’s velocity my guess it’s fixed update already but f not we can try and just make a new action with it changing it to fixed update.

SawyerK

  • Junior Playmaker
  • **
  • Posts: 93
Re: Jittery camera movement with Mouse Look
« Reply #2 on: April 26, 2023, 02:15:56 PM »
Here it is:
Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2013. All rights reserved.

using UnityEngine;

namespace HutongGames.PlayMaker.Actions
{
[ActionCategory(ActionCategory.Physics)]
    [Tooltip("Sets the velocity of a game object with a rigid body. To leave any axis unchanged, set variable to 'None'." +
             "\nIn most cases you should not modify the velocity directly, as this can result in unrealistic behaviour. " +
             "See unity docs: <a href=\"http://unity3d.com/support/documentation/ScriptReference/Rigidbody-velocity.html\">Rigidbody.velocity</a>.")]
    public class SetVelocity : ComponentAction<Rigidbody>
{
[RequiredField]
[CheckForComponent(typeof(Rigidbody))]
        [Tooltip("The Game Object with the RigidBody component.")]
        public FsmOwnerDefault gameObject;

[UIHint(UIHint.Variable)]
        [Tooltip("Set velocity using Vector3 variable and/or individual channels below.")]
        public FsmVector3 vector;

        [Tooltip("Velocity in X axis.")]
        public FsmFloat x;
        [Tooltip("Velocity in Y axis.")]
        public FsmFloat y;
        [Tooltip("Velocity in Z axis.")]
        public FsmFloat z;

        [Tooltip("You can set velocity in world or local space.")]
        public Space space;

        [Tooltip("Set the velocity every frame.")]
        public bool everyFrame;

public override void Reset()
{
gameObject = null;
vector = null;
// default axis to variable dropdown with None selected.
x = new FsmFloat { UseVariable = true };
y = new FsmFloat { UseVariable = true };
z = new FsmFloat { UseVariable = true };
space = Space.Self;
everyFrame = false;
}

        public override void OnPreprocess()
        {
            Fsm.HandleFixedUpdate = true;
        }

// TODO: test this works in OnEnter!
public override void OnEnter()
{
DoSetVelocity();

if (!everyFrame)
{
Finish();
}
}

public override void OnFixedUpdate()
{
DoSetVelocity();

if (!everyFrame)
Finish();
}

        private void DoSetVelocity()
{
            if (!UpdateCacheAndTransform(Fsm.GetOwnerDefaultTarget(gameObject)))
{
return;
}

// init velocity

Vector3 velocity;

if (vector.IsNone)
{
velocity = space == Space.World ?
rigidbody.velocity :
cachedTransform.InverseTransformDirection(rigidbody.velocity);
}
else
{
velocity = vector.Value;
}

// override any axis

if (!x.IsNone) velocity.x = x.Value;
if (!y.IsNone) velocity.y = y.Value;
if (!z.IsNone) velocity.z = z.Value;

// apply

rigidbody.velocity = space == Space.World ? velocity : cachedTransform.TransformDirection(velocity);
}
}
}

Christoph

  • Beta Group
  • Sr. Member
  • *
  • Posts: 254
Re: Jittery camera movement with Mouse Look
« Reply #3 on: April 27, 2023, 12:54:42 AM »
So yeah. As you can see it’s already running in fixed update. If all your other actions are set to run in fixed code too, the problem should be somewhere else.

SawyerK

  • Junior Playmaker
  • **
  • Posts: 93
Re: Jittery camera movement with Mouse Look
« Reply #4 on: April 27, 2023, 11:56:40 AM »
Is Mouse Look could be the problem?
Weird thing is its only happening when i move and rotate the character at the same time. I only use these to actions to move and rotate the character.
Code: [Select]
// (c) Copyright HutongGames, LLC 2010-2021. All rights reserved.

// NOTE: The new Input System and legacy Input Manager can both be enabled in a project.
// This action was developed for the old input manager, so we will use it if its available.
// If only the new input system is available we will try to use that instead,
// but there might be subtle differences in the behaviour in the new system!

#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
#define NEW_INPUT_SYSTEM_ONLY
#endif

using UnityEngine;

#if NEW_INPUT_SYSTEM_ONLY
using UnityEngine.InputSystem;
#endif

namespace HutongGames.PlayMaker.Actions
{
/// <summary>
/// Action version of Unity's builtin MouseLook behaviour.
/// TODO: Expose invert Y option.
/// </summary>
[ActionCategory(ActionCategory.Input)]
[Tooltip("Rotates a GameObject based on mouse movement. Minimum and Maximum values can be used to constrain the rotation.")]
public class MouseLook : ComponentAction<Transform>
{
public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }

[RequiredField]
[Tooltip("The GameObject to rotate.")]
public FsmOwnerDefault gameObject;

[Tooltip("The axes to rotate around.")]
public RotationAxes axes = RotationAxes.MouseXAndY;

[RequiredField]
[Tooltip("Sensitivity of movement in X direction.")]
public FsmFloat sensitivityX;

[RequiredField]
[Tooltip("Sensitivity of movement in Y direction.")]
public FsmFloat sensitivityY;

[HasFloatSlider(-360,360)]
        [Tooltip("Clamp rotation around X axis. Set to None for no clamping.")]
public FsmFloat minimumX;

[HasFloatSlider(-360, 360)]
        [Tooltip("Clamp rotation around X axis. Set to None for no clamping.")]
        public FsmFloat maximumX;

[HasFloatSlider(-360, 360)]
        [Tooltip("Clamp rotation around Y axis. Set to None for no clamping.")]
        public FsmFloat minimumY;

[HasFloatSlider(-360, 360)]
        [Tooltip("Clamp rotation around Y axis. Set to None for no clamping.")]
        public FsmFloat maximumY;

[Tooltip("Repeat every frame.")]
public bool everyFrame;

        private float rotationX;
        private float rotationY;

        public override void Reset()
{
gameObject = null;
axes = RotationAxes.MouseXAndY;
sensitivityX = 15f;
sensitivityY = 15f;
minimumX = new FsmFloat {UseVariable = true};
            maximumX = new FsmFloat { UseVariable = true };
minimumY = -60f;
maximumY = 60f;
everyFrame = true;
}

public override void OnEnter()
{
            if (!UpdateCachedTransform(Fsm.GetOwnerDefaultTarget(gameObject)))
            {
Finish();
return;
}

// Make the rigid body not change rotation
// TODO: Original Unity script had this. Expose as option?
    var rigidbody = cachedGameObject.GetComponent<Rigidbody>();
            if (rigidbody != null)
{
rigidbody.freezeRotation = true;
}

            // initialize rotation

            rotationX = cachedTransform.localRotation.eulerAngles.y;
            rotationY = cachedTransform.localRotation.eulerAngles.x;

            if (!everyFrame)
{
                DoMouseLook();
                Finish();
}
        }

public override void OnUpdate()
{
DoMouseLook();
}

        private void DoMouseLook()
{
            if (!UpdateCachedTransform(Fsm.GetOwnerDefaultTarget(gameObject)))
            {
                Finish();
                return;
            }

            switch (axes)
{
case RotationAxes.MouseXAndY:

cachedTransform.localEulerAngles = new Vector3(GetYRotation(), GetXRotation(), 0);
break;

case RotationAxes.MouseX:

                    cachedTransform.localEulerAngles = new Vector3(cachedTransform.localEulerAngles.x, GetXRotation(), 0);
break;

case RotationAxes.MouseY:

                    cachedTransform.localEulerAngles = new Vector3(GetYRotation(-1), cachedTransform.localEulerAngles.y, 0);
break;
}
        }

        private float GetXRotation()
{
#if NEW_INPUT_SYSTEM_ONLY
            if (Mouse.current == null) return rotationX;
// fudge factor accounts for sensitivity of old input system
            rotationX += Mouse.current.delta.ReadValue().x * sensitivityY.Value * 0.05f;
#else
            rotationX += Input.GetAxis("Mouse X") * sensitivityX.Value;
#endif
            rotationX = ClampAngle(rotationX, minimumX, maximumX) % 360;
return rotationX;
}

        private float GetYRotation(float invert = 1)
{
#if NEW_INPUT_SYSTEM_ONLY
            if (Mouse.current == null) return rotationY;
            // fudge factor accounts for sensitivity of old input system
            rotationY += Mouse.current.delta.ReadValue().y * sensitivityY.Value * invert * -0.05f;
#else
            rotationY += Input.GetAxis("Mouse Y") * sensitivityY.Value * invert;
#endif
rotationY = ClampAngle(rotationY, minimumY, maximumY) % 360;
return rotationY;
}

// Clamp function that respects IsNone and 360 wrapping
        private static float ClampAngle(float angle, FsmFloat min, FsmFloat max)
{
            if (angle < 0f) angle = 360 + angle;

            var from = min.IsNone ? -720 : min.Value;
            var to = max.IsNone ? 720 : max.Value;

            if (angle > 180f) return Mathf.Max(angle, 360 + from);
            return Mathf.Min(angle, to);
}
}
}