Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 14 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
0
Question by deandraper82 · Dec 02, 2021 at 03:15 PM · speed

Ground speed slow, but speed right while airborne

I have downloaded the Unity Learn 3D Game Kit https://assetstore.unity.com/packages/templates/tutorials/3d-game-kit-115747 Most of it seems to work properly, but I am having trouble with character's move speed. When I am on the ground, I move incredibly slow, but when I jump while moving forward, I move what I assume to be a proper speed. Has anyone else encountered this issue? Or does anyone know of a setting that applies only to ground move speed, and not jumping?? I thought maybe I had changed something, or installed something improperly, but I redownloaded using the recommended Unity version for the kit, and I am still encountering the same issue. Any assistance would be greatly appreciated. This is the PlayerController script:

 using UnityEngine;
 using Gamekit3D.Message;
 using System.Collections;
 using UnityEngine.XR.WSA;
 
 namespace Gamekit3D
 {
     [RequireComponent(typeof(CharacterController))]
     [RequireComponent(typeof(Animator))]
     public class PlayerController : MonoBehaviour, IMessageReceiver
     {
         protected static PlayerController s_Instance;
         public static PlayerController instance { get { return s_Instance; } }
 
         public bool respawning { get { return m_Respawning; } }
 
         public float maxForwardSpeed = 8f;        // How fast Ellen can run.
         public float gravity = 20f;               // How fast Ellen accelerates downwards when airborne.
         public float jumpSpeed = 10f;             // How fast Ellen takes off when jumping.
         public float minTurnSpeed = 400f;         // How fast Ellen turns when moving at maximum speed.
         public float maxTurnSpeed = 1200f;        // How fast Ellen turns when stationary.
         public float idleTimeout = 5f;            // How long before Ellen starts considering random idles.
         public bool canAttack;                    // Whether or not Ellen can swing her staff.
 
         public CameraSettings cameraSettings;            // Reference used to determine the camera's direction.
         public MeleeWeapon meleeWeapon;                  // Reference used to (de)activate the staff when attacking. 
         public RandomAudioPlayer footstepPlayer;         // Random Audio Players used for various situations.
         public RandomAudioPlayer hurtAudioPlayer;
         public RandomAudioPlayer landingPlayer;
         public RandomAudioPlayer emoteLandingPlayer;
         public RandomAudioPlayer emoteDeathPlayer;
         public RandomAudioPlayer emoteAttackPlayer;
         public RandomAudioPlayer emoteJumpPlayer;
 
         protected AnimatorStateInfo m_CurrentStateInfo;    // Information about the base layer of the animator cached.
         protected AnimatorStateInfo m_NextStateInfo;
         protected bool m_IsAnimatorTransitioning;
         protected AnimatorStateInfo m_PreviousCurrentStateInfo;    // Information about the base layer of the animator from last frame.
         protected AnimatorStateInfo m_PreviousNextStateInfo;
         protected bool m_PreviousIsAnimatorTransitioning;
         protected bool m_IsGrounded = true;            // Whether or not Ellen is currently standing on the ground.
         protected bool m_PreviouslyGrounded = true;    // Whether or not Ellen was standing on the ground last frame.
         protected bool m_ReadyToJump;                  // Whether or not the input state and Ellen are correct to allow jumping.
         protected float m_DesiredForwardSpeed;         // How fast Ellen aims be going along the ground based on input.
         protected float m_ForwardSpeed;                // How fast Ellen is currently going along the ground.
         protected float m_VerticalSpeed;               // How fast Ellen is currently moving up or down.
         protected PlayerInput m_Input;                 // Reference used to determine how Ellen should move.
         protected CharacterController m_CharCtrl;      // Reference used to actually move Ellen.
         protected Animator m_Animator;                 // Reference used to make decisions based on Ellen's current animation and to set parameters.
         protected Material m_CurrentWalkingSurface;    // Reference used to make decisions about audio.
         protected Quaternion m_TargetRotation;         // What rotation Ellen is aiming to have based on input.
         protected float m_AngleDiff;                   // Angle in degrees between Ellen's current rotation and her target rotation.
         protected Collider[] m_OverlapResult = new Collider[8];    // Used to cache colliders that are near Ellen.
         protected bool m_InAttack;                     // Whether Ellen is currently in the middle of a melee attack.
         protected bool m_InCombo;                      // Whether Ellen is currently in the middle of her melee combo.
         protected Damageable m_Damageable;             // Reference used to set invulnerablity and health based on respawning.
         protected Renderer[] m_Renderers;              // References used to make sure Renderers are reset properly. 
         protected Checkpoint m_CurrentCheckpoint;      // Reference used to reset Ellen to the correct position on respawn.
         protected bool m_Respawning;                   // Whether Ellen is currently respawning.
         protected float m_IdleTimer;                   // Used to count up to Ellen considering a random idle.
 
         // These constants are used to ensure Ellen moves and behaves properly.
         // It is advised you don't change them without fully understanding what they do in code.
         const float k_AirborneTurnSpeedProportion = 5.4f;
         const float k_GroundedRayDistance = 1f;
         const float k_JumpAbortSpeed = 10f;
         const float k_MinEnemyDotCoeff = 0.2f;
         const float k_InverseOneEighty = 1f / 180f;
         const float k_StickingGravityProportion = 0.3f;
         const float k_GroundAcceleration = 20f;
         const float k_GroundDeceleration = 25f;
 
         // Parameters
 
         readonly int m_HashAirborneVerticalSpeed = Animator.StringToHash("AirborneVerticalSpeed");
         readonly int m_HashForwardSpeed = Animator.StringToHash("ForwardSpeed");
         readonly int m_HashAngleDeltaRad = Animator.StringToHash("AngleDeltaRad");
         readonly int m_HashTimeoutToIdle = Animator.StringToHash("TimeoutToIdle");
         readonly int m_HashGrounded = Animator.StringToHash("Grounded");
         readonly int m_HashInputDetected = Animator.StringToHash("InputDetected");
         readonly int m_HashMeleeAttack = Animator.StringToHash("MeleeAttack");
         readonly int m_HashHurt = Animator.StringToHash("Hurt");
         readonly int m_HashDeath = Animator.StringToHash("Death");
         readonly int m_HashRespawn = Animator.StringToHash("Respawn");
         readonly int m_HashHurtFromX = Animator.StringToHash("HurtFromX");
         readonly int m_HashHurtFromY = Animator.StringToHash("HurtFromY");
         readonly int m_HashStateTime = Animator.StringToHash("StateTime");
         readonly int m_HashFootFall = Animator.StringToHash("FootFall");
 
         // States
         readonly int m_HashLocomotion = Animator.StringToHash("Locomotion");
         readonly int m_HashAirborne = Animator.StringToHash("Airborne");
         readonly int m_HashLanding = Animator.StringToHash("Landing");    // Also a parameter.
         readonly int m_HashEllenCombo1 = Animator.StringToHash("EllenCombo1");
         readonly int m_HashEllenCombo2 = Animator.StringToHash("EllenCombo2");
         readonly int m_HashEllenCombo3 = Animator.StringToHash("EllenCombo3");
         readonly int m_HashEllenCombo4 = Animator.StringToHash("EllenCombo4");
         readonly int m_HashEllenDeath = Animator.StringToHash("EllenDeath");
 
         // Tags
         readonly int m_HashBlockInput = Animator.StringToHash("BlockInput");
 
         protected bool IsMoveInput
         {
             get { return !Mathf.Approximately(m_Input.MoveInput.sqrMagnitude, 0f); }
         }
 
         public void SetCanAttack(bool canAttack)
         {
             this.canAttack = canAttack;
         }
 
         // Called automatically by Unity when the script is first added to a gameobject or is reset from the context menu.
         void Reset()
         {
             meleeWeapon = GetComponentInChildren<MeleeWeapon>();
 
             Transform footStepSource = transform.Find("FootstepSource");
             if (footStepSource != null)
                 footstepPlayer = footStepSource.GetComponent<RandomAudioPlayer>();
 
             Transform hurtSource = transform.Find("HurtSource");
             if (hurtSource != null)
                 hurtAudioPlayer = hurtSource.GetComponent<RandomAudioPlayer>();
 
             Transform landingSource = transform.Find("LandingSource");
             if (landingSource != null)
                 landingPlayer = landingSource.GetComponent<RandomAudioPlayer>();
 
             cameraSettings = FindObjectOfType<CameraSettings>();
 
             if (cameraSettings != null)
             {
                 if (cameraSettings.follow == null)
                     cameraSettings.follow = transform;
 
                 if (cameraSettings.lookAt == null)
                     cameraSettings.follow = transform.Find("HeadTarget");
             }
         }
 
         // Called automatically by Unity when the script first exists in the scene.
         void Awake()
         {
             m_Input = GetComponent<PlayerInput>();
             m_Animator = GetComponent<Animator>();
             m_CharCtrl = GetComponent<CharacterController>();
 
             meleeWeapon.SetOwner(gameObject);
 
             s_Instance = this;
         }
 
         // Called automatically by Unity after Awake whenever the script is enabled. 
         void OnEnable()
         {
             SceneLinkedSMB<PlayerController>.Initialise(m_Animator, this);
 
             m_Damageable = GetComponent<Damageable>();
             m_Damageable.onDamageMessageReceivers.Add(this);
 
             m_Damageable.isInvulnerable = true;
 
             EquipMeleeWeapon(false);
 
             m_Renderers = GetComponentsInChildren<Renderer>();
         }
 
         // Called automatically by Unity whenever the script is disabled.
         void OnDisable()
         {
             m_Damageable.onDamageMessageReceivers.Remove(this);
 
             for (int i = 0; i < m_Renderers.Length; ++i)
             {
                 m_Renderers[i].enabled = true;
             }
         }
 
         // Called automatically by Unity once every Physics step.
         void FixedUpdate()
         {
             CacheAnimatorState();
 
             UpdateInputBlocking();
 
             EquipMeleeWeapon(IsWeaponEquiped());
 
             m_Animator.SetFloat(m_HashStateTime, Mathf.Repeat(m_Animator.GetCurrentAnimatorStateInfo(0).normalizedTime, 1f));
             m_Animator.ResetTrigger(m_HashMeleeAttack);
 
             if (m_Input.Attack && canAttack)
                 m_Animator.SetTrigger(m_HashMeleeAttack);
 
             CalculateForwardMovement();
             CalculateVerticalMovement();
 
             SetTargetRotation();
 
             if (IsOrientationUpdated() && IsMoveInput)
                 UpdateOrientation();
 
             PlayAudio();
 
             TimeoutToIdle();
 
             m_PreviouslyGrounded = m_IsGrounded;
         }
 
         // Called at the start of FixedUpdate to record the current state of the base layer of the animator.
         void CacheAnimatorState()
         {
             m_PreviousCurrentStateInfo = m_CurrentStateInfo;
             m_PreviousNextStateInfo = m_NextStateInfo;
             m_PreviousIsAnimatorTransitioning = m_IsAnimatorTransitioning;
 
             m_CurrentStateInfo = m_Animator.GetCurrentAnimatorStateInfo(0);
             m_NextStateInfo = m_Animator.GetNextAnimatorStateInfo(0);
             m_IsAnimatorTransitioning = m_Animator.IsInTransition(0);
         }
 
         // Called after the animator state has been cached to determine whether this script should block user input.
         void UpdateInputBlocking()
         {
             bool inputBlocked = m_CurrentStateInfo.tagHash == m_HashBlockInput && !m_IsAnimatorTransitioning;
             inputBlocked |= m_NextStateInfo.tagHash == m_HashBlockInput;
             m_Input.playerControllerInputBlocked = inputBlocked;
         }
 
         // Called after the animator state has been cached to determine whether or not the staff should be active or not.
         bool IsWeaponEquiped()
         {
             bool equipped = m_NextStateInfo.shortNameHash == m_HashEllenCombo1 || m_CurrentStateInfo.shortNameHash == m_HashEllenCombo1;
             equipped |= m_NextStateInfo.shortNameHash == m_HashEllenCombo2 || m_CurrentStateInfo.shortNameHash == m_HashEllenCombo2;
             equipped |= m_NextStateInfo.shortNameHash == m_HashEllenCombo3 || m_CurrentStateInfo.shortNameHash == m_HashEllenCombo3;
             equipped |= m_NextStateInfo.shortNameHash == m_HashEllenCombo4 || m_CurrentStateInfo.shortNameHash == m_HashEllenCombo4;
 
             return equipped;
         }
 
         // Called each physics step with a parameter based on the return value of IsWeaponEquiped.
         void EquipMeleeWeapon(bool equip)
         {
             meleeWeapon.gameObject.SetActive(equip);
             m_InAttack = false;
             m_InCombo = equip;
 
             if (!equip)
                 m_Animator.ResetTrigger(m_HashMeleeAttack);
         }
 
         // Called each physics step.
         void CalculateForwardMovement()
         {
             // Cache the move input and cap it's magnitude at 1.
             Vector2 moveInput = m_Input.MoveInput;
             if (moveInput.sqrMagnitude > 1f)
                 moveInput.Normalize();
 
             // Calculate the speed intended by input.
             m_DesiredForwardSpeed = moveInput.magnitude * maxForwardSpeed;
 
             // Determine change to speed based on whether there is currently any move input.
             float acceleration = IsMoveInput ? k_GroundAcceleration : k_GroundDeceleration;
 
             // Adjust the forward speed towards the desired speed.
             m_ForwardSpeed = Mathf.MoveTowards(m_ForwardSpeed, m_DesiredForwardSpeed, acceleration * Time.deltaTime);
 
             // Set the animator parameter to control what animation is being played.
             m_Animator.SetFloat(m_HashForwardSpeed, m_ForwardSpeed);
         }
 
         // Called each physics step.
         void CalculateVerticalMovement()
         {
             // If jump is not currently held and Ellen is on the ground then she is ready to jump.
             if (!m_Input.JumpInput && m_IsGrounded)
                 m_ReadyToJump = true;
 
             if (m_IsGrounded)
             {
                 // When grounded we apply a slight negative vertical speed to make Ellen "stick" to the ground.
                 m_VerticalSpeed = -gravity * k_StickingGravityProportion;
 
                 // If jump is held, Ellen is ready to jump and not currently in the middle of a melee combo...
                 if (m_Input.JumpInput && m_ReadyToJump && !m_InCombo)
                 {
                     // ... then override the previously set vertical speed and make sure she cannot jump again.
                     m_VerticalSpeed = jumpSpeed;
                     m_IsGrounded = false;
                     m_ReadyToJump = false;
                 }
             }
             else
             {
                 // If Ellen is airborne, the jump button is not held and Ellen is currently moving upwards...
                 if (!m_Input.JumpInput && m_VerticalSpeed > 0.0f)
                 {
                     // ... decrease Ellen's vertical speed.
                     // This is what causes holding jump to jump higher that tapping jump.
                     m_VerticalSpeed -= k_JumpAbortSpeed * Time.deltaTime;
                 }
 
                 // If a jump is approximately peaking, make it absolute.
                 if (Mathf.Approximately(m_VerticalSpeed, 0f))
                 {
                     m_VerticalSpeed = 0f;
                 }
                 
                 // If Ellen is airborne, apply gravity.
                 m_VerticalSpeed -= gravity * Time.deltaTime;
             }
         }
 
         // Called each physics step to set the rotation Ellen is aiming to have.
         void SetTargetRotation()
         {
             // Create three variables, move input local to the player, flattened forward direction of the camera and a local target rotation.
             Vector2 moveInput = m_Input.MoveInput;
             Vector3 localMovementDirection = new Vector3(moveInput.x, 0f, moveInput.y).normalized;
             
             Vector3 forward = Quaternion.Euler(0f, cameraSettings.Current.m_XAxis.Value, 0f) * Vector3.forward;
             forward.y = 0f;
             forward.Normalize();
 
             Quaternion targetRotation;
             
             // If the local movement direction is the opposite of forward then the target rotation should be towards the camera.
             if (Mathf.Approximately(Vector3.Dot(localMovementDirection, Vector3.forward), -1.0f))
             {
                 targetRotation = Quaternion.LookRotation(-forward);
             }
             else
             {
                 // Otherwise the rotation should be the offset of the input from the camera's forward.
                 Quaternion cameraToInputOffset = Quaternion.FromToRotation(Vector3.forward, localMovementDirection);
                 targetRotation = Quaternion.LookRotation(cameraToInputOffset * forward);
             }
 
             // The desired forward direction of Ellen.
             Vector3 resultingForward = targetRotation * Vector3.forward;
 
             // If attacking try to orient to close enemies.
             if (m_InAttack)
             {
                 // Find all the enemies in the local area.
                 Vector3 centre = transform.position + transform.forward * 2.0f + transform.up;
                 Vector3 halfExtents = new Vector3(3.0f, 1.0f, 2.0f);
                 int layerMask = 1 << LayerMask.NameToLayer("Enemy");
                 int count = Physics.OverlapBoxNonAlloc(centre, halfExtents, m_OverlapResult, targetRotation, layerMask);
 
                 // Go through all the enemies in the local area...
                 float closestDot = 0.0f;
                 Vector3 closestForward = Vector3.zero;
                 int closest = -1;
 
                 for (int i = 0; i < count; ++i)
                 {
                     // ... and for each get a vector from the player to the enemy.
                     Vector3 playerToEnemy = m_OverlapResult[i].transform.position - transform.position;
                     playerToEnemy.y = 0;
                     playerToEnemy.Normalize();
 
                     // Find the dot product between the direction the player wants to go and the direction to the enemy.
                     // This will be larger the closer to Ellen's desired direction the direction to the enemy is.
                     float d = Vector3.Dot(resultingForward, playerToEnemy);
 
                     // Store the closest enemy.
                     if (d > k_MinEnemyDotCoeff && d > closestDot)
                     {
                         closestForward = playerToEnemy;
                         closestDot = d;
                         closest = i;
                     }
                 }
 
                 // If there is a close enemy...
                 if (closest != -1)
                 {
                     // The desired forward is the direction to the closest enemy.
                     resultingForward = closestForward;
                     
                     // We also directly set the rotation, as we want snappy fight and orientation isn't updated in the UpdateOrientation function during an atatck.
                     transform.rotation = Quaternion.LookRotation(resultingForward);
                 }
             }
 
             // Find the difference between the current rotation of the player and the desired rotation of the player in radians.
             float angleCurrent = Mathf.Atan2(transform.forward.x, transform.forward.z) * Mathf.Rad2Deg;
             float targetAngle = Mathf.Atan2(resultingForward.x, resultingForward.z) * Mathf.Rad2Deg;
 
             m_AngleDiff = Mathf.DeltaAngle(angleCurrent, targetAngle);
             m_TargetRotation = targetRotation;
         }
 
         // Called each physics step to help determine whether Ellen can turn under player input.
         bool IsOrientationUpdated()
         {
             bool updateOrientationForLocomotion = !m_IsAnimatorTransitioning && m_CurrentStateInfo.shortNameHash == m_HashLocomotion || m_NextStateInfo.shortNameHash == m_HashLocomotion;
             bool updateOrientationForAirborne = !m_IsAnimatorTransitioning && m_CurrentStateInfo.shortNameHash == m_HashAirborne || m_NextStateInfo.shortNameHash == m_HashAirborne;
             bool updateOrientationForLanding = !m_IsAnimatorTransitioning && m_CurrentStateInfo.shortNameHash == m_HashLanding || m_NextStateInfo.shortNameHash == m_HashLanding;
 
             return updateOrientationForLocomotion || updateOrientationForAirborne || updateOrientationForLanding || m_InCombo && !m_InAttack;
         }
 
         // Called each physics step after SetTargetRotation if there is move input and Ellen is in the correct animator state according to IsOrientationUpdated.
         void UpdateOrientation()
         {
             m_Animator.SetFloat(m_HashAngleDeltaRad, m_AngleDiff * Mathf.Deg2Rad);
 
             Vector3 localInput = new Vector3(m_Input.MoveInput.x, 0f, m_Input.MoveInput.y);
             float groundedTurnSpeed = Mathf.Lerp(maxTurnSpeed, minTurnSpeed, m_ForwardSpeed / m_DesiredForwardSpeed);
             float actualTurnSpeed = m_IsGrounded ? groundedTurnSpeed : Vector3.Angle(transform.forward, localInput) * k_InverseOneEighty * k_AirborneTurnSpeedProportion * groundedTurnSpeed;
             m_TargetRotation = Quaternion.RotateTowards(transform.rotation, m_TargetRotation, actualTurnSpeed * Time.deltaTime);
 
             transform.rotation = m_TargetRotation;
         }
 
         // Called each physics step to check if audio should be played and if so instruct the relevant random audio player to do so.
         void PlayAudio()
         {
             float footfallCurve = m_Animator.GetFloat(m_HashFootFall);
 
             if (footfallCurve > 0.01f && !footstepPlayer.playing && footstepPlayer.canPlay)
             {
                 footstepPlayer.playing = true;
                 footstepPlayer.canPlay = false;
                 footstepPlayer.PlayRandomClip(m_CurrentWalkingSurface, m_ForwardSpeed < 4 ? 0 : 1);
             }
             else if (footstepPlayer.playing)
             {
                 footstepPlayer.playing = false;
             }
             else if (footfallCurve < 0.01f && !footstepPlayer.canPlay)
             {
                 footstepPlayer.canPlay = true;
             }
 
             if (m_IsGrounded && !m_PreviouslyGrounded)
             {
                 landingPlayer.PlayRandomClip(m_CurrentWalkingSurface, bankId: m_ForwardSpeed < 4 ? 0 : 1);
                 emoteLandingPlayer.PlayRandomClip();
             }
 
             if (!m_IsGrounded && m_PreviouslyGrounded && m_VerticalSpeed > 0f)
             {
                 emoteJumpPlayer.PlayRandomClip();
             }
 
             if (m_CurrentStateInfo.shortNameHash == m_HashHurt && m_PreviousCurrentStateInfo.shortNameHash != m_HashHurt)
             {
                 hurtAudioPlayer.PlayRandomClip();
             }
 
             if (m_CurrentStateInfo.shortNameHash == m_HashEllenDeath && m_PreviousCurrentStateInfo.shortNameHash != m_HashEllenDeath)
             {
                 emoteDeathPlayer.PlayRandomClip();
             }
 
             if (m_CurrentStateInfo.shortNameHash == m_HashEllenCombo1 && m_PreviousCurrentStateInfo.shortNameHash != m_HashEllenCombo1 ||
                 m_CurrentStateInfo.shortNameHash == m_HashEllenCombo2 && m_PreviousCurrentStateInfo.shortNameHash != m_HashEllenCombo2 ||
                 m_CurrentStateInfo.shortNameHash == m_HashEllenCombo3 && m_PreviousCurrentStateInfo.shortNameHash != m_HashEllenCombo3 ||
                 m_CurrentStateInfo.shortNameHash == m_HashEllenCombo4 && m_PreviousCurrentStateInfo.shortNameHash != m_HashEllenCombo4)
             {
                 emoteAttackPlayer.PlayRandomClip();
             }
         }
 
         // Called each physics step to count up to the point where Ellen considers a random idle.
         void TimeoutToIdle()
         {
             bool inputDetected = IsMoveInput || m_Input.Attack || m_Input.JumpInput;
             if (m_IsGrounded && !inputDetected)
             {
                 m_IdleTimer += Time.deltaTime;
 
                 if (m_IdleTimer >= idleTimeout)
                 {
                     m_IdleTimer = 0f;
                     m_Animator.SetTrigger(m_HashTimeoutToIdle);
                 }
             }
             else
             {
                 m_IdleTimer = 0f;
                 m_Animator.ResetTrigger(m_HashTimeoutToIdle);
             }
 
             m_Animator.SetBool(m_HashInputDetected, inputDetected);
         }
 
         // Called each physics step (so long as the Animator component is set to Animate Physics) after FixedUpdate to override root motion.
         void OnAnimatorMove()
         {
             Vector3 movement;
 
             // If Ellen is on the ground...
             if (m_IsGrounded)
             {
                 // ... raycast into the ground...
                 RaycastHit hit;
                 Ray ray = new Ray(transform.position + Vector3.up * k_GroundedRayDistance * 0.5f, -Vector3.up);
                 if (Physics.Raycast(ray, out hit, k_GroundedRayDistance, Physics.AllLayers, QueryTriggerInteraction.Ignore))
                 {
                     // ... and get the movement of the root motion rotated to lie along the plane of the ground.
                     movement = Vector3.ProjectOnPlane(m_Animator.deltaPosition, hit.normal);
                     
                     // Also store the current walking surface so the correct audio is played.
                     Renderer groundRenderer = hit.collider.GetComponentInChildren<Renderer>();
                     m_CurrentWalkingSurface = groundRenderer ? groundRenderer.sharedMaterial : null;
                 }
                 else
                 {
                     // If no ground is hit just get the movement as the root motion.
                     // Theoretically this should rarely happen as when grounded the ray should always hit.
                     movement = m_Animator.deltaPosition;
                     m_CurrentWalkingSurface = null;
                 }
             }
             else
             {
                 // If not grounded the movement is just in the forward direction.
                 movement = m_ForwardSpeed * transform.forward * Time.deltaTime;
             }
 
             // Rotate the transform of the character controller by the animation's root rotation.
             m_CharCtrl.transform.rotation *= m_Animator.deltaRotation;
 
             // Add to the movement with the calculated vertical speed.
             movement += m_VerticalSpeed * Vector3.up * Time.deltaTime;
 
             // Move the character controller.
             m_CharCtrl.Move(movement);
 
             // After the movement store whether or not the character controller is grounded.
             m_IsGrounded = m_CharCtrl.isGrounded;
 
             // If Ellen is not on the ground then send the vertical speed to the animator.
             // This is so the vertical speed is kept when landing so the correct landing animation is played.
             if (!m_IsGrounded)
                 m_Animator.SetFloat(m_HashAirborneVerticalSpeed, m_VerticalSpeed);
 
             // Send whether or not Ellen is on the ground to the animator.
             m_Animator.SetBool(m_HashGrounded, m_IsGrounded);
         }
         
         // This is called by an animation event when Ellen swings her staff.
         public void MeleeAttackStart(int throwing = 0)
         {
             meleeWeapon.BeginAttack(throwing != 0);
             m_InAttack = true;
         }
 
         // This is called by an animation event when Ellen finishes swinging her staff.
         public void MeleeAttackEnd()
         {
             meleeWeapon.EndAttack();
             m_InAttack = false;
         }
 
         // This is called by Checkpoints to make sure Ellen respawns correctly.
         public void SetCheckpoint(Checkpoint checkpoint)
         {
             if (checkpoint != null)
                 m_CurrentCheckpoint = checkpoint;
         }
 
         // This is usually called by a state machine behaviour on the animator controller but can be called from anywhere.
         public void Respawn()
         {
             StartCoroutine(RespawnRoutine());
         }
         
         protected IEnumerator RespawnRoutine()
         {
             // Wait for the animator to be transitioning from the EllenDeath state.
             while (m_CurrentStateInfo.shortNameHash != m_HashEllenDeath || !m_IsAnimatorTransitioning)
             {
                 yield return null;
             }
             
             // Wait for the screen to fade out.
             yield return StartCoroutine(ScreenFader.FadeSceneOut());
             while (ScreenFader.IsFading)
             {
                 yield return null;
             }
 
             // Enable spawning.
             EllenSpawn spawn = GetComponentInChildren<EllenSpawn>();
             spawn.enabled = true;
 
             // If there is a checkpoint, move Ellen to it.
             if (m_CurrentCheckpoint != null)
             {
                 transform.position = m_CurrentCheckpoint.transform.position;
                 transform.rotation = m_CurrentCheckpoint.transform.rotation;
             }
             else
             {
                 Debug.LogError("There is no Checkpoint set, there should always be a checkpoint set. Did you add a checkpoint at the spawn?");
             }
             
             // Set the Respawn parameter of the animator.
             m_Animator.SetTrigger(m_HashRespawn);
             
             // Start the respawn graphic effects.
             spawn.StartEffect();
             
             // Wait for the screen to fade in.
             // Currently it is not important to yield here but should some changes occur that require waiting until a respawn has finished this will be required.
             yield return StartCoroutine(ScreenFader.FadeSceneIn());
             
             m_Damageable.ResetDamage();
         }
 
         // Called by a state machine behaviour on Ellen's animator controller.
         public void RespawnFinished()
         {
             m_Respawning = false;
             
             //we set the damageable invincible so we can't get hurt just after being respawned (feel like a double punitive)
             m_Damageable.isInvulnerable = false;
         }
 
         // Called by Ellen's Damageable when she is hurt.
         public void OnReceiveMessage(MessageType type, object sender, object data)
         {
             switch (type)
             {
                 case MessageType.DAMAGED:
                     {
                         Damageable.DamageMessage damageData = (Damageable.DamageMessage)data;
                         Damaged(damageData);
                     }
                     break;
                 case MessageType.DEAD:
                     {
                         Damageable.DamageMessage damageData = (Damageable.DamageMessage)data;
                         Die(damageData);
                     }
                     break;
             }
         }
 
         // Called by OnReceiveMessage.
         void Damaged(Damageable.DamageMessage damageMessage)
         {
             // Set the Hurt parameter of the animator.
             m_Animator.SetTrigger(m_HashHurt);
 
             // Find the direction of the damage.
             Vector3 forward = damageMessage.damageSource - transform.position;
             forward.y = 0f;
 
             Vector3 localHurt = transform.InverseTransformDirection(forward);
 
             // Set the HurtFromX and HurtFromY parameters of the animator based on the direction of the damage.
             m_Animator.SetFloat(m_HashHurtFromX, localHurt.x);
             m_Animator.SetFloat(m_HashHurtFromY, localHurt.z);
 
             // Shake the camera.
             CameraShake.Shake(CameraShake.k_PlayerHitShakeAmount, CameraShake.k_PlayerHitShakeTime);
 
             // Play an audio clip of being hurt.
             if (hurtAudioPlayer != null)
             {
                 hurtAudioPlayer.PlayRandomClip();
             }
         }
 
         // Called by OnReceiveMessage and by DeathVolumes in the scene.
         public void Die(Damageable.DamageMessage damageMessage)
         {
             m_Animator.SetTrigger(m_HashDeath);
             m_ForwardSpeed = 0f;
             m_VerticalSpeed = 0f;
             m_Respawning = true;
             m_Damageable.isInvulnerable = true;
         }
     }
 }

Comment
Add comment
10 |3000 characters needed characters left characters exceeded
â–¼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

0 Replies

· Add your reply
  • Sort: 

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

131 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Rotate object from localRotation A to localRotation B at rate C. 2 Answers

Collider problems with Speed 1 Answer

How to Access AnimaionState in Mecanim? 1 Answer

Acceleration of Transform in FixedUpdate (SOLVED) 0 Answers

Vector2 MoveToward on HUD Canvas slow 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges