Starting with Lumberyard Input – Part 2

On part1 of this series, we got our character moving based on the keyboard input. This tutorial will be focused on getting it to work with mouse interaction.

Mouse requires more work because we need to rotate the player entity for left right, and the camera entity on up and down. If you image you are standing, you can rotate your body to turn different directions, but you just rotate your head to look up and down.

Capturing the Mouse Rotation

First lets add some stuff to our class definition’s private section (naughty?)


void PerformRotation(const AzFramework::InputChannel& inputChannel);
void TrackMouseMovement(const AzFramework::InputChannel::PositionData2D* position_data);

AZ::Vector2 m_lastMousePosition{.5f, .5f};
AZ::Vector2 m_mouseChangeAggregate{0, 0};
float RotationSpeed = 5.f;

PerformRotation and TrackMouseMovements are helper functions which will be explained later.
m_lastMousePosition is the last position of the mouse normalized (from 0 to 1).
m_mouseChangeAggregate is the hard one to understand. It’s basically the aggregated amount of change that you have moved your mouse. It’s used to derive rotation.
RotationSpeed will be another value that we can define in the editor but will default to 5.

In the source file, we first need to update our reflection to include the RotationSpeed.

    ->Field("Movement scale", &TutorialSeriesCharacterComponent::MovementScale)
    ->Field("Rotation Speed", &TutorialSeriesCharacterComponent::RotationSpeed);

if (auto editContext = serializationContext->GetEditContext())
    editContext->Class<TutorialSeriesCharacterComponent>("TutorialSeriesCharacterComponent", "Main controller component")
        ->ClassElement(AZ::Edit::ClassElements::EditorData, "")
        ->Attribute(AZ::Edit::Attributes::Category, "TutorialSeries")
        ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game"))
        ->DataElement(nullptr, &TutorialSeriesCharacterComponent::MovementScale, "Movement scale&quot;, "How fast the character moves&quot;)
        ->DataElement(nullptr, &amp;TutorialSeriesCharacterComponent::RotationSpeed, "Rotation Speed", "The speed multiplier to apply to mouse rotation");

Next we need to add the handling of the input to track their mouse movements to use for rotation later.


void TutorialSeriesCharacterComponent::OnMouseEvent(const InputChannel &amp;inputChannel)
    auto input_type = inputChannel.GetInputChannelId();
    if (input_type == InputDeviceMouse::SystemCursorPosition)

void TutorialSeriesCharacterComponent::PerformRotation(const InputChannel &amp;inputChannel)
    auto position_data = inputChannel.GetCustomData&lt;InputChannel::PositionData2D&gt;();

void TutorialSeriesCharacterComponent::TrackMouseMovement(const InputChannel::PositionData2D *position_data)
    auto deltaMousePosition = m_lastMousePosition - position_data-&gt;m_normalizedPosition;
    m_lastMousePosition = position_data-&gt;m_normalizedPosition;
    m_mouseChangeAggregate += deltaMousePosition;

Lets discuss the line, auto position_data = inputChannel.GetCustomData(); The derived type of this InputChannel for mouse position is InputChannelDeltaWithSharedPosition2D. The main special thing about this derived type is that it keeps track of the delta in movement, and it has a Position vector that comes with it. To access that position vector, it uses the GetCustomData function provided on the InputChannel interface.

TrackMouseMovement gets the delta of mouse movement, and adds it to our aggregate which will determine our total rotation later.

So now we are tracking the total aggregate amount they have moved their mouse around. Compile and run it to make sure nothing breaks. Nothing new will happen of course until we actually rotate some entities.

Rotating the Player (and Therefore the Camera)

Since we made the Player entity the parent of the Camera entity, if we rotate the Player, it will rotate the camera automagically.

To do this, we have to do some magic in the OnTick.


void TutorialSeriesCharacterComponent::OnTick(float deltaTime, AZ::ScriptTimePoint time)
    AZ::Transform entityTransform;
    EBUS_EVENT_ID_RESULT(entityTransform, GetEntityId(), AZ::TransformBus, GetWorldTM);

    EBUS_EVENT_ID(GetEntityId(), AZ::TransformBus, SetWorldTM, entityTransform);

    auto desiredVelocity = AZ::Vector3::CreateZero();
    if (movingForward || movingBack || strafingLeft || strafingRight)

    // Apply relative translation to the character via physics.
    EBUS_EVENT_ID(GetEntityId(), LmbrCentral::CryCharacterPhysicsRequestBus, RequestVelocity, desiredVelocity, 0);

const AZ::Quaternion TutorialSeriesCharacterComponent::GetCurrentOrientation()
    auto z_rotation = AZ::Quaternion::CreateRotationZ(m_mouseChangeAggregate.GetX() * RotationSpeed);
    return z_rotation;

We added line 5 and 6 and the new GetCurrentOrientation function (be sure to add it to the header.)

For now we are only using the left/right value (x value) of the mouse position. We simply grab this entity’s transform, apply the rotation, and set the entity’s transform.

Compile and run! You should now be able to rotate your character with your mouse.

Unfortunately there are a slew of problems.
* You can’t determine which direction you move.
* The mouse eventually hits the edge of the window and you can’t rotate anymore.
* Obviously, no looking up and down

Check out the next part of this series where we start to fix these issues.

3 thoughts on “Starting with Lumberyard Input – Part 2

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s