Skip to main content

3D preview

Getting the model

You need a model of your car where all the parts you want to animate are lose and movable. You don't need to rig anything on it in Blender.

Orbit camera

To make the orbit camera I used Cinemachine with the CinemachineFreeLook.

To control the camera with the mouse or touch screen I used the old input system, but you can also use the new input system.

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

[RequireComponent(typeof(CinemachineFreeLook))]
public class FreeLookInput : MonoBehaviour
{
private CinemachineFreeLook freeLookCamera;

private string XAxisName = "Mouse X";
private string YAxisName = "Mouse Y";

public float resetDuration = 0.5f; // Duration for setting the rotation

private Coroutine resetCoroutine;

private void Start()
{
freeLookCamera = GetComponent<CinemachineFreeLook>();
freeLookCamera.m_XAxis.m_InputAxisName = "";
freeLookCamera.m_YAxis.m_InputAxisName = "";
}


private void Update()
{
if (Input.GetMouseButton(0) && !Utilities.IsOverUI())
{
freeLookCamera.m_XAxis.m_InputAxisValue = -Input.GetAxis(XAxisName);
freeLookCamera.m_YAxis.m_InputAxisValue = -Input.GetAxis(YAxisName);
}
else
{
freeLookCamera.m_XAxis.m_InputAxisValue = 0;
freeLookCamera.m_YAxis.m_InputAxisValue = 0;
}
}

public void FollowCamView()
{
SetRotation(new Vector2(180f, 0.67f));
}

public void SetRotation(Vector2 targetRotation)
{
if (resetCoroutine != null)
StopCoroutine(resetCoroutine);

resetCoroutine = StartCoroutine(SetRotationSmoothly(targetRotation));
}

IEnumerator SetRotationSmoothly(Vector2 targetRotation)
{
float elapsedTime = 0f;
Vector2 startRotation = new Vector2(freeLookCamera.m_XAxis.Value, freeLookCamera.m_YAxis.Value);

while (elapsedTime < resetDuration)
{
float t = elapsedTime / resetDuration;
freeLookCamera.m_XAxis.Value = Mathf.Lerp(startRotation.x, targetRotation.x, t);
freeLookCamera.m_YAxis.Value = Mathf.Lerp(startRotation.y, targetRotation.y, t);
elapsedTime += Time.deltaTime;
yield return null;
}

freeLookCamera.m_XAxis.Value = targetRotation.x;
freeLookCamera.m_YAxis.Value = targetRotation.y;
}
}

The Utilities class:

public static class Utilities
{
/// <summary>Check if Pointer is over UI</summary>
/// <returns><see cref="bool"/> <see langword="true"/> if Pointer is over UI</returns>
public static bool IsOverUI()
{
PointerEventData pointerEventData = new PointerEventData(EventSystem.current) { position = Input.mousePosition };
List<RaycastResult> results = new List<RaycastResult>();
EventSystem.current.RaycastAll(pointerEventData, results);
return results.Count > 0;
}
}