Hello everyone, I used the Third Person Game template provided by the wonderful development team, and copy-pasted the script for the default ThirdPersonController to a new controller for a different player entity whose animations work differently, IE I designed it to use the older 90s frame-by-frame style with seperate files for each animation instead of the skeletal style the template character uses. Although the rest of the script seems to be working fine because the compiler does not give me any errors or warnings/suggestions, it does tell me it expects a namespace or end-of-file even though I believe I typed in the correct number of parenthesis and/or semicolons. Does anybody know why this might be happening? The script is as follows, verbatim: Code (CSharp): using UnityEngine; #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED using UnityEngine.InputSystem; #endif /* Note: animations are called via the controller for both the character and capsule using animator null checks */ namespace StarterAssets { [RequireComponent(typeof(CharacterController))] #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED [RequireComponent(typeof(PlayerInput))] #endif public class BootsIdleController : MonoBehaviour { public GameObject BootsIdle; [Header("Boots")] [Tooltip("The character uses its own gravity value. The engine default is -9.81f")] public float Gravity = -15.0f; [Space(10)] [Tooltip("Time required to pass before being able to jump again. Set to 0f to instantly jump again")] public float JumpTimeout = 0.50f; [Tooltip("Time required to pass before entering the fall state. Useful for walking down stairs")] public float FallTimeout = 0.15f; [Header("Player Grounded")] [Tooltip("If the character is grounded or not. Not part of the CharacterController built in grounded check")] public bool Grounded = true; [Tooltip("Useful for rough ground")] public float GroundedOffset = -0.14f; [Tooltip("The radius of the grounded check. Should match the radius of the CharacterController")] public float GroundedRadius = 0.28f; [Tooltip("What layers the character uses as ground")] public LayerMask GroundLayers; [Header("Cinemachine")] [Tooltip("The follow target set in the Cinemachine Virtual Camera that the camera will follow")] public GameObject CinemachineCameraTarget; [Tooltip("How far in degrees can you move the camera up")] public float TopClamp = 70.0f; [Tooltip("How far in degrees can you move the camera down")] public float BottomClamp = -30.0f; [Tooltip("Additional degress to override the camera. Useful for fine tuning camera position when locked")] public float CameraAngleOverride = 0.0f; [Tooltip("For locking the camera position on all axis")] public bool LockCameraPosition = false; // cinemachine private float _cinemachineTargetYaw; private float _cinemachineTargetPitch; // player private float _rotationVelocity; // timeout deltatime private float _jumpTimeoutDelta; private float _fallTimeoutDelta; if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED private PlayerInput _playerInput; #endif private CharacterController _controller; private StarterAssetsInputs _input; private GameObject _mainCamera; private const float _threshold = 0.01f; private bool IsCurrentDeviceMouse { get { #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED return _playerInput.currentControlScheme == "KeyboardMouse"; #else return false; #endif } } private void BootsAwake() // get a reference to our main camera if (_mainCamera == null) { _mainCamera = GameObject.FindGameObjectWithTag("MainCamera"); } } private void BootsStart() { BootsIdle.SetActive(false); _cinemachineTargetYaw = CinemachineCameraTarget.transform.rotation.eulerAngles.y; _controller = GetComponent<CharacterController>(); _input = GetComponent<StarterAssetsInputs>(); #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED _playerInput = GetComponent<PlayerInput>(); #else Debug.LogError( "Starter Assets package is missing dependencies. Please use Tools/Starter Assets/Reinstall Dependencies to fix it"); #endif } private void BootsUpdate() { BootsGroundedCheck(); if (Input.GetKey("left")) { BootsIdle.SetActive(false); } if (Input.GetKey("right")) { BootsIdle.SetActive(false); } if (Input.GetKey("down")) { BootsIdle.SetActive(false); } if (Input.GetKey("up")) { BootsIdle.SetActive(false); }; } private void BootsLateUpdate() { BootsCameraRotation(); } private void BootsGroundedCheck() { // set sphere position, with offset Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z); Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers, QueryTriggerInteraction.Ignore); } private void BootsCameraRotation() { // if there is an input and camera position is not fixed if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition) { //Don't multiply mouse input by Time.deltaTime; float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime; _cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier; _cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier; } // clamp our rotations so our values are limited 360 degrees _cinemachineTargetYaw = BootsClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue); _cinemachineTargetPitch = BootsClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp); // Cinemachine will follow this target CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride, _cinemachineTargetYaw, 0.0f); } private static float BootsClampAngle(float lfAngle, float lfMin, float lfMax) { if (lfAngle < -360f) lfAngle += 360f; if (lfAngle > 360f) lfAngle -= 360f; return Mathf.Clamp(lfAngle, lfMin, lfMax); } private void BootsOnDrawGizmosSelected() { Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f); Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f); if (Grounded) Gizmos.color = transparentGreen; else Gizmos.color = transparentRed; // when selected, draw a gizmo in the position of, and matching radius of, the grounded collider Gizmos.DrawSphere( new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z), GroundedRadius); } }
Okay, I did figure it out, I just redid it from the ground and up and made a new class entirely at the very top of the script so that there was no wonkiness with clashing scripts with the old player class, but now I have a seperate problem I believe I raised last year, namely that I Googled the suggested codes for making the player disappear when you press the proper keys, but sadly nothing happens. Code (CSharp): using UnityEngine; #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED using UnityEngine.InputSystem; #endif /* Note: animations are called via the controller for both the character and capsule using animator null checks */ namespace StarterAssets { [RequireComponent(typeof(CharacterController))] #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED [RequireComponent(typeof(PlayerInput))] #endif public class BootsIdleThirdPersonController : MonoBehaviour { public GameObject BootsIdle; [Header("Player")] [Tooltip("Move speed of the character in m/s")] public float MoveSpeed = 2.0f; [Tooltip("Sprint speed of the character in m/s")] public float SprintSpeed = 5.335f; [Tooltip("How fast the character turns to face movement direction")] [Range(0.0f, 0.3f)] public float RotationSmoothTime = 0.12f; [Tooltip("Acceleration and deceleration")] public float SpeedChangeRate = 10.0f; public AudioClip LandingAudioClip; public AudioClip[] FootstepAudioClips; [Range(0, 1)] public float FootstepAudioVolume = 0.5f; [Space(10)] [Tooltip("The height the player can jump")] public float JumpHeight = 1.2f; [Tooltip("The character uses its own gravity value. The engine default is -9.81f")] public float Gravity = -15.0f; [Space(10)] [Tooltip("Time required to pass before being able to jump again. Set to 0f to instantly jump again")] public float JumpTimeout = 0.50f; [Tooltip("Time required to pass before entering the fall state. Useful for walking down stairs")] public float FallTimeout = 0.15f; [Header("Player Grounded")] [Tooltip("If the character is grounded or not. Not part of the CharacterController built in grounded check")] public bool Grounded = true; [Tooltip("Useful for rough ground")] public float GroundedOffset = -0.14f; [Tooltip("The radius of the grounded check. Should match the radius of the CharacterController")] public float GroundedRadius = 0.28f; [Tooltip("What layers the character uses as ground")] public LayerMask GroundLayers; [Header("Cinemachine")] [Tooltip("The follow target set in the Cinemachine Virtual Camera that the camera will follow")] public GameObject CinemachineCameraTarget; [Tooltip("How far in degrees can you move the camera up")] public float TopClamp = 70.0f; [Tooltip("How far in degrees can you move the camera down")] public float BottomClamp = -30.0f; [Tooltip("Additional degress to override the camera. Useful for fine tuning camera position when locked")] public float CameraAngleOverride = 0.0f; [Tooltip("For locking the camera position on all axis")] public bool LockCameraPosition = false; // cinemachine private float _cinemachineTargetYaw; private float _cinemachineTargetPitch; // timeout deltatime private float _jumpTimeoutDelta; private float _fallTimeoutDelta; #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED private PlayerInput _playerInput; #endif private Animator _animator; private CharacterController _controller; private StarterAssetsInputs _input; private GameObject _mainCamera; private const float _threshold = 0.01f; private bool _hasAnimator; private bool IsCurrentDeviceMouse { get { #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED return _playerInput.currentControlScheme == "KeyboardMouse"; #else return false; #endif } } private void Awake() { // get a reference to our main camera if (_mainCamera == null) { _mainCamera = GameObject.FindGameObjectWithTag("MainCamera"); } } private void Start() { _cinemachineTargetYaw = CinemachineCameraTarget.transform.rotation.eulerAngles.y; _controller = GetComponent<CharacterController>(); _input = GetComponent<StarterAssetsInputs>(); #if ENABLE_INPUT_SYSTEM && STARTER_ASSETS_PACKAGES_CHECKED _playerInput = GetComponent<PlayerInput>(); #else Debug.LogError( "Starter Assets package is missing dependencies. Please use Tools/Starter Assets/Reinstall Dependencies to fix it"); #endif // reset our timeouts on start } private void Update() { GroundedCheck(); if ( Input.GetKeyDown(KeyCode.LeftArrow) == true ) { BootsIdle.GetComponent<Renderer>().enabled = false; } if ( Input.GetKeyDown(KeyCode.RightArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; if ( Input.GetKeyDown(KeyCode.UpArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; if ( Input.GetKeyDown(KeyCode.DownArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; } private void LateUpdate() { CameraRotation(); } private void GroundedCheck() { // set sphere position, with offset Vector3 spherePosition = new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z); Grounded = Physics.CheckSphere(spherePosition, GroundedRadius, GroundLayers, QueryTriggerInteraction.Ignore); } private void CameraRotation() { // if there is an input and camera position is not fixed if (_input.look.sqrMagnitude >= _threshold && !LockCameraPosition) { //Don't multiply mouse input by Time.deltaTime; float deltaTimeMultiplier = IsCurrentDeviceMouse ? 1.0f : Time.deltaTime; _cinemachineTargetYaw += _input.look.x * deltaTimeMultiplier; _cinemachineTargetPitch += _input.look.y * deltaTimeMultiplier; } // clamp our rotations so our values are limited 360 degrees _cinemachineTargetYaw = ClampAngle(_cinemachineTargetYaw, float.MinValue, float.MaxValue); _cinemachineTargetPitch = ClampAngle(_cinemachineTargetPitch, BottomClamp, TopClamp); // Cinemachine will follow this target CinemachineCameraTarget.transform.rotation = Quaternion.Euler(_cinemachineTargetPitch + CameraAngleOverride, _cinemachineTargetYaw, 0.0f); } private static float ClampAngle(float lfAngle, float lfMin, float lfMax) { if (lfAngle < -360f) lfAngle += 360f; if (lfAngle > 360f) lfAngle -= 360f; return Mathf.Clamp(lfAngle, lfMin, lfMax); } private void OnDrawGizmosSelected() { Color transparentGreen = new Color(0.0f, 1.0f, 0.0f, 0.35f); Color transparentRed = new Color(1.0f, 0.0f, 0.0f, 0.35f); if (Grounded) Gizmos.color = transparentGreen; else Gizmos.color = transparentRed; // when selected, draw a gizmo in the position of, and matching radius of, the grounded collider Gizmos.DrawSphere( new Vector3(transform.position.x, transform.position.y - GroundedOffset, transform.position.z), GroundedRadius); } } } What I would like anyone who is helping correct the problem focus on is the snippet regarding the "If Key is Pressed" section, with the scripts making the renderer false/disappear, which is not happening currently even though the script compiles correctly.
Please don't post walls of plain text for code, use code-tags. You can also edit your posts. Note, this thread is nothing to do with the Editor so this is also the wrong forum, it's a Scripting post so I'll move it there. Here's the page that lists all the available forums: https://forum.unity.com/
Thank you for the help/moderation. I am really sorry I made those mistakes and will make sure to follow your directions in the future regarding pasting code, as well as where I post the question. I thought it was about the editor and general help cause I used the editor for making my game overall as well as scripting, but if it's regarding scripting help explicitly it should go in scripting period?
Is it because of the lack of code tags, or because of something else? I will change it to code tags too if that is the problem.
And this particular snippet I can isolate, to make it more obvious what is not working properly: Code (CSharp): if ( Input.GetKeyDown(KeyCode.LeftArrow) == true ) { BootsIdle.GetComponent<Renderer>().enabled = false; } if ( Input.GetKeyDown(KeyCode.RightArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; if ( Input.GetKeyDown(KeyCode.UpArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; if ( Input.GetKeyDown(KeyCode.DownArrow) == true ) BootsIdle.GetComponent<Renderer>().enabled = false; Should I use a different method besides "object.GetComponent<Renderer>().enabled = false", like "object.setactive(false)"? I tried that because I got that result from Googling it as well, but unfortunately it still didn't work.
Hello. I'm not sure what the entire thing is doing but it is (generally speaking) not very efficient at doing it. That is from the aspect of time of course (which I'm not focused on) and from readability which is in my mind equally important. For instance: BootsIdle.GetComponent<Renderer>() is repeated several times. That reference isn't changing is it? So get it once outside of the method and hold on to the reference. It is set to false based upon the state of 4 conditions. How about adding method that returns the status of the 4 Inputs and then you just assign the result. Something like: Code (CSharp): bootsIdleRenderer.enabled = IsKeyDown(); In BootsOnDrawGizmosSelected you continually assign values to transparentGreen and transparentRed but again those never change so assign them once outside of that method. Code (CSharp): Gizmos.color = Grounded ? transparentGreen : transparentRed; And finally "whitespace is your friend". It is also free, add some
Thank you for the help! I do not know if I should change BootsGizmo though, because I was just copy pasting it verbatim from the character template like I explained in my first post, so it might alter other parts of the code that rely on it. The first suggestion you stated though I can and will definitely do.
I think there might be bugs too now, because I am told the local function "LateUpdate" is declared but never used, even though I know it wasn't a problem for the default template I pasted it from, and I didn't change that particular code at all. What gives?
Do you think it might be cause I copy pasted most of the script, like I assumed the "Update" and "LateUpdate" functions would carry over seamlessly into my new class, even though it is actually reserved for the PlayerClass specifically? I could guess that
I didn't notice your reply. It isn't "reserved" this is all just code you tell it what you want it doesn't tell you So long as your new class inherits MonoBehaviour you get the standard methods. Experimentation is one of the best ways to get a feel for how coding works and will build confidence. I would suggest not "guessing" that is one of the worst systems and likely to lead to "well I must be correct because now it works". You could have just gotten lucky. Know why the code works and why changing (improving) something would work even better. That's my 2 cents.
Okay, then it is actually worse that way, because I used the same exact code snippet for the original Player character and my new character, yet it gives me an error for new character. I don't believe it is good practice when developing an app to make one's code inconsistent and logically unpredictable like that.
Cause what I am refererring to is when you start a new project from the ground up, you are given a "third person game template" with a character who has a working script already. In that exact/particular script, it gives you scripts for "Update" and "LateUpdate", even though it is never called earlier in the code it picks up on that it should do the code every single frame/update. When I copy paste the script and make the revisions in other places of the code, not that piece at all, it gives me an error message saying "Update" was never called even though that was exactly as true for the original character, and it never complained/gave me an error.
I have to guess based upon what you are writing that you don't exactly understand how the MonoBehavior works or why it is there. That isn't a problem when starting out but you need to get to the point of knowing it isn't just a magic word you need to type. Update isn't a script it is a method and it didn't "not get called" it always gets called by Unity automatically as part of the lifecycle of the class. You can post the class (make sure you embed it as Code (CSharp): code . The issue can be a lot of things, C# is case-sensitive and you might have decided that case shouldn't matter. Sometimes people spell things wrong and sometimes they misinterpret error messages. They can happen in the editor, the compiler or at runtime all for different reasons. I suggest that you try again and take it one step at-a-time. We've all been there.