JoeJeff.cs
6.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
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;
}
}
}