Player, player movement, camera control
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using KinematicCharacterController;
|
||||
using System;
|
||||
|
||||
namespace KinematicCharacterController.Walkthrough.RootMotionExample
|
||||
{
|
||||
public struct PlayerCharacterInputs
|
||||
{
|
||||
public float MoveAxisForward;
|
||||
public float MoveAxisRight;
|
||||
}
|
||||
|
||||
public class MyCharacterController : MonoBehaviour, ICharacterController
|
||||
{
|
||||
public KinematicCharacterMotor Motor;
|
||||
|
||||
[Header("Stable Movement")]
|
||||
public float MaxStableMoveSpeed = 10f;
|
||||
public float StableMovementSharpness = 15;
|
||||
public float OrientationSharpness = 10;
|
||||
|
||||
[Header("Air Movement")]
|
||||
public float MaxAirMoveSpeed = 10f;
|
||||
public float AirAccelerationSpeed = 5f;
|
||||
public float Drag = 0.1f;
|
||||
|
||||
[Header("Animation Parameters")]
|
||||
public Animator CharacterAnimator;
|
||||
public float ForwardAxisSharpness = 10;
|
||||
public float TurnAxisSharpness = 5;
|
||||
|
||||
[Header("Misc")]
|
||||
public Vector3 Gravity = new Vector3(0, -30f, 0);
|
||||
public Transform MeshRoot;
|
||||
|
||||
private Vector3 _moveInputVector;
|
||||
private Vector3 _lookInputVector;
|
||||
private float _forwardAxis;
|
||||
private float _rightAxis;
|
||||
private float _targetForwardAxis;
|
||||
private float _targetRightAxis;
|
||||
private Vector3 _rootMotionPositionDelta;
|
||||
private Quaternion _rootMotionRotationDelta;
|
||||
|
||||
/// <summary>
|
||||
/// This is called every frame by MyPlayer in order to tell the character what its inputs are
|
||||
/// </summary>
|
||||
public void SetInputs(ref PlayerCharacterInputs inputs)
|
||||
{
|
||||
// Axis inputs
|
||||
_targetForwardAxis = inputs.MoveAxisForward;
|
||||
_targetRightAxis = inputs.MoveAxisRight;
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
_rootMotionPositionDelta = Vector3.zero;
|
||||
_rootMotionRotationDelta = Quaternion.identity;
|
||||
|
||||
// Assign to motor
|
||||
Motor.CharacterController = this;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
// Handle animation
|
||||
_forwardAxis = Mathf.Lerp(_forwardAxis, _targetForwardAxis, 1f - Mathf.Exp(-ForwardAxisSharpness * Time.deltaTime));
|
||||
_rightAxis = Mathf.Lerp(_rightAxis, _targetRightAxis, 1f - Mathf.Exp(-TurnAxisSharpness * Time.deltaTime));
|
||||
CharacterAnimator.SetFloat("Forward", _forwardAxis);
|
||||
CharacterAnimator.SetFloat("Turn", _rightAxis);
|
||||
CharacterAnimator.SetBool("OnGround", Motor.GroundingStatus.IsStableOnGround);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called before the character begins its movement update
|
||||
/// </summary>
|
||||
public void BeforeCharacterUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its rotation should be right now.
|
||||
/// This is the ONLY place where you should set the character's rotation
|
||||
/// </summary>
|
||||
public void UpdateRotation(ref Quaternion currentRotation, float deltaTime)
|
||||
{
|
||||
currentRotation = _rootMotionRotationDelta * currentRotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is where you tell your character what its velocity should be right now.
|
||||
/// This is the ONLY place where you can set the character's velocity
|
||||
/// </summary>
|
||||
public void UpdateVelocity(ref Vector3 currentVelocity, float deltaTime)
|
||||
{
|
||||
if (Motor.GroundingStatus.IsStableOnGround)
|
||||
{
|
||||
if (deltaTime > 0)
|
||||
{
|
||||
// The final velocity is the velocity from root motion reoriented on the ground plane
|
||||
currentVelocity = _rootMotionPositionDelta / deltaTime;
|
||||
currentVelocity = Motor.GetDirectionTangentToSurface(currentVelocity, Motor.GroundingStatus.GroundNormal) * currentVelocity.magnitude;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Prevent division by zero
|
||||
currentVelocity = Vector3.zero;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_forwardAxis > 0f)
|
||||
{
|
||||
// If we want to move, add an acceleration to the velocity
|
||||
Vector3 targetMovementVelocity = Motor.CharacterForward * _forwardAxis * MaxAirMoveSpeed;
|
||||
Vector3 velocityDiff = Vector3.ProjectOnPlane(targetMovementVelocity - currentVelocity, Gravity);
|
||||
currentVelocity += velocityDiff * AirAccelerationSpeed * deltaTime;
|
||||
}
|
||||
|
||||
// Gravity
|
||||
currentVelocity += Gravity * deltaTime;
|
||||
|
||||
// Drag
|
||||
currentVelocity *= (1f / (1f + (Drag * deltaTime)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// (Called by KinematicCharacterMotor during its update cycle)
|
||||
/// This is called after the character has finished its movement update
|
||||
/// </summary>
|
||||
public void AfterCharacterUpdate(float deltaTime)
|
||||
{
|
||||
// Reset root motion deltas
|
||||
_rootMotionPositionDelta = Vector3.zero;
|
||||
_rootMotionRotationDelta = Quaternion.identity;
|
||||
}
|
||||
|
||||
public bool IsColliderValidForCollisions(Collider coll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void OnGroundHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void OnMovementHit(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
public void PostGroundingUpdate(float deltaTime)
|
||||
{
|
||||
}
|
||||
|
||||
public void AddVelocity(Vector3 velocity)
|
||||
{
|
||||
}
|
||||
|
||||
public void ProcessHitStabilityReport(Collider hitCollider, Vector3 hitNormal, Vector3 hitPoint, Vector3 atCharacterPosition, Quaternion atCharacterRotation, ref HitStabilityReport hitStabilityReport)
|
||||
{
|
||||
}
|
||||
|
||||
private void OnAnimatorMove()
|
||||
{
|
||||
// Accumulate rootMotion deltas between character updates
|
||||
_rootMotionPositionDelta += CharacterAnimator.deltaPosition;
|
||||
_rootMotionRotationDelta = CharacterAnimator.deltaRotation * _rootMotionRotationDelta;
|
||||
}
|
||||
|
||||
public void OnDiscreteCollisionDetected(Collider hitCollider)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e96594aad710a0b43a67031fa15f8a06
|
||||
timeCreated: 1507247652
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,90 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using KinematicCharacterController;
|
||||
using KinematicCharacterController.Examples;
|
||||
using System.Linq;
|
||||
|
||||
namespace KinematicCharacterController.Walkthrough.RootMotionExample
|
||||
{
|
||||
public class MyPlayer : MonoBehaviour
|
||||
{
|
||||
public ExampleCharacterCamera OrbitCamera;
|
||||
public Transform CameraFollowPoint;
|
||||
public MyCharacterController Character;
|
||||
|
||||
private const string MouseXInput = "Mouse X";
|
||||
private const string MouseYInput = "Mouse Y";
|
||||
private const string MouseScrollInput = "Mouse ScrollWheel";
|
||||
private const string HorizontalInput = "Horizontal";
|
||||
private const string VerticalInput = "Vertical";
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
|
||||
// Tell camera to follow transform
|
||||
OrbitCamera.SetFollowTransform(CameraFollowPoint);
|
||||
|
||||
// Ignore the character's collider(s) for camera obstruction checks
|
||||
OrbitCamera.IgnoredColliders.Clear();
|
||||
OrbitCamera.IgnoredColliders.AddRange(Character.GetComponentsInChildren<Collider>());
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (Input.GetMouseButtonDown(0))
|
||||
{
|
||||
Cursor.lockState = CursorLockMode.Locked;
|
||||
}
|
||||
|
||||
HandleCharacterInput();
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
HandleCameraInput();
|
||||
}
|
||||
|
||||
private void HandleCameraInput()
|
||||
{
|
||||
// Create the look input vector for the camera
|
||||
float mouseLookAxisUp = Input.GetAxisRaw(MouseYInput);
|
||||
float mouseLookAxisRight = Input.GetAxisRaw(MouseXInput);
|
||||
Vector3 lookInputVector = new Vector3(mouseLookAxisRight, mouseLookAxisUp, 0f);
|
||||
|
||||
// Prevent moving the camera while the cursor isn't locked
|
||||
if (Cursor.lockState != CursorLockMode.Locked)
|
||||
{
|
||||
lookInputVector = Vector3.zero;
|
||||
}
|
||||
|
||||
// Input for zooming the camera (disabled in WebGL because it can cause problems)
|
||||
float scrollInput = -Input.GetAxis(MouseScrollInput);
|
||||
#if UNITY_WEBGL
|
||||
scrollInput = 0f;
|
||||
#endif
|
||||
|
||||
// Apply inputs to the camera
|
||||
OrbitCamera.UpdateWithInput(Time.deltaTime, scrollInput, lookInputVector);
|
||||
|
||||
// Handle toggling zoom level
|
||||
if (Input.GetMouseButtonDown(1))
|
||||
{
|
||||
OrbitCamera.TargetDistance = (OrbitCamera.TargetDistance == 0f) ? OrbitCamera.DefaultDistance : 0f;
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleCharacterInput()
|
||||
{
|
||||
PlayerCharacterInputs characterInputs = new PlayerCharacterInputs();
|
||||
|
||||
// Build the CharacterInputs struct
|
||||
characterInputs.MoveAxisForward = Input.GetAxisRaw(VerticalInput);
|
||||
characterInputs.MoveAxisRight = Input.GetAxisRaw(HorizontalInput);
|
||||
|
||||
// Apply inputs to character
|
||||
Character.SetInputs(ref characterInputs);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 34acb1750e367084bac169843c2821b7
|
||||
timeCreated: 1507247652
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user