holopy3/Assets/SteamVR/InteractionSystem/Samples/JoeJeff/JoeJeff.cs
2020-12-10 15:25:12 +01:00

212 lines
No EOL
6.6 KiB
C#

using UnityEngine;
using System.Collections;
using Valve.VR.InteractionSystem;
namespace Valve.VR.InteractionSystem.Sample
{
public class JoeJeff : MonoBehaviour
{
public float animationSpeed;
public float jumpVelocity;
[SerializeField]
private float m_MovingTurnSpeed = 360;
[SerializeField]
private float m_StationaryTurnSpeed = 180;
public float airControl;
[Tooltip("The time it takes after landing a jump to slow down")]
public float frictionTime = 0.2f;
[SerializeField]
private float footHeight = 0.1f;
[SerializeField]
private float footRadius = 0.03f;
private RaycastHit footHit;
private bool isGrounded;
private float turnAmount;
private float forwardAmount;
private float groundedTime;
private Animator animator;
private Vector3 input;
private bool held;
private new Rigidbody rigidbody;
private Interactable interactable;
public FireSource fire;
private void Start()
{
animator = GetComponent<Animator>();
rigidbody = GetComponent<Rigidbody>();
interactable = GetComponent<Interactable>();
animator.speed = animationSpeed;
}
private void Update()
{
held = interactable.attachedToHand != null;
jumpTimer -= Time.deltaTime;
CheckGrounded();
rigidbody.freezeRotation = !held;
if (held == false)
FixRotation();
}
private void FixRotation()
{
Vector3 eulers = transform.eulerAngles;
eulers.x = 0;
eulers.z = 0;
Quaternion targetRotation = Quaternion.Euler(eulers);
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, Time.deltaTime * (isGrounded ? 20 : 3));
}
public void OnAnimatorMove()
{
// we implement this function to override the default root motion.
// this allows us to modify the positional speed before it's applied.
if (Time.deltaTime > 0)
{
Vector3 animationDelta = (animator.deltaPosition) / Time.deltaTime;
animationDelta = Vector3.ProjectOnPlane(animationDelta, footHit.normal);
if (isGrounded && jumpTimer < 0)
{
if (groundedTime < frictionTime) //slow down when first hitting the floor after a jump
{
float moveFac = Mathf.InverseLerp(0, frictionTime, groundedTime);
//print(moveFac);
Vector3 lerpV = Vector3.Lerp(rigidbody.velocity, animationDelta, moveFac * Time.deltaTime * 30);
animationDelta.x = lerpV.x;
animationDelta.z = lerpV.z;
}
// adding a little downward force to keep him on the floor
animationDelta.y += -0.2f;// rb.velocity.y;
rigidbody.velocity = animationDelta;
}
else
{
rigidbody.velocity += input * Time.deltaTime * airControl;
}
}
}
public void Move(Vector3 move, bool jump)
{
input = move;
if (move.magnitude > 1f)
move.Normalize();
move = transform.InverseTransformDirection(move);
turnAmount = Mathf.Atan2(move.x, move.z);
forwardAmount = move.z;
ApplyExtraTurnRotation();
// control and velocity handling is different when grounded and airborne:
if (isGrounded)
{
HandleGroundedMovement(jump);
}
// send input and other state parameters to the animator
UpdateAnimator(move);
}
private void UpdateAnimator(Vector3 move)
{
animator.speed = fire.isBurning ? animationSpeed * 2 : animationSpeed;
// update the animator parameters
animator.SetFloat("Forward", fire.isBurning ? 2 : forwardAmount, 0.1f, Time.deltaTime);
animator.SetFloat("Turn", turnAmount, 0.1f, Time.deltaTime);
animator.SetBool("OnGround", isGrounded);
animator.SetBool("Holding", held);
if (!isGrounded)
{
animator.SetFloat("FallSpeed", Mathf.Abs(rigidbody.velocity.y));
animator.SetFloat("Jump", rigidbody.velocity.y);
}
}
private void ApplyExtraTurnRotation()
{
// help the character turn faster (this is in addition to root rotation in the animation)
float turnSpeed = Mathf.Lerp(m_StationaryTurnSpeed, m_MovingTurnSpeed, forwardAmount);
transform.Rotate(0, turnAmount * turnSpeed * Time.deltaTime, 0);
}
private void CheckGrounded()
{
isGrounded = false;
if (jumpTimer < 0 & !held) // make sure we didn't just jump
{
isGrounded = (Physics.SphereCast(new Ray(transform.position + Vector3.up * footHeight, Vector3.down), footRadius, out footHit, footHeight - footRadius));
if (Vector2.Distance(new Vector2(transform.position.x, transform.position.z), new Vector2(footHit.point.x, footHit.point.z)) > footRadius / 2)
{
isGrounded = false;
//on slope, hit point is on edge of sphere cast
}
}
}
private void FixedUpdate()
{
groundedTime += Time.fixedDeltaTime;
if (!isGrounded) groundedTime = 0; // reset timer
if (isGrounded & !held)
{
Debug.DrawLine(transform.position, footHit.point);
rigidbody.position = new Vector3(rigidbody.position.x, footHit.point.y, rigidbody.position.z);
}
}
private void HandleGroundedMovement(bool jump)
{
// check whether conditions are right to allow a jump:
if (jump && isGrounded)
{
Jump();
}
}
private float jumpTimer;
public void Jump()
{
isGrounded = false;
jumpTimer = 0.1f;
animator.applyRootMotion = false;
rigidbody.position += Vector3.up * 0.03f;
Vector3 velocity = rigidbody.velocity;
velocity.y = jumpVelocity;
rigidbody.velocity = velocity;
}
}
}