Search Unity

  1. Unity 2018.3 is now released.
    Dismiss Notice
  2. The Unity Pro & Visual Studio Professional Bundle gives you the tools you need to develop faster & collaborate more efficiently. Learn more.
    Dismiss Notice
  3. Want more efficiency in your development work? Sign up to receive weekly tech and creative know-how from Unity experts.
    Dismiss Notice
  4. Build games and experiences that can load instantly and without install. Explore the Project Tiny Preview today!
    Dismiss Notice
  5. Nominations have been announced for this years Unity Awards. Celebrate the wonderful projects made by your peers this year and get voting! Vote here!
    Dismiss Notice
  6. Want to provide direct feedback to the Unity team? Join the Unity Advisory Panel.
    Dismiss Notice
  7. Improve your Unity skills with a certified instructor in a private, interactive classroom. Watch the overview now.
    Dismiss Notice

Making Cinemachine play nice with Rewired

Discussion in 'Cinemachine' started by Murgilod, Feb 14, 2018.

  1. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    4,191
    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:

    Code (CSharp):
    1.         /// <summary>Delegate for overriding Unity's default input system.  Returns the value
    2.         /// of the named axis.</summary>
    3.         public delegate float AxisInputDelegate(string axisName);
    4.  
    5.         /// <summary>Delegate for overriding Unity's default input system.
    6.         /// If you set this, then your delegate will be called instead of
    7.         /// System.Input.GetAxis(axisName) whenever in-game user input is needed.</summary>
    8.         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.
     
    Last edited: Feb 14, 2018
    thatscraigz likes this.
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,831
    Code (CSharp):
    1.         class MyInputHandler
    2.         {
    3.             [RuntimeInitializeOnLoadMethod]
    4.             static void InitializeModule()
    5.             {
    6.                 CinemachineCore.GetInputAxis = GetInput;
    7.             }
    8.  
    9.             static float GetInput(string name)
    10.             {
    11.                 // Do something here to parse name for Rewired
    12.                 // then call rewired and return the value
    13.                 return 0;
    14.             }
    15.         }
    16.  
     
  3. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,831
    There is no written guide, but I'd be happy to help. Can you give some details about the behaviour you're looking for?
     
  4. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    4,191
    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.



    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.

    Code (CSharp):
    1. using UnityEngine;
    2. using Rewired;
    3. using System.Collections;
    4.  
    5. public class MouseOrbitImproved : MonoBehaviour
    6. {
    7.  
    8.     public Transform target;
    9.     public float distance = 5.0f;
    10.     public float xSpeed = 120.0f;
    11.     public float ySpeed = 120.0f;
    12.  
    13.     float x = 0.0f;
    14.     float y = 0.0f;
    15.  
    16.     Player player;
    17.  
    18.     // Use this for initialization
    19.     void Start()
    20.     {
    21.         player = ReInput.players.GetPlayer(0);
    22.  
    23.         Vector3 angles = transform.eulerAngles;
    24.         x = angles.y;
    25.         y = angles.x;
    26.     }
    27.  
    28.     void LateUpdate()
    29.     {
    30.         if (target)
    31.         {
    32.             x += player.GetAxis("CameraHorizontal") * xSpeed * distance * Time.deltaTime;
    33.             y -= player.GetAxis("CameraVertical") * ySpeed * Time.deltaTime;
    34.  
    35.             Quaternion rotation = Quaternion.Euler(y, x, 0);
    36.  
    37.             Vector3 negDistance = new Vector3(0.0f, 0.0f, -distance);
    38.             Vector3 position = rotation * negDistance + target.position;
    39.  
    40.             transform.rotation = rotation;
    41.             transform.position = position;
    42.         }
    43.     }
    44. }
     
  5. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,831
    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.
     
  6. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    4,191
    Doesn't this invalidate the functionality of the cinemachine collider though?
     
  7. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    1,831
    Actually not. Collider will still work. Amazing, isn't it :)
     
    MikeFish likes this.
  8. Murgilod

    Murgilod

    Joined:
    Nov 12, 2013
    Posts:
    4,191
    Oh, perfect! I accidentally forgot to set "avoid obstacles" which was causing me the problem! Thanks for all your help!
     
  9. StarFluke

    StarFluke

    Joined:
    Jan 19, 2013
    Posts:
    22
    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 :oops:.
     
  10. canis

    canis

    Joined:
    Oct 25, 2013
    Posts:
    44
    Thanks for Gregoryl.
    for those who may still looking into this issue. here is my implementation.

    Code (CSharp):
    1.  
    2. using System.Collections;
    3. using UnityEngine;
    4. using Cinemachine;
    5. using Rewired;
    6.  
    7. [RequireComponent(typeof(CinemachineFreeLook))]
    8. public class CinemachineRewiredFreeLook : MonoBehaviour
    9. {
    10.     [SerializeField] int m_PlayerId = 0;
    11.  
    12.     private void Reset() { OnValidate(); }
    13.     private void OnValidate()
    14.     {
    15.         if (Application.isPlaying && ReInput.isReady)
    16.             InitializeInput();
    17.     }
    18.  
    19.     private IEnumerator Start()
    20.     {
    21.         yield return new WaitUntil(() => ReInput.isReady);
    22.         InitializeInput();
    23.     }
    24.  
    25.     private void InitializeInput()
    26.     {
    27.         if (ReInput.isReady)
    28.         {
    29.             Player input = ReInput.players.GetPlayer(m_PlayerId);
    30.             CinemachineCore.GetInputAxis = input.GetAxis;
    31.         }
    32.     }
    33. }
    34.  
    35. public class CinemachineRewiredOverrider
    36. {
    37.     [RuntimeInitializeOnLoadMethod]
    38.     private static void InitializeSystemPlayer()
    39.     {
    40.         CinemachineCore.GetInputAxis = ReInput.players.SystemPlayer.GetAxis;
    41.     }
    42. }
    43.  
    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 :)
    however the Cinemachine will ONLY listen to player 0.

    Code (CSharp):
    1. public class CinemachineRewiredOverrider
    2. {
    3.     [RuntimeInitializeOnLoadMethod]
    4.     private static void InitializeSystemPlayer()
    5.     {
    6.         CinemachineCore.GetInputAxis = ReInput.players.GetPlayer(0).GetAxis;
    7.     }
    8. }
     
    Last edited: May 19, 2018
  11. StarFluke

    StarFluke

    Joined:
    Jan 19, 2013
    Posts:
    22
    Nice one canis!
     
  12. guavaman

    guavaman

    Joined:
    Nov 20, 2009
    Posts:
    3,362
    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.
     
    Last edited: Nov 2, 2018
  13. eyeballTickler

    eyeballTickler

    Joined:
    Jun 13, 2015
    Posts:
    3
    guavaman and Gregoryl like this.