Mobile Joystick and Cinemachine Touch Input

Hey, I’m trying to make use of the Cinemachine free look for mobile, but the touch input (Mouse X/Y) interferes with the standard assets joystick H/V axes, controlling both at the same time. I’ve looked into Event.Use() with no luck, how do I fix this?

Can you set up new input channels to drive your CM camera? Don’t use the standard ones.

Hi,

Are you getting anywhere with this? let me know.

Bye,

Jean

Hey @Jean-Fabre , apologies for not replying sooner. I’m still having trouble fixing the problem. I’ve tried isolating the CM freelook input to Unity’s touch pad Standard asset prefab, but the camera was unresponsive.

@Gregoryl I duplicated the Mouse Y & Mouse X (input manager) and renamed them to Touch Y & Touch X. From there, i changed the Freelook axis input’s to Touch X/Y, that was also not moving the camera.

@Jean-Fabre i’ve seen mobile games like Honkai Impact 3rd isolate Camera controls to the right half of the screen. Is there a way i can get CinemachineCore to override via touch pad/Ui Sprite? Unity’ touch pad prefab looks like this:

using System;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;

namespace UnityStandardAssets.CrossPlatformInput
{
    [RequireComponent(typeof(Image))]
    public class TouchPad : MonoBehaviour, IPointerDownHandler, IPointerUpHandler
    {
        // Options for which axes to use
        public enum AxisOption
        {
            Both, // Use both
            OnlyHorizontal, // Only horizontal
            OnlyVertical // Only vertical
        }


        public enum ControlStyle
        {
            Absolute, // operates from the center of the image
            Relative, // operates from the center of the initial touch
            Swipe, // swipe to touch touch no maintained center
        }


        public AxisOption axesToUse = AxisOption.Both; // The options for the axes that the still will use
        public ControlStyle controlStyle = ControlStyle.Absolute; // control style to use
        public string horizontalAxisName = "Horizontal"; // The name given to the horizontal axis for the cross platform input
        public string verticalAxisName = "Vertical"; // The name given to the vertical axis for the cross platform input
        public float Xsensitivity = 1f;
        public float Ysensitivity = 1f;

        Vector3 m_StartPos;
        Vector2 m_PreviousDelta;
        Vector3 m_JoytickOutput;
        bool m_UseX; // Toggle for using the x axis
        bool m_UseY; // Toggle for using the Y axis
        CrossPlatformInputManager.VirtualAxis m_HorizontalVirtualAxis; // Reference to the joystick in the cross platform input
        CrossPlatformInputManager.VirtualAxis m_VerticalVirtualAxis; // Reference to the joystick in the cross platform input
        bool m_Dragging;
        int m_Id = -1;
        Vector2 m_PreviousTouchPos; // swipe style control touch


#if !UNITY_EDITOR
    private Vector3 m_Center;
    private Image m_Image;
#else
        Vector3 m_PreviousMouse;
#endif

        void OnEnable()
        {
            CreateVirtualAxes();
        }

        void Start()
        {

#if !UNITY_EDITOR
            m_Image = GetComponent<Image>();
            m_Center = m_Image.transform.position;
#endif
        }

        void CreateVirtualAxes()
        {
            // set axes to use
            m_UseX = (axesToUse == AxisOption.Both || axesToUse == AxisOption.OnlyHorizontal);
            m_UseY = (axesToUse == AxisOption.Both || axesToUse == AxisOption.OnlyVertical);

            // create new axes based on axes to use
            if (m_UseX)
            {
                m_HorizontalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(horizontalAxisName);
                CrossPlatformInputManager.RegisterVirtualAxis(m_HorizontalVirtualAxis);
            }
            if (m_UseY)
            {
                m_VerticalVirtualAxis = new CrossPlatformInputManager.VirtualAxis(verticalAxisName);
                CrossPlatformInputManager.RegisterVirtualAxis(m_VerticalVirtualAxis);
            }
        }

        void UpdateVirtualAxes(Vector3 value)
        {
            value = value.normalized;
            if (m_UseX)
            {
                m_HorizontalVirtualAxis.Update(value.x);
            }

            if (m_UseY)
            {
                m_VerticalVirtualAxis.Update(value.y);
            }
        }


        public void OnPointerDown(PointerEventData data)
        {
            m_Dragging = true;
            m_Id = data.pointerId;
#if !UNITY_EDITOR
        if (controlStyle != ControlStyle.Absolute )
            m_Center = data.position;
#endif
        }

        void Update()
        {
            if (!m_Dragging)
            {
                return;
            }
            if (Input.touchCount >= m_Id + 1 && m_Id != -1)
            {
#if !UNITY_EDITOR

            if (controlStyle == ControlStyle.Swipe)
            {
                m_Center = m_PreviousTouchPos;
                m_PreviousTouchPos = Input.touches[m_Id].position;
            }
            Vector2 pointerDelta = new Vector2(Input.touches[m_Id].position.x - m_Center.x , Input.touches[m_Id].position.y - m_Center.y).normalized;
            pointerDelta.x *= Xsensitivity;
            pointerDelta.y *= Ysensitivity;
#else
                Vector2 pointerDelta;
                pointerDelta.x = Input.mousePosition.x - m_PreviousMouse.x;
                pointerDelta.y = Input.mousePosition.y - m_PreviousMouse.y;
                m_PreviousMouse = new Vector3(Input.mousePosition.x, Input.mousePosition.y, 0f);
#endif
                UpdateVirtualAxes(new Vector3(pointerDelta.x, pointerDelta.y, 0));
            }
        }


        public void OnPointerUp(PointerEventData data)
        {
            m_Dragging = false;
            m_Id = -1;
            UpdateVirtualAxes(Vector3.zero);
        }

        void OnDisable()
        {
            if (CrossPlatformInputManager.AxisExists(horizontalAxisName))
                CrossPlatformInputManager.UnRegisterVirtualAxis(horizontalAxisName);

            if (CrossPlatformInputManager.AxisExists(verticalAxisName))
                CrossPlatformInputManager.UnRegisterVirtualAxis(verticalAxisName);
        }
    }
}

Hi,

yes, you can do that, take over the cinemachine input and feed this with the on screen joystick system

have you checked
CinemachineCoreGetInputTouchAxis.cs component?

simply replace the touch input feeds with your on screen joystick values, also, you will likely want to change the way the input works, as mouse/touch input are absolute movement, but you may want your on screen joystick to move the camera in relative mode ( that is, if you keep the joystick left, the camera will keep rotating). But that’s already in the second phase of the implementation, first, modify CinemachineCoreGetInputTouchAxis.cs to react to your on screen joystick somehow.

Bye,

Jean

1 Like

Looking to setup up something very similar to this in the new inputer system. On-screen joystick for movement and touch for camera orbit.

Probably the #1 character control system for mobile. Would be great to have a tangible example from our Unity overlords to adopt this quicker!

1 Like

@Blarp , here is the modification from the CinemachineGetInputTouchAxis.cs, I’ve created to make the cinemachine works with the CrossPlatformInput touch control from the StandardAssets. Just attach it to the Cinemachine virtual camera (free look or 3rd person cam), and the touch screen joystic with axes set to Mouse X and Mouse Y will drive the Cinemachine Camera, hope this helps!

using Cinemachine;
using UnityEngine;
using UnityStandardAssets.CrossPlatformInput;

/// <summary>
/// This is an add-on behaviour that globally maps the touch control
/// to standard input channels, such as mouse X and mouse Y.
/// Drop it on any game object in your scene.
/// </summary>
public class CinemachineCrossPlatformInput : MonoBehaviour
{
    /// <summary>Sensitivity multiplier for x-axis</summary>
    [Tooltip("Sensitivity multiplier for x-axis")]
    public float TouchSensitivityX = 3f;

    /// <summary>Sensitivity multiplier for y-axis</summary>
    [Tooltip("Sensitivity multiplier for y-axis")]
    public float TouchSensitivityY = 3f;

    /// <summary>Input channel to spoof for X axis</summary>
    [Tooltip("Input channel to spoof for X axis")]
    public string TouchXInputMapTo = "Mouse X";

    /// <summary>Input channel to spoof for Y axis</summary>
    [Tooltip("Input channel to spoof for Y axis")]
    public string TouchYInputMapTo = "Mouse Y";

    void Start()
    {
        CinemachineCore.GetInputAxis = GetInputAxis;
    }

    private float GetInputAxis(string axisName)
    {
        if (axisName == TouchXInputMapTo)
            return CrossPlatformInputManager.GetAxis(TouchXInputMapTo) * TouchSensitivityX;
        if (axisName == TouchYInputMapTo)
            return CrossPlatformInputManager.GetAxis(TouchYInputMapTo) * TouchSensitivityY;

        return CrossPlatformInputManager.GetAxis(axisName);
    }
}
4 Likes