Search Unity

Offset the camera within the Unity assets FPSController Script

Discussion in 'Scripting' started by denissuu, Feb 14, 2020.

  1. denissuu

    denissuu

    Joined:
    Nov 6, 2019
    Posts:
    162
    Hi there everyone! I am using the unity standard assets pack, and I want to make my character's camera to be offset on the Z axis by a certain value, so it isn't inside the actual capsule that is the player, as that messes up my Occlusion Culling when you are against walls.But I can't seem to find where I'm supposed to implement my new position in those scripts.

    Here is the code from the scripts so you don't have to import the assets by yourselves :


    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityStandardAssets.CrossPlatformInput;
    4.  
    5. namespace UnityStandardAssets.Characters.FirstPerson
    6. {
    7.     [RequireComponent(typeof(Rigidbody))]
    8.     [RequireComponent(typeof(CapsuleCollider))]
    9.     public class RigidbodyFirstPersonController : MonoBehaviour
    10.     {
    11.  
    12.  
    13.         [Serializable]
    14.         public class MovementSettings
    15.         {
    16.             public float ForwardSpeed = 8.0f;   // Speed when walking forward
    17.             public float BackwardSpeed = 4.0f;  // Speed when walking backwards
    18.             public float StrafeSpeed = 4.0f;    // Speed when walking sideways
    19.             public float RunMultiplier = 2.0f;   // Speed when sprinting
    20.             public KeyCode RunKey = KeyCode.LeftShift;
    21.             public float JumpForce = 30f;
    22.             public AnimationCurve SlopeCurveModifier = new AnimationCurve(new Keyframe(-90.0f, 1.0f), new Keyframe(0.0f, 1.0f), new Keyframe(90.0f, 0.0f));
    23.             [HideInInspector] public float CurrentTargetSpeed = 8f;
    24.  
    25. #if !MOBILE_INPUT
    26.             private bool m_Running;
    27. #endif
    28.  
    29.             public void UpdateDesiredTargetSpeed(Vector2 input)
    30.             {
    31.                 if (input == Vector2.zero) return;
    32.                 if (input.x > 0 || input.x < 0)
    33.                 {
    34.                     //strafe
    35.                     CurrentTargetSpeed = StrafeSpeed;
    36.                 }
    37.                 if (input.y < 0)
    38.                 {
    39.                     //backwards
    40.                     CurrentTargetSpeed = BackwardSpeed;
    41.                 }
    42.                 if (input.y > 0)
    43.                 {
    44.                     //forwards
    45.                     //handled last as if strafing and moving forward at the same time forwards speed should take precedence
    46.                     CurrentTargetSpeed = ForwardSpeed;
    47.                 }
    48. #if !MOBILE_INPUT
    49.                 if (Input.GetKey(RunKey))
    50.                 {
    51.                     CurrentTargetSpeed *= RunMultiplier;
    52.                     m_Running = true;
    53.                 }
    54.                 else
    55.                 {
    56.                     m_Running = false;
    57.                 }
    58. #endif
    59.             }
    60.  
    61. #if !MOBILE_INPUT
    62.             public bool Running
    63.             {
    64.                 get { return m_Running; }
    65.             }
    66. #endif
    67.         }
    68.  
    69.  
    70.         [Serializable]
    71.         public class AdvancedSettings
    72.         {
    73.             public float groundCheckDistance = 0.01f; // distance for checking if the controller is grounded ( 0.01f seems to work best for this )
    74.             public float stickToGroundHelperDistance = 0.5f; // stops the character
    75.             public float slowDownRate = 20f; // rate at which the controller comes to a stop when there is no input
    76.             public bool airControl; // can the user control the direction that is being moved in the air
    77.             [Tooltip("set it to 0.1 or more if you get stuck in wall")]
    78.             public float shellOffset; //reduce the radius by that ratio to avoid getting stuck in wall (a value of 0.1f is nice)
    79.         }
    80.  
    81.  
    82.         public Camera cam;
    83.         public MovementSettings movementSettings = new MovementSettings();
    84.         public MouseLook mouseLook = new MouseLook();
    85.         public AdvancedSettings advancedSettings = new AdvancedSettings();
    86.  
    87.  
    88.         private Rigidbody m_RigidBody;
    89.         private CapsuleCollider m_Capsule;
    90.         private float m_YRotation;
    91.         private Vector3 m_GroundContactNormal;
    92.         private bool m_Jump, m_PreviouslyGrounded, m_Jumping, m_IsGrounded;
    93.  
    94.         [HideInInspector]
    95.         public Vector2 runAxis;
    96.  
    97.  
    98.         public Vector3 Velocity
    99.         {
    100.             get { return m_RigidBody.velocity; }
    101.         }
    102.  
    103.         public bool Grounded
    104.         {
    105.             get { return m_IsGrounded; }
    106.         }
    107.  
    108.         public bool Jumping
    109.         {
    110.             get { return m_Jumping; }
    111.         }
    112.  
    113.         public bool Running
    114.         {
    115.             get
    116.             {
    117. #if !MOBILE_INPUT
    118.                 return movementSettings.Running;
    119. #else
    120.                 return false;
    121. #endif
    122.             }
    123.         }
    124.  
    125.  
    126.         private void Start()
    127.         {
    128.             m_RigidBody = GetComponent<Rigidbody>();
    129.             m_Capsule = GetComponent<CapsuleCollider>();
    130.             mouseLook.Init (transform, cam.transform);
    131.         }
    132.  
    133.  
    134.         private void Update()
    135.         {
    136.             RotateView();
    137.  
    138.             if (CrossPlatformInputManager.GetButtonDown("Jump") && !m_Jump)
    139.             {
    140.                 m_Jump = true;
    141.             }
    142.         }
    143.  
    144.  
    145.         private void FixedUpdate()
    146.         {
    147.             GroundCheck();
    148.             Vector2 input = GetInput();
    149.  
    150.             if ((Mathf.Abs(input.x) > float.Epsilon || Mathf.Abs(input.y) > float.Epsilon) && (advancedSettings.airControl || m_IsGrounded))
    151.             {
    152.                 // always move along the camera forward as it is the direction that it being aimed at
    153.                 Vector3 desiredMove = cam.transform.forward*input.y + cam.transform.right*input.x;
    154.                 desiredMove = Vector3.ProjectOnPlane(desiredMove, m_GroundContactNormal).normalized;
    155.  
    156.                 desiredMove.x = desiredMove.x*movementSettings.CurrentTargetSpeed;
    157.                 desiredMove.z = desiredMove.z*movementSettings.CurrentTargetSpeed;
    158.                 desiredMove.y = desiredMove.y*movementSettings.CurrentTargetSpeed;
    159.                 if (m_RigidBody.velocity.sqrMagnitude <
    160.                     (movementSettings.CurrentTargetSpeed*movementSettings.CurrentTargetSpeed))
    161.                 {
    162.                     m_RigidBody.AddForce(desiredMove*SlopeMultiplier(), ForceMode.Impulse);
    163.                 }
    164.             }
    165.  
    166.             if (m_IsGrounded)
    167.             {
    168.                 m_RigidBody.drag = 5f;
    169.  
    170.                 if (m_Jump)
    171.                 {
    172.                     m_RigidBody.drag = 0f;
    173.                     m_RigidBody.velocity = new Vector3(m_RigidBody.velocity.x, 0f, m_RigidBody.velocity.z);
    174.                     m_RigidBody.AddForce(new Vector3(0f, movementSettings.JumpForce, 0f), ForceMode.Impulse);
    175.                     m_Jumping = true;
    176.                 }
    177.  
    178.                 if (!m_Jumping && Mathf.Abs(input.x) < float.Epsilon && Mathf.Abs(input.y) < float.Epsilon && m_RigidBody.velocity.magnitude < 1f)
    179.                 {
    180.                     m_RigidBody.Sleep();
    181.                 }
    182.             }
    183.             else
    184.             {
    185.                 m_RigidBody.drag = 0f;
    186.                 if (m_PreviouslyGrounded && !m_Jumping)
    187.                 {
    188.                     StickToGroundHelper();
    189.                 }
    190.             }
    191.             m_Jump = false;
    192.         }
    193.  
    194.  
    195.         private float SlopeMultiplier()
    196.         {
    197.             float angle = Vector3.Angle(m_GroundContactNormal, Vector3.up);
    198.             return movementSettings.SlopeCurveModifier.Evaluate(angle);
    199.         }
    200.  
    201.  
    202.         private void StickToGroundHelper()
    203.         {
    204.             RaycastHit hitInfo;
    205.             if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
    206.                                    ((m_Capsule.height/2f) - m_Capsule.radius) +
    207.                                    advancedSettings.stickToGroundHelperDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
    208.             {
    209.                 if (Mathf.Abs(Vector3.Angle(hitInfo.normal, Vector3.up)) < 85f)
    210.                 {
    211.                     m_RigidBody.velocity = Vector3.ProjectOnPlane(m_RigidBody.velocity, hitInfo.normal);
    212.                 }
    213.             }
    214.         }
    215.  
    216.  
    217.         private Vector2 GetInput()
    218.         {
    219.          
    220.             Vector2 input = new Vector2
    221.                 {
    222.                     x = runAxis.x,
    223.                     y = runAxis.y
    224.                 };
    225.             movementSettings.UpdateDesiredTargetSpeed(input);
    226.             return input;
    227.         }
    228.  
    229.  
    230.         private void RotateView()
    231.         {
    232.             //avoids the mouse looking if the game is effectively paused
    233.             if (Mathf.Abs(Time.timeScale) < float.Epsilon) return;
    234.  
    235.             // get the rotation before it's changed
    236.             float oldYRotation = transform.eulerAngles.y;
    237.  
    238.             mouseLook.LookRotation (transform, cam.transform);
    239.  
    240.             if (m_IsGrounded || advancedSettings.airControl)
    241.             {
    242.                 // Rotate the rigidbody velocity to match the new direction that the character is looking
    243.                 Quaternion velRotation = Quaternion.AngleAxis(transform.eulerAngles.y - oldYRotation, Vector3.up);
    244.                 m_RigidBody.velocity = velRotation*m_RigidBody.velocity;
    245.             }
    246.         }
    247.  
    248.         /// sphere cast down just beyond the bottom of the capsule to see if the capsule is colliding round the bottom
    249.         private void GroundCheck()
    250.         {
    251.             m_PreviouslyGrounded = m_IsGrounded;
    252.             RaycastHit hitInfo;
    253.             if (Physics.SphereCast(transform.position, m_Capsule.radius * (1.0f - advancedSettings.shellOffset), Vector3.down, out hitInfo,
    254.                                    ((m_Capsule.height/2f) - m_Capsule.radius) + advancedSettings.groundCheckDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
    255.             {
    256.                 m_IsGrounded = true;
    257.                 m_GroundContactNormal = hitInfo.normal;
    258.             }
    259.             else
    260.             {
    261.                 m_IsGrounded = false;
    262.                 m_GroundContactNormal = Vector3.up;
    263.             }
    264.             if (!m_PreviouslyGrounded && m_IsGrounded && m_Jumping)
    265.             {
    266.                 m_Jumping = false;
    267.             }
    268.         }
    269.  
    270.     }
    271. }
    272.  

    Code (CSharp):
    1. using System;
    2. using UnityEngine;
    3. using UnityStandardAssets.CrossPlatformInput;
    4.  
    5. namespace UnityStandardAssets.Characters.FirstPerson
    6. {
    7.     [Serializable]
    8.     public class MouseLook
    9.     {
    10.         public float XSensitivity = 2f;
    11.         public float YSensitivity = 2f;
    12.         public bool clampVerticalRotation = true;
    13.         public float MinimumX = -90F;
    14.         public float MaximumX = 90F;
    15.         public bool smooth;
    16.         public float smoothTime = 5f;
    17.         public bool lockCursor = true;
    18.  
    19.  
    20.         private Quaternion m_CharacterTargetRot;
    21.         private Quaternion m_CameraTargetRot;
    22.         private bool m_cursorIsLocked = true;
    23.  
    24.         [HideInInspector]
    25.         public Vector2 lookAxis;
    26.  
    27.         public void Init(Transform character, Transform camera)
    28.         {
    29.             m_CharacterTargetRot = character.localRotation;
    30.             m_CameraTargetRot = camera.localRotation;
    31.         }
    32.  
    33.  
    34.         public void LookRotation(Transform character, Transform camera)
    35.         {
    36.             float yRot = lookAxis.x * XSensitivity;
    37.             float xRot = lookAxis.y * YSensitivity;
    38.  
    39.             m_CharacterTargetRot *= Quaternion.Euler (0f, yRot, 0f);
    40.             m_CameraTargetRot *= Quaternion.Euler (-xRot, 0f, 0f);
    41.  
    42.             if(clampVerticalRotation)
    43.                 m_CameraTargetRot = ClampRotationAroundXAxis (m_CameraTargetRot);
    44.  
    45.             if(smooth)
    46.             {
    47.                 character.localRotation = Quaternion.Slerp (character.localRotation, m_CharacterTargetRot,
    48.                     smoothTime * Time.deltaTime);
    49.                 camera.localRotation = Quaternion.Slerp (camera.localRotation, m_CameraTargetRot,
    50.                     smoothTime * Time.deltaTime);
    51.             }
    52.             else
    53.             {
    54.                 character.localRotation = m_CharacterTargetRot;
    55.                 camera.localRotation = m_CameraTargetRot;
    56.             }
    57.  
    58.             UpdateCursorLock();
    59.         }
    60.  
    61.         public void SetCursorLock(bool value)
    62.         {
    63.             lockCursor = value;
    64.             if(!lockCursor)
    65.             {//we force unlock the cursor if the user disable the cursor locking helper
    66.                 Cursor.lockState = CursorLockMode.None;
    67.                 Cursor.visible = true;
    68.             }
    69.         }
    70.  
    71.         public void UpdateCursorLock()
    72.         {
    73.             //if the user set "lockCursor" we check & properly lock the cursos
    74.             if (lockCursor)
    75.                 InternalLockUpdate();
    76.         }
    77.  
    78.         private void InternalLockUpdate()
    79.         {
    80.             if(Input.GetKeyUp(KeyCode.Escape))
    81.             {
    82.                 m_cursorIsLocked = false;
    83.             }
    84.             else if(Input.GetMouseButtonUp(0))
    85.             {
    86.                 m_cursorIsLocked = true;
    87.             }
    88.  
    89.             if (m_cursorIsLocked)
    90.             {
    91.                 Cursor.lockState = CursorLockMode.Locked;
    92.                 Cursor.visible = false;
    93.             }
    94.             else if (!m_cursorIsLocked)
    95.             {
    96.                 Cursor.lockState = CursorLockMode.None;
    97.                 Cursor.visible = true;
    98.             }
    99.         }
    100.  
    101.         Quaternion ClampRotationAroundXAxis(Quaternion q)
    102.         {
    103.             q.x /= q.w;
    104.             q.y /= q.w;
    105.             q.z /= q.w;
    106.             q.w = 1.0f;
    107.  
    108.             float angleX = 2.0f * Mathf.Rad2Deg * Mathf.Atan (q.x);
    109.  
    110.             angleX = Mathf.Clamp (angleX, MinimumX, MaximumX);
    111.  
    112.             q.x = Mathf.Tan (0.5f * Mathf.Deg2Rad * angleX);
    113.  
    114.             return q;
    115.         }
    116.  
    117.     }
    118. }
    119.  

    If anyone could help me find out where I'm supposed to insert that offset on the Z axis and how, I would really appreciate it! I tried moving the camera a bit further on the Z while it was a child of the RigidBodyFpsController ( player ), and when I start moving it gets it's position set back inside the capsule where it usually is. This code is way too complicated for me to understand much out of it as I'm still a beginner sadly. :/
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,742
    Can you just move it back in the prefab? Or do you need a dynamic offset?

    In either case having an extra GameObject in the place of your current camera anchor and then putting the camera as a child of that is going to be the solution, then move its
    transform.localPosition
    to suit your needs.
     
    denissuu likes this.
  3. denissuu

    denissuu

    Joined:
    Nov 6, 2019
    Posts:
    162
    I mean, the prefab was already unpacked as I wanted to add a spotlight to the player's position and that was the easiest way, just made it a child of it.Also, I have tried making one more camera that is untagged so it isn't used instead of my actual camera, then made my maincam the child of that unused cam with the offset I wanted away from my character, and placed the unused cam in the inspector instead of my main one.It still seems that my Camera gets it's position set over there inside the capsule, even like this.I don't know if this was what you meant really, but I hope so haha.Correct me if I did it wrong.

    Edit : This also seems to prevent my Patrol Script to move my camera's transform transform.LookAt(this.gameObject.transform); to the killer when he gets close enough to kill me.I guess that the camera is hard-locked there or something.Or maybe it's just me not realising the problem.
     
    Last edited: Feb 14, 2020
  4. denissuu

    denissuu

    Joined:
    Nov 6, 2019
    Posts:
    162
    I have managed to make it work finally, I just disabled the headbob script as I didn't need it anyways and I can make one myself I think if I need it, and attached this to the camera :


    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. public class CameraFollow : MonoBehaviour
    6. {
    7.     public GameObject player;
    8.     public float zoffset = 1f;
    9.     public float yoffset = 3f;
    10.     public Camera cam;
    11.     // Update is called once per frame
    12.     private void Update()
    13.     {
    14.         cam.transform.position = new Vector3(player.transform.position.x, player.transform.position.y + yoffset, player.transform.position.z - zoffset);
    15.     }
    16. }
    17.  
     
    Kurt-Dekker likes this.