# Mobile Steering Wheel Controller - problem

Hello guys,

I’ve been struggling with a Steering Wheel Controller for mobile using touch input.

The problem:

• being able to have the steering wheel sprite rotate between -300 and 300 degrees because it only goes between 0 and 360 (359 + 1 will get it back to 0 degrees)
• that means that I can’t have a steering wheel that can rotate 1 and a half times to the left and right

What I tried:

• instead of modifying the sprite.eulerAngles.z which just loops around, I’ve created a Vector3 rotation, adding to it delta angle rotation, then using sprite.eulerAngles = rotation; as shown below.

Old:

``````                steeringRect.eulerAngles = new Vector3(0, 0, angle);
``````

New:

``````                if (rotOld == rotDefault)
{
rotOld = angle;
}
rotDelta = angle - rotOld;
rotAngle += rotDelta;
rotation.z = rotAngle; //Mathf.Clamp(rotAngle, -300, 300); - REMOVED CLAMP SO I CAN TEST BETTER
steeringRect.eulerAngles = rotation;
rotOld = angle;
``````

Problems with what I tried:

• rotating steering to the left results in positive delta rotation. Adding that to the Vector3 rotation however results sometimes in a decreasing angle. How??? If delta is showing positive, I’m adding positive to rotation.z, how is it possible to sometimes have a decreasing value?

I feel like I’ve changed so much and tried so many aproaches of the same thing that it became a mess.

My goal is to have the rotation clamped between -300 and 300 degrees. Return to 0 when released. Simple as that. But I can’t wrap my head around a fix…

YouTube link to the problem: (it looks like adding delta rotation is the same as just setting the rotation.z to angle)

Full script:

``````using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class SteeringWheel : MonoBehaviour
{
public GameObject steeringWheel;
public GameObject test;
public float returnTime;
public TextMeshProUGUI baseAngleText;
public TextMeshProUGUI angleText;
public TextMeshProUGUI rotAngleText;
public TextMeshProUGUI spriteRotText;
public TextMeshProUGUI deltaRotText;

private RectTransform steeringRect;
private bool steering;
private bool returningSteering;
private int touchID;

private Vector3 rotation;
private float rotDefault = 9696;
private float rotOld;
private float rotDelta;
private float rotAngle;

private float baseAngle;
private float angle;

// Start is called before the first frame update
void Start()
{
rotOld = rotDefault;
steeringRect = steeringWheel.GetComponent<RectTransform>();
}

// Update is called once per frame
void Update()
{
for (int i = 0; i < Input.touchCount; i++)
{
Touch touch = Input.GetTouch(i);

//IF TOUCHING THE STEERING WHEEL
Vector2 localTouchPosition = steeringRect.InverseTransformPoint(touch.position);
if (steeringRect.rect.Contains(localTouchPosition))
{
steering = true;
touchID = touch.fingerId;

//STOP RETURNING IF TOUCHED AGAIN
if (returningSteering)
{
returningSteering = false;
StopCoroutine("ReturnSteeringWheel");
}

//GET BASE ANGLE BASED ON FIRST TOUCH
if (touch.phase == TouchPhase.Began && touch.fingerId == touchID)
{
Vector2 dir = touch.position - (Vector2)steeringRect.position;
baseAngle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90 + rotation.z;
rotAngle = rotation.z;
}
}

if (steering && touch.fingerId == touchID)
{
//CALCULATING ANGLE TO ROTATE BY
Vector2 dir = touch.position - (Vector2)steeringRect.position;
angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg - 90 - baseAngle;
if ((Mathf.Round(angle * 10) / 10 == 0)){
angle = 0;
}

//TRIED TO ADD THE ANGLE IN ANOTHER VECTOR3 SO IT COULD EXCEED THE VALUE OF 360
if (rotOld == rotDefault)
{
rotOld = angle;
}
rotDelta = angle - rotOld;
rotAngle += rotDelta;
rotation.z = rotAngle; //Mathf.Clamp(rotAngle, -300, 300); - REMOVED CLAMP SO I CAN TEST BETTER
steeringRect.eulerAngles = rotation;
rotOld = angle;

steeringRect.eulerAngles = new Vector3(0, 0, angle);
}

if (touch.phase == TouchPhase.Ended && touch.fingerId == touchID)
{
rotOld = rotDefault;
steering = false;
returningSteering = true;
StartCoroutine("ReturnSteeringWheel");
}
}
baseAngleText.text = "Base angle: " + baseAngle.ToString();
angleText.text = "Calculated angle: " + angle.ToString();
deltaRotText.text = "Delta rotation: " + rotDelta.ToString();
rotAngleText.text = "Vector3 added delta: " + rotAngle.ToString();
spriteRotText.text = "Sprite angle: " + steeringRect.eulerAngles.z.ToString();
}

private IEnumerator ReturnSteeringWheel()
{
while(rotation.z  != 0)
{
rotation = Vector3.MoveTowards(rotation, new Vector3(0, 0, 0), Time.deltaTime * returnTime);
steeringRect.eulerAngles = rotation;
yield return null;
}
}
}
``````

I hope I described my problem well. If I did not, please tell me…
Thank you

The way to do this is to change what is storing the left/right and make it a single float variable that can go from -300 to +300.

Modify your control logic to only adjust that float (by however fast you want) and to keep it within -300 to +300.

Then set your steering wheel rotation by setting the rotation to `Quaternion.Euler( 0, 0, angle);`

It can even go from -1000 to +1000 or whatever you want. The steering wheel will go around and around and be “correct” throughout that range.