1: using UnityEngine;
2: using System.Collections;
3: public class ThirdPersonController : MonoBehaviour {
4: public AnimationClip idleAnimation;
5: public AnimationClip walkAnimation;
6: public AnimationClip runAnimation;
7: public AnimationClip jumpPoseAnimation;
8: public float walkMaxAnimationSpeed = 0.75f;
9: public float trotMaxAnimationSpeed= 1.0f;
10: public float runMaxAnimationSpeed = 1.0f;
11: public float jumpAnimationSpeed = 1.15f;
12: public float landAnimationSpeed = 1.0f;
13: private Animation _animation;
14: // The speed when walking
15: public float walkSpeed = 2.0f;
16: // after trotAfterSeconds of walking we trot with trotSpeed
17: public float trotSpeed = 4.0f;
18: // when pressing "Fire3" button (cmd) we start running
19: public float runSpeed = 6.0f;
20: public float inAirControlAcceleration = 3.0f;
21: // How high do we jump when pressing jump and letting go immediately
22: public float jumpHeight = 0.5f;
23: // The gravity for the character
24: public float gravity = 20.0f;
25: // The gravity in controlled descent mode
26: public float speedSmoothing = 10.0f;
27: public float rotateSpeed = 500.0f;
28: public float trotAfterSeconds = 3.0f;
29: public bool canJump = true;
30: private float jumpRepeatTime = 0.05f;
31: private float jumpTimeout = 0.15f;
32: private float groundedTimeout = 0.25f;
33: // The camera doesnt start following the target immediately but waits for a split second to avoid too much waving around.
34: private float lockCameraTimer = 0.0f;
35: // The current move direction in x-z
36: private Vector3 moveDirection = Vector3.zero;
37: // The current vertical speed
38: private float verticalSpeed = 0.0f;
39: // The current x-z move speed
40: private float moveSpeed = 0.0f;
41: // The last collision flags returned from controller.Move
42: private CollisionFlags collisionFlags;
43: // Are we jumping? (Initiated with jump button and not grounded yet)
44: private bool jumping = false;
45: private bool jumpingReachedApex = false;
46: // Are we moving backwards (This locks the camera to not do a 180 degree spin)
47: private bool movingBack = false;
48: // Is the user pressing any keys?
49: private bool isMoving = false;
50: // When did the user start walking (Used for going into trot after a while)
51: private float walkTimeStart = 0.0f;
52: // Last time the jump button was clicked down
53: private float lastJumpButtonTime = -10.0f;
54: // Last time we performed a jump
55: private float lastJumpTime = -1.0f;
56: // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
57: private float lastJumpStartHeight = 0.0f;
58: private Vector3 inAirVelocity = Vector3.zero;
59: private float lastGroundedTime = 0.0f;
60: private bool isControllable = true;
61: enum CharacterState {
62: Idle = 0,
63: Walking = 1,
64: Trotting = 2,
65: Running = 3,
66: Jumping = 4,
67: }
68: private CharacterState _characterState;
69: // Use this for initialization
70: void Start () {
71: }
72: void Awake () {
73: moveDirection = transform.TransformDirection(Vector3.forward);
74: _animation = GetComponent <Animation> ();
75: if(!_animation)
76: Debug.Log("The character you would like to control doesn't have animations. Moving her might look weird.");
77: /*
78: public var idleAnimation : AnimationClip;
79: public var walkAnimation : AnimationClip;
80: public var runAnimation : AnimationClip;
81: public var jumpPoseAnimation : AnimationClip;
82: */
83: if(!idleAnimation) {
84: _animation = null;
85: Debug.Log("No idle animation found. Turning off animations.");
86: }
87: if(!walkAnimation) {
88: _animation = null;
89: Debug.Log("No walk animation found. Turning off animations.");
90: }
91: if(!runAnimation) {
92: _animation = null;
93: Debug.Log("No run animation found. Turning off animations.");
94: }
95: if(!jumpPoseAnimation && canJump) {
96: _animation = null;
97: Debug.Log("No jump animation found and the character has canJump enabled. Turning off animations.");
98: }
99: }
100: void UpdateSmoothedMovementDirection ()
101: {
102: Transform cameraTransform = Camera.main.transform;
103: bool grounded = IsGrounded();
104: // Forward vector relative to the camera along the x-z plane
105: Vector3 forward = cameraTransform.TransformDirection(Vector3.forward);
106: forward.y = 0;
107: forward = forward.normalized;
108: // Right vector relative to the camera
109: // Always orthogonal to the forward vector
110: Vector3 right = new Vector3(forward.z, 0, -forward.x);
111: float v = Input.GetAxisRaw("Vertical");
112: float h = Input.GetAxisRaw("Horizontal");
113: // Are we moving backwards or looking backwards
114: if (v < -0.2f)
115: movingBack = true;
116: else
117: movingBack = false;
118: bool wasMoving = isMoving;
119: isMoving = Mathf.Abs (h) > 0.1f || Mathf.Abs (v) > 0.1f;
120: // Target direction relative to the camera
121: Vector3 targetDirection = h * right + v * forward;
122: // Grounded controls
123: if (grounded)
124: {
125: // Lock camera for short period when transitioning moving & standing still
126: lockCameraTimer += Time.deltaTime;
127: if (isMoving != wasMoving)
128: lockCameraTimer = 0.0f;
129: // We store speed and direction seperately,
130: // so that when the character stands still we still have a valid forward direction
131: // moveDirection is always normalized, and we only update it if there is user input.
132: if (targetDirection != Vector3.zero)
133: {
134: // If we are really slow, just snap to the target direction
135: if (moveSpeed < walkSpeed * 0.9f && grounded)
136: {
137: moveDirection = targetDirection.normalized;
138: }
139: // Otherwise smoothly turn towards it
140: else
141: {
142: moveDirection = Vector3.RotateTowards(moveDirection, targetDirection, rotateSpeed * Mathf.Deg2Rad * Time.deltaTime, 1000);
143: moveDirection = moveDirection.normalized;
144: }
145: }
146: // Smooth the speed based on the current target direction
147: float curSmooth = speedSmoothing * Time.deltaTime;
148: // Choose target speed
149: //* We want to support analog input but make sure you cant walk faster diagonally than just forward or sideways
150: float targetSpeed = Mathf.Min(targetDirection.magnitude, 1.0f);
151: _characterState = CharacterState.Idle;
152: // Pick speed modifier
153: if (Input.GetKey (KeyCode.LeftShift) || Input.GetKey (KeyCode.RightShift))
154: {
155: targetSpeed *= runSpeed;
156: _characterState = CharacterState.Running;
157: }
158: else if (Time.time - trotAfterSeconds > walkTimeStart)
159: {
160: targetSpeed *= trotSpeed;
161: _characterState = CharacterState.Trotting;
162: }
163: else
164: {
165: targetSpeed *= walkSpeed;
166: _characterState = CharacterState.Walking;
167: }
168: moveSpeed = Mathf.Lerp(moveSpeed, targetSpeed, curSmooth);
169: // Reset walk time start when we slow down
170: if (moveSpeed < walkSpeed * 0.3f)
171: walkTimeStart = Time.time;
172: }
173: // In air controls
174: else
175: {
176: // Lock camera while in air
177: if (jumping)
178: lockCameraTimer = 0.0f;
179: if (isMoving)
180: inAirVelocity += targetDirection.normalized * Time.deltaTime * inAirControlAcceleration;
181: }
182: }
183: void ApplyJumping ()
184: {
185: // Prevent jumping too fast after each other
186: if (lastJumpTime + jumpRepeatTime > Time.time)
187: return;
188: if (IsGrounded()) {
189: // Jump
190: // - Only when pressing the button down
191: // - With a timeout so you can press the button slightly before landing
192: if (canJump && Time.time < lastJumpButtonTime + jumpTimeout) {
193: verticalSpeed = CalculateJumpVerticalSpeed (jumpHeight);
194: SendMessage("DidJump", SendMessageOptions.DontRequireReceiver);
195: }
196: }
197: }
198: void ApplyGravity ()
199: {
200: if (isControllable) // don't move player at all if not controllable.
201: {
202: // Apply gravity
203: bool jumpButton = Input.GetButton("Jump");
204: // When we reach the apex of the jump we send out a message
205: if (jumping && !jumpingReachedApex && verticalSpeed <= 0.0f)
206: {
207: jumpingReachedApex = true;
208: SendMessage("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);
209: }
210: if (IsGrounded ())
211: verticalSpeed = 0.0f;
212: else
213: verticalSpeed -= gravity * Time.deltaTime;
214: }
215: }
216: float CalculateJumpVerticalSpeed (float targetJumpHeight)
217: {
218: // From the jump height and gravity we deduce the upwards speed
219: // for the character to reach at the apex.
220: return Mathf.Sqrt(2 * targetJumpHeight * gravity);
221: }
222: void DidJump ()
223: {
224: jumping = true;
225: jumpingReachedApex = false;
226: lastJumpTime = Time.time;
227: lastJumpStartHeight = transform.position.y;
228: lastJumpButtonTime = -10;
229: _characterState = CharacterState.Jumping;
230: }
231: void OnControllerColliderHit (ControllerColliderHit hit)
232: {
233: // Debug.DrawRay(hit.point, hit.normal);
234: if (hit.moveDirection.y > 0.01f)
235: return;
236: }
237: float GetSpeed () {
238: return moveSpeed;
239: }
240: public bool IsJumping () {
241: return jumping;
242: }
243: bool IsGrounded () {
244: return (collisionFlags & CollisionFlags.CollidedBelow) != 0;
245: }
246: Vector3 GetDirection () {
247: return moveDirection;
248: }
249: public bool IsMovingBackwards () {
250: return movingBack;
251: }
252: public float GetLockCameraTimer ()
253: {
254: return lockCameraTimer;
255: }
256: bool IsMoving ()
257: {
258: return Mathf.Abs(Input.GetAxisRaw("Vertical")) + Mathf.Abs(Input.GetAxisRaw("Horizontal")) > 0.5f;
259: }
260: bool HasJumpReachedApex ()
261: {
262: return jumpingReachedApex;
263: }
264: bool IsGroundedWithTimeout ()
265: {
266: return lastGroundedTime + groundedTimeout > Time.time;
267: }
268: void Reset ()
269: {
270: gameObject.tag = "Player";
271: }
272: // Update is called once per frame
273: void Update () {
274: if (!isControllable)
275: {
276: // kill all inputs if not controllable.
277: Input.ResetInputAxes();
278: }
279: if (Input.GetButtonDown ("Jump"))
280: {
281: lastJumpButtonTime = Time.time;
282: }
283: UpdateSmoothedMovementDirection();
284: // Apply gravity
285: // - extra power jump modifies gravity
286: // - controlledDescent mode modifies gravity
287: ApplyGravity ();
288: // Apply jumping logic
289: ApplyJumping ();
290: // Calculate actual motion
291: Vector3 movement = moveDirection * moveSpeed + new Vector3 (0, verticalSpeed, 0) + inAirVelocity;
292: movement *= Time.deltaTime;
293: // Move the controller
294: CharacterController controller = GetComponent <CharacterController> ();
295: collisionFlags = controller.Move(movement);
296: // ANIMATION sector
297: if(_animation) {
298: if(_characterState == CharacterState.Jumping)
299: {
300: if(!jumpingReachedApex) {
301: _animation[jumpPoseAnimation.name].speed = jumpAnimationSpeed;
302: _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
303: _animation.CrossFade(jumpPoseAnimation.name);
304: } else {
305: _animation[jumpPoseAnimation.name].speed = -landAnimationSpeed;
306: _animation[jumpPoseAnimation.name].wrapMode = WrapMode.ClampForever;
307: _animation.CrossFade(jumpPoseAnimation.name);
308: }
309: }
310: else
311: {
312: if(controller.velocity.sqrMagnitude < 0.1) {
313: _animation.CrossFade(idleAnimation.name);
314: }
315: else
316: {
317: if(_characterState == CharacterState.Running) {
318: _animation[runAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, runMaxAnimationSpeed);
319: _animation.CrossFade(runAnimation.name);
320: }
321: else if(_characterState == CharacterState.Trotting) {
322: _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, trotMaxAnimationSpeed);
323: _animation.CrossFade(walkAnimation.name);
324: }
325: else if(_characterState == CharacterState.Walking) {
326: _animation[walkAnimation.name].speed = Mathf.Clamp(controller.velocity.magnitude, 0.0f, walkMaxAnimationSpeed);
327: _animation.CrossFade(walkAnimation.name);
328: }
329: }
330: }
331: }
332: // ANIMATION sector
333: // Set rotation to the move direction
334: if (IsGrounded())
335: {
336: transform.rotation = Quaternion.LookRotation(moveDirection);
337: }
338: else
339: {
340: var xzMove = movement;
341: xzMove.y = 0;
342: if (xzMove.sqrMagnitude > 0.001f)
343: {
344: transform.rotation = Quaternion.LookRotation(xzMove);
345: }
346: }
347: // We are in jump mode but just became grounded
348: if (IsGrounded())
349: {
350: lastGroundedTime = Time.time;
351: inAirVelocity = Vector3.zero;
352: if (jumping)
353: {
354: jumping = false;
355: SendMessage("DidLand", SendMessageOptions.DontRequireReceiver);
356: }
357: }
358: }
359: }
mercredi 23 septembre 2015
Unity ThirdPersonController.js to ThirdPersonController.cs
S'abonner à :
Publier des commentaires (Atom)
Aucun commentaire:
Publier un commentaire