Rotate flashlight into the direction the player is looks

Ive got a 3d first person charater that has a flashlight as a child object.
The flahslight has a script attached and im attempting to rotate the flashlight ahead in the direction the player looks and then when they stop giving look input have it lerp back to center. Horizontal works but vertical does not.

this code works on the y but just not on the x, it lags behind on the x

Please assist, oddly enough ChatGPT is pretty unhelpful.

[SerializeField]
    private float rotationOffsetAngle = 10f; // Smaller angle for natural leading effect

    [SerializeField]
    private float _maxLerpSpeed = 2f;

    [SerializeField]
    private float _returnLerpSpeed = 2.5f;

private void Update()
    {
        if (_largeLight.enabled && _smallLight.enabled)
        {
            Vector2 lookInput = _playerLook.LookInput;

            // Check if the look input is above a small threshold to avoid jittering
            if (lookInput.magnitude > 0.1f)
            {
                // Calculate small rotation offset for natural leading
                float xRotation = lookInput.y * rotationOffsetAngle;
                float yRotation = lookInput.x * rotationOffsetAngle;

                // Create target rotation slightly ahead based on camera's rotation
                Quaternion targetRotation =
                    _mainCamera.rotation * Quaternion.Euler(-xRotation, yRotation, 0);

                // Smoothly rotate using Slerp for better handling of larger changes
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    targetRotation,
                    Time.deltaTime * _maxLerpSpeed
                );
            }
            else
            {
                // Lerp back to the current rotation of the main camera when look input is near zero
                transform.rotation = Quaternion.Slerp(
                    transform.rotation,
                    _mainCamera.rotation,
                    Time.deltaTime * _returnLerpSpeed
                );
            }
        }
    }

Hardly odd at all. Chat is only helpful if:

  • Chat has been trained on your exact problem or one close enough to it
  • you describe your problem well enough that Chat barfs the solution back to you

Sounds like you’re already a good ways into debugging it… now take it across the finish line and find out what is wrong so that you might reason about how to fix it.

If the lags are from the code above they will be from those spherical linear interpolation (Slerp) calls, which are used in the above case as a poor man’s low-pass filter. If that’s the issue then increasing the magnitude of the third term supplied to Slerp() (the term you multiply by Time.deltaTime) will likely make things more snappy.

NOTE: multiplying it by Time.deltaTime is correct here, to ensure speed consistency across varying framerates.

By debugging you can find out exactly what your program is doing so you can fix it.

Use the above techniques to get the information you need in order to reason about what the problem is.

You can also use Debug.Log(...); statements to find out if any of your code is even running. Don’t assume it is.

Once you understand what the problem is, you may begin to reason about a solution to the problem.

Hi, I think this code might help you:

newMoveDirection = UnityEngine.Quaternion.Euler(
    0f,
    Player.VirtualCamera.Camera.transform.rotation.eulerAngles.y,
    0f
)

This is the type of code we use to create a camera movement that simulates looking motion for the player. I’m pretty sure you can adapt it to the torch you have. This allows X and Z inputs from the keyboard/joystick while making sure the Y (the Yaw) is aligned with the view.

Additionally, I like the way your lerp when it has to go back but when your are on your “live” state of your mechanic, I would make the torch more responsive and follow the movement right away. But this is just my opinion and if you have a good game design explanation for this then go for it!!

Hello, thank you for the response. I am currently doing that in the code and multiplying it by the camera rotation (because if im turned around it will go in the opposite direction.) its the vertical that is the issue among some choppyness. its seems like my code isnt making it do anything on the vertical its only the lerp back to center that even makes it move vertical

I don’t really understand what you are trying to achieve, but if you want the torch to face the camera’s direction or the player’s direction, no need for the kind of computation you are doing, simply use their forward direction and do a rotate towards? Because right now you are recomputing angles and rotations, this is probably not necessary.

However, this won’t solve the pitch issue you have (no rotation and the X axis). For this, you could accumulate the rotation given by the inputs and then add it to the final rotation applied to the torch. You would introduce the concept of angular velocities.

// Computing the next angular velocity.
if(InputController.Instance.CurrentControlScheme == ControlSchemes.GAMEPAD)
{
    AngularVelocity = new UnityEngine.Vector2(
        -lookDirection.y * PitchAngularSpeed,
        lookDirection.x * yawAngularSpeed
    ) * lookIntensity * UnityEngine.Time.deltaTime;
}
else
{
    AngularVelocity = new UnityEngine.Vector2(
        -mouseDelta.y,
        mouseDelta.x
    );
}

// Accumulating the pitch rotation.
AccumulatedPitchRotation += AngularVelocity.x;

// Accumulating the yaw rotation.
AccumulatedYawRotation += AngularVelocity.y;

/*
 * Ensuring that the accumulated pitch rotation is within the limits.
 */
if(AccumulatedPitchRotation.IsGreaterThan(MaxPitchAngle, epsilon: 0.01f))
{
    AngularVelocity = new UnityEngine.Vector2(
        AngularVelocity.x - AccumulatedPitchRotation - MaxPitchAngle,
        AngularVelocity.y
    );

    AccumulatedPitchRotation = MaxPitchAngle;
}
else if(AccumulatedPitchRotation.IsLessThan(MinPitchAngle, epsilon: 0.01f))
{
    AngularVelocity = new UnityEngine.Vector2(
        AngularVelocity.x - AccumulatedPitchRotation - MinPitchAngle,
        AngularVelocity.y
    );

    AccumulatedPitchRotation = MinPitchAngle;
}

/*
 * Ensuring that the accumulated yaw rotation is within the limits.
 */
if(AccumulatedYawRotation.IsGreaterThan(360f, epsilon: 0.01f))
{
    AccumulatedYawRotation -= 360f;
}
else if(AccumulatedYawRotation.IsLessThan(-360f, epsilon: 0.01f))
{
    AccumulatedYawRotation += 360f;
}

// Here you must decide how you want to compute the offset of the torch from the player.
nextOffset = ???

// Updating the torch's offset.
Offset = UnityEngine.Quaternion.Euler(0f,AccumulatedYawRotation,0f) * nextOffset;

// Updating the torch's position.
Torch.transform.position = Torch.FollowTarget.position + Offset;

// Updating the torch's rotation.
Torch.transform.LookAt(Torch.LookAtTarget);

This code isn’t going to work out of the box but gives you a starting point, it is used to implement an orbital camera for a 3rd person game, this is just some of the code executed on LateUpdate.

Additionally it should be done in late update, like camera movement, to be sure that all transforms are synchronized, especially when you want use some interpolation to create a fake lag like you do with Slerp()