Last active
October 12, 2021 00:27
-
-
Save whoisryosuke/f7b12ca2077853435ba45cb1754444c1 to your computer and use it in GitHub Desktop.
Unity - 3D Player Movement using Unity's Player Input package - via: https://www.youtube.com/watch?v=537B1kJp9YQ
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections; | |
| using System.Collections.Generic; | |
| using UnityEngine; | |
| using UnityEngine.AI; | |
| // Handles actual movement of character + triggering things like animation | |
| // This game has a "shooting mode" which is activated by Left Shift | |
| // So you'll see shooting logic as well | |
| public class PlayerLocomotionController : MonoBehaviour | |
| { | |
| private Animator _animator; | |
| private PlayerMovementInputController _movement; | |
| private Vector2 smoothDeltaPosition = Vector2.zero; | |
| public Vector2 velocity = Vector2.zero; | |
| public float magnitude = 0.25f; | |
| public bool shouldMove; | |
| public bool shouldTurn; | |
| public float turn; | |
| public GameObject look; | |
| public GameObject arrow; | |
| public Transform arrowBone; | |
| public GameObject arrowPrefab; | |
| private void OnEnable() | |
| { | |
| _movement = GetComponent<PlayerMovementInputController>(); | |
| _animator = GetComponent<Animator>(); | |
| } | |
| public void Update() | |
| { | |
| Vector3 worldDeltaPosition = _movement.nextPosition - transform.position; | |
| //Map to local space | |
| float dX = Vector3.Dot(transform.right, worldDeltaPosition); | |
| float dY = Vector3.Dot(transform.forward, worldDeltaPosition); | |
| Vector2 deltaPosition = new Vector2(dX, dY); | |
| float smooth = Mathf.Min(1.0f, Time.deltaTime / 0.15f); | |
| smoothDeltaPosition = Vector2.Lerp(smoothDeltaPosition, deltaPosition, smooth); | |
| if (Time.deltaTime > 1e-5f) | |
| { | |
| velocity = smoothDeltaPosition / Time.deltaTime; | |
| } | |
| shouldMove = velocity.magnitude > magnitude; | |
| bool isAiming = (_movement.aimValue == 1f); | |
| if (isAiming) | |
| { | |
| if ((_movement.fireValue == 1f)) | |
| { | |
| _animator.SetTrigger("Fire"); | |
| arrow.SetActive(false); | |
| StartCoroutine(FireArrow()); | |
| } | |
| if (_animator.GetCurrentAnimatorStateInfo(2).IsName("Fire")) | |
| { | |
| arrow.SetActive(false); | |
| } | |
| else | |
| { | |
| arrow.SetActive(true); | |
| } | |
| _movement.fireValue = 0f; | |
| } | |
| _animator.SetBool("IsAiming", isAiming); | |
| _animator.SetBool("IsMoving", shouldMove); | |
| _animator.SetFloat("VelocityX", velocity.x); | |
| _animator.SetFloat("VelocityY", Mathf.Abs(velocity.y)); | |
| } | |
| private void OnAnimatorMove() | |
| { | |
| //Update the position based on the next position; | |
| transform.position = _movement.nextPosition; | |
| } | |
| [SerializeField] | |
| private Transform fireTransform; | |
| IEnumerator FireArrow() | |
| { | |
| GameObject projectile = Instantiate(arrowPrefab); | |
| projectile.transform.forward = look.transform.forward; | |
| projectile.transform.position = fireTransform.position + fireTransform.forward; | |
| //Wait for the position to update | |
| yield return new WaitForSeconds(0.1f); | |
| projectile.GetComponent<ArrowProjectile>().Fire(); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System.Collections; | |
| using System.Collections.Generic; | |
| using UnityEngine; | |
| using UnityEngine.AI; | |
| using UnityEngine.InputSystem; | |
| // This class handles taking user input and converting to proper movement | |
| // This does not move the character - only rotates. | |
| // `nextPosition` contains movement - handled by PlayerLocomotionController (see below) | |
| [RequireComponent(typeof(PlayerInput))] | |
| [RequireComponent(typeof(NavMeshAgent))] | |
| public class PlayerMovementInputController : MonoBehaviour | |
| { | |
| private NavMeshAgent _agent; | |
| // These all sync with Player Input using the callbacks below (e.g. `onMove`) | |
| public Vector2 _move; | |
| public Vector2 _look; | |
| public float aimValue; | |
| public float fireValue; | |
| public Vector3 nextPosition; | |
| public Quaternion nextRotation; | |
| public float rotationPower = 3f; | |
| public float rotationLerp = 0.5f; | |
| public float speed = 1f; | |
| // The main camera in scene (usually MainCamera) | |
| public Camera camera; | |
| // An empty game object marker inside your Player - like near head | |
| public GameObject followTransform; | |
| private void Awake() | |
| { | |
| _agent = GetComponent<NavMeshAgent>(); | |
| } | |
| public void OnMove(InputValue value) | |
| { | |
| _move = value.Get<Vector2>(); | |
| } | |
| public void OnLook(InputValue value) | |
| { | |
| _look = value.Get<Vector2>(); | |
| } | |
| public void OnAim(InputValue value) | |
| { | |
| aimValue = value.Get<float>(); | |
| } | |
| public void OnFire(InputValue value) | |
| { | |
| fireValue = value.Get<float>(); | |
| } | |
| private void Update() | |
| { | |
| #region Player Based Rotation | |
| //Move the player based on the X input on the controller | |
| //transform.rotation *= Quaternion.AngleAxis(_look.x * rotationPower, Vector3.up); | |
| #endregion | |
| #region Follow Transform Rotation | |
| //Rotate the Follow Target transform based on the input | |
| followTransform.transform.rotation *= Quaternion.AngleAxis(_look.x * rotationPower, Vector3.up); | |
| #endregion | |
| #region Vertical Rotation | |
| followTransform.transform.rotation *= Quaternion.AngleAxis(-_look.y * rotationPower / 2, Vector3.right); | |
| var angles = followTransform.transform.localEulerAngles; | |
| angles.z = 0; | |
| var angle = followTransform.transform.localEulerAngles.x; | |
| //Clamp the Up/Down rotation | |
| if (angle > 180 && angle < 340) | |
| { | |
| angles.x = 340; | |
| } | |
| else if (angle < 180 && angle > 40) | |
| { | |
| angles.x = 40; | |
| } | |
| followTransform.transform.localEulerAngles = angles; | |
| #endregion | |
| nextRotation = Quaternion.Lerp(followTransform.transform.rotation, nextRotation, Time.deltaTime * rotationLerp); | |
| if (_move.x == 0 && _move.y == 0) | |
| { | |
| nextPosition = transform.position; | |
| if (aimValue == 1) | |
| { | |
| //Set the player rotation based on the look transform | |
| transform.rotation = Quaternion.Euler(0, followTransform.transform.rotation.eulerAngles.y, 0); | |
| //reset the y rotation of the look transform | |
| followTransform.transform.localEulerAngles = new Vector3(angles.x, 0, 0); | |
| } | |
| return; | |
| } | |
| float moveSpeed = speed / 100f; | |
| Vector3 position = (transform.forward * _move.y * moveSpeed) + (transform.right * _move.x * moveSpeed); | |
| nextPosition = transform.position + position; | |
| //Set the player rotation based on the look transform | |
| transform.rotation = Quaternion.Euler(0, followTransform.transform.rotation.eulerAngles.y, 0); | |
| //reset the y rotation of the look transform | |
| followTransform.transform.localEulerAngles = new Vector3(angles.x, 0, 0); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment