Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice
  3. Join us on November 16th, 2023, between 1 pm and 9 pm CET for Ask the Experts Online on Discord and on Unity Discussions.
    Dismiss Notice
  4. Dismiss Notice

First Person Shooter - How to rotate the character and child objects (i.e gun)?

Discussion in 'Cinemachine' started by JacketPotatoeFan, Jun 25, 2019.

  1. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    Been tackling this for a few days and finally gave in and am asking for some help.

    Below is an image of what my hierarchy looks like.

    https://i.imgur.com/QvaF220.png

    - Main Camera has a Cinemachine Brain component.
    - FPOV has a Cinemachine Virtual Camera component where the Aim is set to "POV".

    I have a custom Camera controller (basically a bridge between the new Input System) which passes some data to the virtual camera (sensitivity, input x/y etc). This all works fine. The Main Camera rotates correctly, I can look around freely. The VCam handles rotating the Main Camera without me needed to code all that, which is pretty cool.

    Here's what I am trying to do next. I need to handle rotating the actually player ("First Person" GameObject), and the Gun. The player should not rotate on the X axis, but the Gun should (so if you look up, the Gun will follow, but the player will not).

    I have tried copying over the rotation data from the main camera, but things go way out of control (spinning etc). Am not sure what else to do now. I am trying to avoid separate rotation logic, since the Virtual Camera is already doing it for me.

    Hope someone can give me some advice.

    Thanks

    Edit: I got it rotating, but it stutters. Am not good with rotation stuff, find it quite confusing, so not sure what to do next. Making progress though (think).

    Here is the code for rotation the player object and weapon.

    Code (csharp):
    1. player.eulerAngles = new Vector3(0, maincam.transform.rotation.eulerAngles.y, 0);
    2. weapon.localEulerAngles = new Vector3(maincam.transform.rotation.eulerAngles.x, maincam.transform.rotation.eulerAngles.y, 0);
     
    Last edited: Jun 25, 2019
  2. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,238
    You want the player to always rotate in Y along with the vcam (but not x), but have the weapon fully rotate with the vcam (X and Y), is that right?

    You want to avoid creating feedback loops (POV rotates the vcam, which rotates the main cam, then your script apples that to the player, which because of parenting rotates the vcam some more).

    Better to disconnect the input from POV horizontal, use only the vertical.

    Handle the horizontal rotation yourself, move the player only (which will move the vcam, which will move the camera). Don't read back the camera value to rotate the player, let the player drive the camera, not the other way around.

    Then grab vcam.State.CorrectedRotation, and set the weapon's rotation to that. Don't read the vcam's transform, read the vcam's State.
     
    Last edited: Jul 16, 2019
  3. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    Hey, thanks for replying.

    Yes to your first question, that is exactly what I want to do.

    I'll be honest, you lost me a little with the rest. I'm sorry. Only started playing with Cinemachine a few days ago.

    So I modified the hierarchy a little so that the player mesh is now a child. So now it looks more like this...

    - Main Camera
    - First Person (my camera controller script is on this, and also the controller to move the character will be here)
    -- VCams (child vcams in here (walk, sprint etc, from reading previous posts by you and your team))
    -- Player Mesh (this I would like to rotate it's Y axis only (Up)).
    -- Gun (ignore this for now, once i figure out rotating the player mesh, this should be easy)

    Probably should show an image. Basically Main Camera is out on it's own.

    For the moment I am just working on freely looking around, so there is no actual player movement. But I will take your advice and not move the camera directly when I work on that part.

    Right now, I am probably doing it the wrong way by copying the Y rotation from the main camera directly. It works, but it stutters.

    I would like to somehow grab whatever value the Cinemachine component is setting on the camera so it all synced and smooth. I was hoping to avoid writing separate code to do handle rotations, since Cinemachine does it all so nicely.

    I am using Cinemachine 2.3.4 and don't see access to a "CorrectedRotation" property.

    Thanks.

    Edit: I think you meant "CorrectedOrientation" right? If so, I am not sure how to use that. I see it's a Quanternion.
     
    Last edited: Jun 25, 2019
  4. Gregoryl

    Gregoryl

    Unity Technologies

    Joined:
    Dec 22, 2016
    Posts:
    7,238
    I would set up the game objects like this:
    • Main Camera (with CM Brain)
    • First person - with script to control position and Y rotation
      • Player mesh (will move and rotate with parent)
    • vcam - StateDrivenCamera
      • idle vcam: Body = transposer to track First Person, LockToTargetWithWorldUp binding; Composer = POV with no X axis input
      • walk vcam, similar set-up
      • etc
    Not too sure how to handle the gun - that depends on how you want it to behave. If you always want it fixed in the exact same screen position, you could make it a child of the Main Camera.

    Yes, I meant CorrectedOrientation. Although, I should have said FinalOrientation. That one's probably best. It gives the worldspace rotation that will be applied to the main camera (noise, dutch, etc all factored in). If you want the camera noise to not apply to the gun (so gun's position will not be absolutely fixed on screen), you could make a script to do
    Code (CSharp):
    1. weapon.transform.position = brain.ActiveVirtualCamera.State.RawPosition;
    2. weapon.transform.rotation = brain.ActiveVirtualCamera.State.RawOrientation;
     
    JacketPotatoeFan likes this.
  5. JacketPotatoeFan

    JacketPotatoeFan

    Joined:
    Nov 23, 2016
    Posts:
    34
    Sorry for taking so long to reply, was out of town on business.

    With your help I managed to get it all working nicely. Thanks a ton.
     
    Gregoryl likes this.