Making Cinemachine play nice with Rewired

Alright, I’ve finally encountered a problem I can’t even begin to figure out how to solve.

I use Rewired to handle all my player input because the Unity input system becomes quickly cumbersome when it comes to supporting multiple platforms and controller types. Unfortunately, I have no idea how to make it so that the Cinemachine Free Look component uses Rewired instead of the base input system.

I started poking around in the code to see if I could code around this, but quickly found myself lost as I began to navigate deeper and deeper into the various scripts. Eventually I found what I think I need to start changing, but I have no idea how as my scripting knowledge is woefully at a beginner-to-intermediate level, and the concepts at play are a bit beyond me. This is what I found in CinemachineCore.cs:

        /// <summary>Delegate for overriding Unity's default input system.  Returns the value
        /// of the named axis.</summary>
        public delegate float AxisInputDelegate(string axisName);

        /// <summary>Delegate for overriding Unity's default input system.
        /// If you set this, then your delegate will be called instead of
        /// System.Input.GetAxis(axisName) whenever in-game user input is needed.</summary>
        public static AxisInputDelegate GetInputAxis = UnityEngine.Input.GetAxis;

It looks like this is what I need to start changing, but I have no idea how. Any help would be greatly appreciated.

edit: While I’m here, is there a guide to making custom camera behaviours? I’d really like a proper 360 camera orbit like in a 6 DOF third person game and the Free Look camera just isn’t cutting the mustard for a few reasons. It’d be a great bonus if I could have it work with the camera collision system as well.

1 Like
        class MyInputHandler
        {
            [RuntimeInitializeOnLoadMethod]
            static void InitializeModule()
            {
                CinemachineCore.GetInputAxis = GetInput;
            }

            static float GetInput(string name)
            {
                // Do something here to parse name for Rewired
                // then call rewired and return the value
                return 0;
            }
        }

There is no written guide, but I’d be happy to help. Can you give some details about the behaviour you’re looking for?

Just so I don’t completely break anything, I should just stick this in its own script, correct?

Please excuse my lack of editing, I don’t have OBS configured to produce videos in a format Vegas can accept and didn’t want to deal with the hassle of FFMPEG.

https://www.youtube.com/watch?v=DP5XZzWVAHY

As you can see, the camera is simple as can be. It’s basically just a free orbit around the model with no clamping on the x or y value. The code is as follows, if you need. It’s just a pared down version of this script from the wiki.

using UnityEngine;
using Rewired;
using System.Collections;

public class MouseOrbitImproved : MonoBehaviour
{

    public Transform target;
    public float distance = 5.0f;
    public float xSpeed = 120.0f;
    public float ySpeed = 120.0f;

    float x = 0.0f;
    float y = 0.0f;

    Player player;

    // Use this for initialization
    void Start()
    {
        player = ReInput.players.GetPlayer(0);

        Vector3 angles = transform.eulerAngles;
        x = angles.y;
        y = angles.x;
    }

    void LateUpdate()
    {
        if (target)
        {
            x += player.GetAxis("CameraHorizontal") * xSpeed * distance * Time.deltaTime;
            y -= player.GetAxis("CameraVertical") * ySpeed * Time.deltaTime;

            Quaternion rotation = Quaternion.Euler(y, x, 0);

            Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
            Vector3 position = rotation * negDistance + target.position;

            transform.rotation = rotation;
            transform.position = position;
        }
    }
}

Not necessary to do that, since it doesn’t derive from ScriptableObject. You can just put it anywhere.

The simplest way to turn this into a vcam is to add the script as a behaviour to an ordinary vcam, with “Do Nothing” in both Aim and Body. That turns off all the procedural stuff, allowing your script to drive the vcam’s transform.

Doesn’t this invalidate the functionality of the cinemachine collider though?

Actually not. Collider will still work. Amazing, isn’t it :slight_smile:

1 Like

Oh, perfect! I accidentally forgot to set “avoid obstacles” which was causing me the problem! Thanks for all your help!

Awesome Input Catcher! err… “Handler.” However, it does not seem to be abiding by the speed laws I set up for X axis and Y axis… I have to add my own speed laws into the Handler class. That does not seem very DRY :sweat_smile:.

Thanks for Gregoryl.
for those who may still looking into this issue. here is my implementation.

using System.Collections;
using UnityEngine;
using Cinemachine;
using Rewired;

[RequireComponent(typeof(CinemachineFreeLook))]
public class CinemachineRewiredFreeLook : MonoBehaviour
{
    [SerializeField] int m_PlayerId = 0;

    private void Reset() { OnValidate(); }
    private void OnValidate()
    {
        if (Application.isPlaying && ReInput.isReady)
            InitializeInput();
    }

    private IEnumerator Start()
    {
        yield return new WaitUntil(() => ReInput.isReady);
        InitializeInput();
    }

    private void InitializeInput()
    {
        if (ReInput.isReady)
        {
            Player input = ReInput.players.GetPlayer(m_PlayerId);
            CinemachineCore.GetInputAxis = input.GetAxis;
        }
    }
}

public class CinemachineRewiredOverrider
{
    [RuntimeInitializeOnLoadMethod]
    private static void InitializeSystemPlayer()
    {
        CinemachineCore.GetInputAxis = ReInput.players.SystemPlayer.GetAxis;
    }
}

if you only have single player (playerId = 0) in your game. (common case ?)
you can just create the the following script and put it into your project.
without using the above over engineering script :slight_smile:
however the Cinemachine will ONLY listen to player 0.

public class CinemachineRewiredOverrider
{
    [RuntimeInitializeOnLoadMethod]
    private static void InitializeSystemPlayer()
    {
        CinemachineCore.GetInputAxis = ReInput.players.GetPlayer(0).GetAxis;
    }
}
1 Like

Nice one canis!

I would do it like this. This also handles joystick/keyboard camera movement better.

Edit: Code removed. Rewired 1.1.19.0+ includes this integration in the package.

Here’s a link to said Rewired/Cinemachine integration package: Rewired Documentation | Integration with Other Packages

4 Likes