码迷,mamicode.com
首页 > Windows程序 > 详细

C#版官方角色控制器脚本

时间:2016-01-09 06:19:10      阅读:308      评论:0      收藏:0      [点我收藏+]

标签:

将官方自带的角色控制器脚本,改写为C#版,以下为所有代码:

CharacterMotor.cs  主要设置角色控制的系数,如运动,跳跃,移动,滑动等。第一人称与第三人称主角模型的移动与旋转的角度最后都是在这里计算的。

CharacterMotor.cs  代码:

  1 using UnityEngine;
  2 using System.Collections;
  3  
  4 /**
  5 *主要设置角色控制的系数,如运动,跳跃,移动,滑动等。第一人称与第三人称主角模型的移动与旋转的角度最后都是在这里计算的。
  6  */
  7  
  8 [RequireComponent(typeof(CharacterController))]
  9 [AddComponentMenu("Character/Character Motor")]
 10  
 11 public class CharacterMotor : MonoBehaviour {
 12  
 13 // Does this script currently respond to input?
 14 public bool canControl  = true;
 15  
 16 public bool useFixedUpdate = true;
 17  
 18 // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
 19 // Very handy for organization!
 20  
 21 // The current global direction we want the character to move in.
 22 [System.NonSerialized]
 23 public Vector3 inputMoveDirection = Vector3.zero;
 24  
 25 // Is the jump button held down? We use this interface instead of checking
 26 // for the jump button directly so this script can also be used by AIs.
 27 [System.NonSerialized]
 28 public bool inputJump  = false;
 29  
 30 [System.Serializable]
 31 public class CharacterMotorMovement
 32 {
 33  
 34     // The maximum horizontal speed when moving
 35     public float maxForwardSpeed = 10.0f;
 36     public float maxSidewaysSpeed = 10.0f;
 37     public float maxBackwardsSpeed = 10.0f;
 38  
 39     // Curve for multiplying speed based on slope (negative = downwards)
 40     public AnimationCurve slopeSpeedMultiplier = new AnimationCurve(new Keyframe(-90, 1), new Keyframe(0, 1), new Keyframe(90, 0));
 41  
 42     // How fast does the character change speeds?  Higher is faster.
 43     public float maxGroundAcceleration = 30.0f;
 44     public float maxAirAcceleration = 20.0f;
 45  
 46     // The gravity for the character
 47     public float gravity = 10.0f;
 48     public float maxFallSpeed = 20.0f;
 49  
 50     // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
 51     // Very handy for organization!
 52  
 53     // The last collision flags returned from controller.Move
 54     [System.NonSerialized]
 55     public CollisionFlags collisionFlags; 
 56  
 57     // We will keep track of the character‘s current velocity,
 58     [System.NonSerialized]
 59     public Vector3 velocity;
 60  
 61     // This keeps track of our current velocity while we‘re not grounded
 62     [System.NonSerialized]
 63     public Vector3 frameVelocity = Vector3.zero;
 64  
 65     [System.NonSerialized]
 66     public Vector3 hitPoint = Vector3.zero;
 67  
 68     [System.NonSerialized]
 69     public Vector3 lastHitPoint = new Vector3(Mathf.Infinity, 0, 0);
 70 }
 71  
 72 public CharacterMotorMovement movement = new CharacterMotorMovement();
 73  
 74 public enum MovementTransferOnJump {
 75     None, // The jump is not affected by velocity of floor at all.
 76     InitTransfer, // Jump gets its initial velocity from the floor, then gradualy comes to a stop.
 77     PermaTransfer, // Jump gets its initial velocity from the floor, and keeps that velocity until landing.
 78     PermaLocked // Jump is relative to the movement of the last touched floor and will move together with that floor.
 79 }
 80  
 81 // We will contain all the jumping related variables in one helper class for clarity.    
 82 [System.Serializable]
 83 public class CharacterMotorJumping {
 84     // Can the character jump?
 85     public bool enabled = true;
 86  
 87     // How high do we jump when pressing jump and letting go immediately
 88     public float baseHeight = 1.0f;
 89  
 90     // We add extraHeight units (meters) on top when holding the button down longer while jumping
 91     public float extraHeight = 4.1f;
 92  
 93     // How much does the character jump out perpendicular to the surface on walkable surfaces?
 94     // 0 means a fully vertical jump and 1 means fully perpendicular.
 95     public float perpAmount  = 0.0f;
 96  
 97     // How much does the character jump out perpendicular to the surface on too steep surfaces?
 98     // 0 means a fully vertical jump and 1 means fully perpendicular.
 99     public float steepPerpAmount = 0.5f;
100  
101     // For the next variables, @System.NonSerialized tells Unity to not serialize the variable or show it in the inspector view.
102     // Very handy for organization!
103  
104     // Are we jumping? (Initiated with jump button and not grounded yet)
105     // To see if we are just in the air (initiated by jumping OR falling) see the grounded variable.
106     [System.NonSerialized]
107     public bool jumping = false;
108  
109     [System.NonSerialized]
110     public bool holdingJumpButton = false;
111  
112     // the time we jumped at (Used to determine for how long to apply extra jump power after jumping.)
113     [System.NonSerialized]
114     public float lastStartTime = 0.0f;
115  
116     [System.NonSerialized]
117     public float lastButtonDownTime = -100f;
118  
119     [System.NonSerialized]
120     public Vector3 jumpDir = Vector3.up;
121 }
122  
123 public CharacterMotorJumping  jumping = new CharacterMotorJumping();
124  
125 [System.Serializable]
126 public class CharacterMotorMovingPlatform {
127     public bool enabled = true;
128  
129     public MovementTransferOnJump movementTransfer = MovementTransferOnJump.PermaTransfer;
130  
131     [System.NonSerialized]
132     public Transform hitPlatform;
133  
134     [System.NonSerialized]
135     public Transform activePlatform;
136  
137     [System.NonSerialized]
138     public Vector3 activeLocalPoint;
139  
140     [System.NonSerialized]
141     public Vector3 activeGlobalPoint;
142  
143     [System.NonSerialized]
144     public Quaternion activeLocalRotation;
145  
146     [System.NonSerialized]
147     public Quaternion activeGlobalRotation;
148  
149     [System.NonSerialized]
150     public Matrix4x4 lastMatrix;
151  
152     [System.NonSerialized]
153     public Vector3 platformVelocity;
154  
155     [System.NonSerialized]
156     public bool newPlatform;
157 }
158  
159 public CharacterMotorMovingPlatform movingPlatform  = new CharacterMotorMovingPlatform();
160  
161 [System.Serializable]
162 public class CharacterMotorSliding {
163     // Does the character slide on too steep surfaces?
164     public bool enabled = true;
165  
166     // How fast does the character slide on steep surfaces?
167     public float slidingSpeed  = 15f;
168  
169     // How much can the player control the sliding direction?
170     // If the value is 0.5 the player can slide sideways with half the speed of the downwards sliding speed.
171     public float sidewaysControl = 1.0f;
172  
173     // How much can the player influence the sliding speed?
174     // If the value is 0.5 the player can speed the sliding up to 150% or slow it down to 50%.
175     public float speedControl  = 0.4f;
176 }
177  
178 public CharacterMotorSliding sliding  = new CharacterMotorSliding();
179  
180 [System.NonSerialized]
181 public bool grounded = true;
182  
183 [System.NonSerialized]
184 public Vector3 groundNormal = Vector3.zero;
185  
186 private Vector3  lastGroundNormal = Vector3.zero;
187  
188 private Transform tr;
189  
190 private CharacterController  controller ;
191  
192 void Awake () {
193     controller = GetComponent <CharacterController>();
194     tr = transform;
195 }
196  
197  //=======================================================
198 private void UpdateFunction () {
199     // We copy the actual velocity into a temporary variable that we can manipulate.
200     Vector3 velocity  = movement.velocity;
201  
202     // Update velocity based on input
203     velocity = ApplyInputVelocityChange(velocity);
204  
205     // Apply gravity and jumping force
206     velocity = ApplyGravityAndJumping (velocity);
207  
208     // Moving platform support
209     Vector3 moveDistance  = Vector3.zero;
210     if (MoveWithPlatform()) {
211         Vector3 newGlobalPoint  = movingPlatform.activePlatform.TransformPoint(movingPlatform.activeLocalPoint);
212         moveDistance = (newGlobalPoint - movingPlatform.activeGlobalPoint);
213         if (moveDistance != Vector3.zero)
214             controller.Move(moveDistance);
215  
216         // Support moving platform rotation as well:
217         Quaternion newGlobalRotation  = movingPlatform.activePlatform.rotation * movingPlatform.activeLocalRotation;
218         Quaternion rotationDiff  = newGlobalRotation * Quaternion.Inverse(movingPlatform.activeGlobalRotation);
219  
220         var yRotation = rotationDiff.eulerAngles.y;
221         if (yRotation != 0) {
222             // Prevent rotation of the local up vector
223             tr.Rotate(0, yRotation, 0);
224         }
225     }
226  
227     // Save lastPosition for velocity calculation.
228     Vector3 lastPosition  = tr.position;
229  
230     // We always want the movement to be framerate independent.  Multiplying by Time.deltaTime does this.
231     Vector3 currentMovementOffset = velocity * Time.deltaTime;
232  
233     // Find out how much we need to push towards the ground to avoid loosing grouning
234     // when walking down a step or over a sharp change in slope.
235     float pushDownOffset  = Mathf.Max(controller.stepOffset, new Vector3(currentMovementOffset.x, 0, currentMovementOffset.z).magnitude);
236     if (grounded)
237         currentMovementOffset -= pushDownOffset * Vector3.up;
238  
239     // Reset variables that will be set by collision function
240     movingPlatform.hitPlatform = null;
241     groundNormal = Vector3.zero;
242  
243        // Move our character!
244     movement.collisionFlags = controller.Move (currentMovementOffset);
245  
246     movement.lastHitPoint = movement.hitPoint;
247     lastGroundNormal = groundNormal;
248  
249     if (movingPlatform.enabled && movingPlatform.activePlatform != movingPlatform.hitPlatform) {
250         if (movingPlatform.hitPlatform != null) {
251             movingPlatform.activePlatform = movingPlatform.hitPlatform;
252             movingPlatform.lastMatrix = movingPlatform.hitPlatform.localToWorldMatrix;
253             movingPlatform.newPlatform = true;
254         }
255     }
256  
257     // Calculate the velocity based on the current and previous position.  
258     // This means our velocity will only be the amount the character actually moved as a result of collisions.
259     Vector3 oldHVelocity  = new Vector3(velocity.x, 0, velocity.z);
260     movement.velocity = (tr.position - lastPosition) / Time.deltaTime;
261     Vector3 newHVelocity  = new Vector3(movement.velocity.x, 0, movement.velocity.z);
262  
263     // The CharacterController can be moved in unwanted directions when colliding with things.
264     // We want to prevent this from influencing the recorded velocity.
265     if (oldHVelocity == Vector3.zero) {
266         movement.velocity = new Vector3(0, movement.velocity.y, 0);
267     }
268     else {
269         float projectedNewVelocity  = Vector3.Dot(newHVelocity, oldHVelocity) / oldHVelocity.sqrMagnitude;
270         movement.velocity = oldHVelocity * Mathf.Clamp01(projectedNewVelocity) + movement.velocity.y * Vector3.up;
271     }
272  
273     if (movement.velocity.y < velocity.y - 0.001) {
274         if (movement.velocity.y < 0) {
275             // Something is forcing the CharacterController down faster than it should.
276             // Ignore this
277             movement.velocity.y = velocity.y;
278         }
279         else {
280             // The upwards movement of the CharacterController has been blocked.
281             // This is treated like a ceiling collision - stop further jumping here.
282             jumping.holdingJumpButton = false;
283         }
284     }
285  
286     // We were grounded but just loosed grounding
287     if (grounded && !IsGroundedTest()) {
288         grounded = false;
289  
290         // Apply inertia from platform
291         if (movingPlatform.enabled &&
292             (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
293             movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
294         ) {
295             movement.frameVelocity = movingPlatform.platformVelocity;
296             movement.velocity += movingPlatform.platformVelocity;
297         }
298  
299         SendMessage("OnFall", SendMessageOptions.DontRequireReceiver);
300         // We pushed the character down to ensure it would stay on the ground if there was any.
301         // But there wasn‘t so now we cancel the downwards offset to make the fall smoother.
302         tr.position += pushDownOffset * Vector3.up;
303     }
304     // We were not grounded but just landed on something
305     else if (!grounded && IsGroundedTest()) {
306         grounded = true;
307         jumping.jumping = false;
308         SubtractNewPlatformVelocity();
309  
310         SendMessage("OnLand", SendMessageOptions.DontRequireReceiver);
311     }
312  
313     // Moving platforms support
314     if (MoveWithPlatform()) {
315         // Use the center of the lower half sphere of the capsule as reference point.
316         // This works best when the character is standing on moving tilting platforms. 
317         movingPlatform.activeGlobalPoint = tr.position + Vector3.up * (controller.center.y - controller.height*0.5f + controller.radius);
318         movingPlatform.activeLocalPoint = movingPlatform.activePlatform.InverseTransformPoint(movingPlatform.activeGlobalPoint);
319  
320         // Support moving platform rotation as well:
321         movingPlatform.activeGlobalRotation = tr.rotation;
322         movingPlatform.activeLocalRotation = Quaternion.Inverse(movingPlatform.activePlatform.rotation) * movingPlatform.activeGlobalRotation; 
323     }
324 }
325  
326 void FixedUpdate () {
327     if (movingPlatform.enabled) {
328         if (movingPlatform.activePlatform != null) {
329             if (!movingPlatform.newPlatform) {
330                 Vector3 lastVelocity  = movingPlatform.platformVelocity;
331  
332                 movingPlatform.platformVelocity = (
333                     movingPlatform.activePlatform.localToWorldMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
334                     - movingPlatform.lastMatrix.MultiplyPoint3x4(movingPlatform.activeLocalPoint)
335                 ) / Time.deltaTime;
336             }
337             movingPlatform.lastMatrix = movingPlatform.activePlatform.localToWorldMatrix;
338             movingPlatform.newPlatform = false;
339         }
340         else {
341             movingPlatform.platformVelocity = Vector3.zero;    
342         }
343     }
344  
345     if (useFixedUpdate)
346         UpdateFunction();
347 }
348  
349 void Update () {
350     if (!useFixedUpdate)
351         UpdateFunction();
352 }
353  
354 private Vector3 ApplyInputVelocityChange (Vector3 velocity) {    
355     if (!canControl)
356         inputMoveDirection = Vector3.zero;
357  
358     // Find desired velocity
359     Vector3 desiredVelocity;
360     if (grounded && TooSteep()) {
361         // The direction we‘re sliding in
362         desiredVelocity = new Vector3(groundNormal.x, 0, groundNormal.z).normalized;
363         // Find the input movement direction projected onto the sliding direction
364         var projectedMoveDir = Vector3.Project(inputMoveDirection, desiredVelocity);
365         // Add the sliding direction, the spped control, and the sideways control vectors
366         desiredVelocity = desiredVelocity + projectedMoveDir * sliding.speedControl + (inputMoveDirection - projectedMoveDir) * sliding.sidewaysControl;
367         // Multiply with the sliding speed
368         desiredVelocity *= sliding.slidingSpeed;
369     }
370     else
371         desiredVelocity = GetDesiredHorizontalVelocity();
372  
373     if (movingPlatform.enabled && movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer) {
374         desiredVelocity += movement.frameVelocity;
375         desiredVelocity.y = 0;
376     }
377  
378     if (grounded)
379         desiredVelocity = AdjustGroundVelocityToNormal(desiredVelocity, groundNormal);
380     else
381         velocity.y = 0;
382  
383     // Enforce max velocity change
384     float maxVelocityChange  = GetMaxAcceleration(grounded) * Time.deltaTime;
385     Vector3 velocityChangeVector  = (desiredVelocity - velocity);
386     if (velocityChangeVector.sqrMagnitude > maxVelocityChange * maxVelocityChange) {
387         velocityChangeVector = velocityChangeVector.normalized * maxVelocityChange;
388     }
389     // If we‘re in the air and don‘t have control, don‘t apply any velocity change at all.
390     // If we‘re on the ground and don‘t have control we do apply it - it will correspond to friction.
391     if (grounded || canControl)
392         velocity += velocityChangeVector;
393  
394     if (grounded) {
395         // When going uphill, the CharacterController will automatically move up by the needed amount.
396         // Not moving it upwards manually prevent risk of lifting off from the ground.
397         // When going downhill, DO move down manually, as gravity is not enough on steep hills.
398         velocity.y = Mathf.Min(velocity.y, 0);
399     }
400  
401     return velocity;
402 }
403  
404 private Vector3 ApplyGravityAndJumping (Vector3 velocity) {
405  
406     if (!inputJump || !canControl) {
407         jumping.holdingJumpButton = false;
408         jumping.lastButtonDownTime = -100;
409     }
410  
411     if (inputJump && jumping.lastButtonDownTime < 0 && canControl)
412         jumping.lastButtonDownTime = Time.time;
413  
414     if (grounded)
415         velocity.y = Mathf.Min(0, velocity.y) - movement.gravity * Time.deltaTime;
416     else {
417         velocity.y = movement.velocity.y - movement.gravity * Time.deltaTime;
418  
419         // When jumping up we don‘t apply gravity for some time when the user is holding the jump button.
420         // This gives more control over jump height by pressing the button longer.
421         if (jumping.jumping && jumping.holdingJumpButton) {
422             // Calculate the duration that the extra jump force should have effect.
423             // If we‘re still less than that duration after the jumping time, apply the force.
424             if (Time.time < jumping.lastStartTime + jumping.extraHeight / CalculateJumpVerticalSpeed(jumping.baseHeight)) {
425                 // Negate the gravity we just applied, except we push in jumpDir rather than jump upwards.
426                 velocity += jumping.jumpDir * movement.gravity * Time.deltaTime;
427             }
428         }
429  
430         // Make sure we don‘t fall any faster than maxFallSpeed. This gives our character a terminal velocity.
431         velocity.y = Mathf.Max (velocity.y, -movement.maxFallSpeed);
432     }
433  
434     if (grounded) {
435         // Jump only if the jump button was pressed down in the last 0.2 seconds.
436         // We use this check instead of checking if it‘s pressed down right now
437         // because players will often try to jump in the exact moment when hitting the ground after a jump
438         // and if they hit the button a fraction of a second too soon and no new jump happens as a consequence,
439         // it‘s confusing and it feels like the game is buggy.
440         if (jumping.enabled && canControl && (Time.time - jumping.lastButtonDownTime < 0.2)) {
441             grounded = false;
442             jumping.jumping = true;
443             jumping.lastStartTime = Time.time;
444             jumping.lastButtonDownTime = -100;
445             jumping.holdingJumpButton = true;
446  
447             // Calculate the jumping direction
448             if (TooSteep())
449                 jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.steepPerpAmount);
450             else
451                 jumping.jumpDir = Vector3.Slerp(Vector3.up, groundNormal, jumping.perpAmount);
452  
453             // Apply the jumping force to the velocity. Cancel any vertical velocity first.
454             velocity.y = 0;
455             velocity += jumping.jumpDir * CalculateJumpVerticalSpeed (jumping.baseHeight);
456  
457             // Apply inertia from platform
458             if (movingPlatform.enabled &&
459                 (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
460                 movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
461             ) {
462                 movement.frameVelocity = movingPlatform.platformVelocity;
463                 velocity += movingPlatform.platformVelocity;
464             }
465  
466             SendMessage("OnJump", SendMessageOptions.DontRequireReceiver);
467         }
468         else {
469             jumping.holdingJumpButton = false;
470         }
471     }
472  
473     return velocity;
474 }
475  
476 void OnControllerColliderHit (ControllerColliderHit hit) {
477     if (hit.normal.y > 0 && hit.normal.y > groundNormal.y && hit.moveDirection.y < 0) {
478         if ((hit.point - movement.lastHitPoint).sqrMagnitude > 0.001 || lastGroundNormal == Vector3.zero)
479             groundNormal = hit.normal;
480         else
481             groundNormal = lastGroundNormal;
482  
483         movingPlatform.hitPlatform = hit.collider.transform;
484         movement.hitPoint = hit.point;
485         movement.frameVelocity = Vector3.zero;
486     }
487 }
488  
489 private IEnumerator SubtractNewPlatformVelocity () {
490     // When landing, subtract the velocity of the new ground from the character‘s velocity
491     // since movement in ground is relative to the movement of the ground.
492     if (movingPlatform.enabled &&
493         (movingPlatform.movementTransfer == MovementTransferOnJump.InitTransfer ||
494         movingPlatform.movementTransfer == MovementTransferOnJump.PermaTransfer)
495     ) {
496         // If we landed on a new platform, we have to wait for two FixedUpdates
497         // before we know the velocity of the platform under the character
498         if (movingPlatform.newPlatform) {
499             Transform platform  = movingPlatform.activePlatform;
500             yield return new WaitForFixedUpdate();
501             yield return new WaitForFixedUpdate();
502             if (grounded && platform == movingPlatform.activePlatform)
503                 yield return 1;
504         }
505         movement.velocity -= movingPlatform.platformVelocity;
506     }
507 }
508  
509 private bool MoveWithPlatform () {
510     return (
511         movingPlatform.enabled
512         && (grounded || movingPlatform.movementTransfer == MovementTransferOnJump.PermaLocked)
513         && movingPlatform.activePlatform != null
514     );
515 }
516  
517 private Vector3 GetDesiredHorizontalVelocity () {
518     // Find desired velocity
519     Vector3 desiredLocalDirection  = tr.InverseTransformDirection(inputMoveDirection);
520     float maxSpeed  = MaxSpeedInDirection(desiredLocalDirection);
521     if (grounded) {
522         // Modify max speed on slopes based on slope speed multiplier curve
523         var movementSlopeAngle = Mathf.Asin(movement.velocity.normalized.y)  * Mathf.Rad2Deg;
524         maxSpeed *= movement.slopeSpeedMultiplier.Evaluate(movementSlopeAngle);
525     }
526     return tr.TransformDirection(desiredLocalDirection * maxSpeed);
527 }
528  
529 private Vector3 AdjustGroundVelocityToNormal (Vector3 hVelocity, Vector3 groundNormal) {
530     Vector3 sideways  = Vector3.Cross(Vector3.up, hVelocity);
531     return Vector3.Cross(sideways, groundNormal).normalized * hVelocity.magnitude;
532 }
533  
534 private bool IsGroundedTest () {
535     return (groundNormal.y > 0.01);
536 }
537  
538 float GetMaxAcceleration (bool grounded) {
539     // Maximum acceleration on ground and in air
540     if (grounded)
541         return movement.maxGroundAcceleration;
542     else
543         return movement.maxAirAcceleration;
544 }
545  
546 float CalculateJumpVerticalSpeed (float targetJumpHeight) {
547     // From the jump height and gravity we deduce the upwards speed 
548     // for the character to reach at the apex.
549     return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);
550 }
551  
552 bool IsJumping () {
553     return jumping.jumping;
554 }
555  
556 bool IsSliding () {
557     return (grounded && sliding.enabled && TooSteep());
558 }
559  
560 bool IsTouchingCeiling () {
561     return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
562 }
563  
564 bool IsGrounded () {
565     return grounded;
566 }
567  
568 bool TooSteep () {
569     return (groundNormal.y <= Mathf.Cos(controller.slopeLimit * Mathf.Deg2Rad));
570 }
571  
572 Vector3 GetDirection () {
573     return inputMoveDirection;
574 }
575  
576 void  SetControllable (bool controllable) {
577     canControl = controllable;
578 }
579  
580 // Project a direction onto elliptical quater segments based on forward, sideways, and backwards speed.
581 // The function returns the length of the resulting vector.
582 float MaxSpeedInDirection (Vector3 desiredMovementDirection) {
583     if (desiredMovementDirection == Vector3.zero)
584         return 0;
585     else {
586         float zAxisEllipseMultiplier = (desiredMovementDirection.z > 0 ? movement.maxForwardSpeed : movement.maxBackwardsSpeed) / movement.maxSidewaysSpeed;
587         Vector3 temp = new Vector3(desiredMovementDirection.x, 0, desiredMovementDirection.z / zAxisEllipseMultiplier).normalized;
588         float length = new Vector3(temp.x, 0, temp.z * zAxisEllipseMultiplier).magnitude * movement.maxSidewaysSpeed;
589         return length;
590     }
591 }
592  
593 void SetVelocity (Vector3 velocity) {
594     grounded = false;
595     movement.velocity = velocity;
596     movement.frameVelocity = Vector3.zero;
597     SendMessage("OnExternalVelocity");
598 }
599  
600 // Require a character controller to be attached to the same game object
601  
602 //@script RequireComponent (CharacterController)
603 //@script AddComponentMenu ("Character/Character Motor")
604  
605 }

FPSImputController.cs 用于第一人称控制角色移动,这里会监听主角按下的方向键最后传给CharacterMotor去计算模型的位置与旋转的角度

FPSImputController.cs  代码:

 1 using UnityEngine;
 2 using System.Collections;
 3  
 4 /**
 5 *用于第一人称控制角色移动,这里会监听主角按下的方向键最后传给CharacterMotor去计算模型的位置与旋转的角度
 6  */
 7  
 8 [RequireComponent(typeof(CharacterMotor))]
 9 [AddComponentMenu("Character/FPS Input Controller")]
10  
11 public class FPSInputController : MonoBehaviour {
12  
13 private CharacterMotor motor ;
14  
15 // Use this for initialization
16 void Awake () {
17     motor = GetComponent<CharacterMotor>();
18 }
19  
20 // Update is called once per frame
21 void Update () {
22     // Get the input vector from kayboard or analog stick
23     Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), 0, Input.GetAxis("Vertical"));
24  
25     if (directionVector != Vector3.zero) {
26         // Get the length of the directon vector and then normalize it
27         // Dividing by the length is cheaper than normalizing when we already have the length anyway
28         var directionLength = directionVector.magnitude;
29         directionVector = directionVector / directionLength;
30  
31         // Make sure the length is no bigger than 1
32         directionLength = Mathf.Min(1, directionLength);
33  
34         // Make the input vector more sensitive towards the extremes and less sensitive in the middle
35         // This makes it easier to control slow speeds when using analog sticks
36         directionLength = directionLength * directionLength;
37  
38         // Multiply the normalized direction vector by the modified length
39         directionVector = directionVector * directionLength;
40     }
41  
42     // Apply the direction to the CharacterMotor
43     motor.inputMoveDirection = transform.rotation * directionVector;
44     motor.inputJump = Input.GetButton("Jump");
45 }
46  
47 }

PlatFormInputController.cs 与FPSInputController一样会控制主角,但是会更加精细的计算模型的旋转的插值系数

PlatFormInputController.cs  代码:

 1 using UnityEngine;
 2 using System.Collections;
 3  
 4 /**
 5  *  与FPSInputController一样会控制主角,但是会更加精细的计算模型的旋转的插值系数
 6  */
 7  
 8 [RequireComponent(typeof(CharacterController))]
 9 [AddComponentMenu("Character/Platform Input Controller")]
10 public class PlatformInputController : MonoBehaviour {
11  
12 public bool autoRotate = true;
13 public float  maxRotationSpeed = 360;
14  
15 private CharacterMotor motor ;
16  
17 // Use this for initialization
18 void Awake () {
19     motor = GetComponent<CharacterMotor>();
20 }
21  
22 // Update is called once per frame
23 void Update () {
24     // Get the input vector from kayboard or analog stick
25     Vector3 directionVector = new Vector3(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical"), 0);
26  
27     if (directionVector != Vector3.zero) {
28         // Get the length of the directon vector and then normalize it
29         // Dividing by the length is cheaper than normalizing when we already have the length anyway
30         var directionLength = directionVector.magnitude;
31         directionVector = directionVector / directionLength;
32  
33         // Make sure the length is no bigger than 1
34         directionLength = Mathf.Min(1, directionLength);
35  
36         // Make the input vector more sensitive towards the extremes and less sensitive in the middle
37         // This makes it easier to control slow speeds when using analog sticks
38         directionLength = directionLength * directionLength;
39  
40         // Multiply the normalized direction vector by the modified length
41         directionVector = directionVector * directionLength;
42     }
43  
44     // Rotate the input vector into camera space so up is camera‘s up and right is camera‘s right
45     directionVector = Camera.main.transform.rotation * directionVector;
46  
47     // Rotate input vector to be perpendicular to character‘s up vector
48     var camToCharacterSpace = Quaternion.FromToRotation(-Camera.main.transform.forward, transform.up);
49     directionVector = (camToCharacterSpace * directionVector);
50  
51     // Apply the direction to the CharacterMotor
52     motor.inputMoveDirection = directionVector;
53     motor.inputJump = Input.GetButton("Jump");
54  
55     // Set rotation to the move direction    
56     if (autoRotate && directionVector.sqrMagnitude > 0.01) {
57         Vector3 newForward  = ConstantSlerp(
58             transform.forward,
59             directionVector,
60             maxRotationSpeed * Time.deltaTime
61         );
62         newForward = ProjectOntoPlane(newForward, transform.up);
63         transform.rotation = Quaternion.LookRotation(newForward, transform.up);
64     }
65 }
66  
67 Vector3 ProjectOntoPlane (Vector3 v, Vector3 normal) {
68     return v - Vector3.Project(v, normal);
69 }
70  
71 Vector3 ConstantSlerp (Vector3 from, Vector3 to, float angle) {
72     float value = Mathf.Min(1, angle / Vector3.Angle(from, to));
73     return Vector3.Slerp(from, to, value);
74 }
75  
76 }

ThirdPersonCamera.cs  主要控制第三人称视角时摄像机的控制

ThirdPersonCamera.cs  代码:

  1 using UnityEngine;
  2 using System.Collections;
  3  
  4 /**
  5  *  主要控制第三人称视角时摄像机的控制
  6  */
  7  
  8 public class ThirdPersonCamera : MonoBehaviour {
  9  
 10 public Transform cameraTransform;
 11 private Transform _target;
 12  
 13 public float distance = 7.0f;
 14  
 15 public float height = 3.0f;
 16  
 17 public float angularSmoothLag = 0.3f;
 18 public float angularMaxSpeed = 15.0f;
 19  
 20 public float heightSmoothLag = 0.3f;
 21  
 22 public float snapSmoothLag = 0.2f;
 23 public float snapMaxSpeed = 720.0f;
 24  
 25 public float clampHeadPositionScreenSpace = 0.75f;
 26  
 27 public float lockCameraTimeout = 0.2f;
 28  
 29 private Vector3 headOffset = Vector3.zero;
 30 private Vector3 centerOffset = Vector3.zero;
 31  
 32 private float heightVelocity = 0.0f;
 33 private float  angleVelocity = 0.0f;
 34 private bool snap = false;
 35 private ThirdPersonController controller;
 36 private float targetHeight = 100000.0f; 
 37  
 38 void Awake ()
 39 {
 40     if(!cameraTransform && Camera.main)
 41         cameraTransform = Camera.main.transform;
 42     if(!cameraTransform) {
 43         Debug.Log("Please assign a camera to the ThirdPersonCamera script.");
 44         enabled = false;    
 45     }
 46  
 47     _target = transform;
 48     if (_target)
 49     {
 50         controller = _target.GetComponent<ThirdPersonController>();
 51     }
 52  
 53     if (controller)
 54     {
 55         CharacterController characterController  = (CharacterController)_target.collider;
 56         centerOffset = characterController.bounds.center - _target.position;
 57         headOffset = centerOffset;
 58         headOffset.y = characterController.bounds.max.y - _target.position.y;
 59     }
 60     else
 61         Debug.Log("Please assign a target to the camera that has a ThirdPersonController script attached.");
 62  
 63     Cut(_target, centerOffset);
 64 }
 65  
 66 void DebugDrawStuff ()
 67 {
 68     Debug.DrawLine(_target.position, _target.position + headOffset);
 69  
 70 }
 71  
 72 float  AngleDistance (float a , float b )
 73 {
 74     a = Mathf.Repeat(a, 360);
 75     b = Mathf.Repeat(b, 360);
 76  
 77     return Mathf.Abs(b - a);
 78 }
 79  
 80 void  Apply (Transform dummyTarget, Vector3 dummyCenter)
 81 {
 82     // Early out if we don‘t have a target
 83     if (!controller)
 84         return;
 85  
 86     Vector3 targetCenter = _target.position + centerOffset;
 87     Vector3 targetHead = _target.position + headOffset;
 88  
 89 //    DebugDrawStuff();
 90  
 91     // Calculate the current & target rotation angles
 92     float originalTargetAngle = _target.eulerAngles.y;
 93     float currentAngle = cameraTransform.eulerAngles.y;
 94  
 95     // Adjust real target angle when camera is locked
 96     float targetAngle = originalTargetAngle; 
 97  
 98     // When pressing Fire2 (alt) the camera will snap to the target direction real quick.
 99     // It will stop snapping when it reaches the target
100     if (Input.GetButton("Fire2"))
101         snap = true;
102  
103     if (snap)
104     {
105         // We are close to the target, so we can stop snapping now!
106         if (AngleDistance (currentAngle, originalTargetAngle) < 3.0)
107             snap = false;
108  
109         currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, snapSmoothLag, snapMaxSpeed);
110     }
111     // Normal camera motion
112     else
113     {
114  
115         if (controller.GetLockCameraTimer () < lockCameraTimeout)
116         {
117             targetAngle = currentAngle;
118         }
119  
120         // Lock the camera when moving backwards!
121         // * It is really confusing to do 180 degree spins when turning around.
122         if (AngleDistance (currentAngle, targetAngle) > 160 && controller.IsMovingBackwards ())
123             targetAngle += 180;
124  
125         currentAngle = Mathf.SmoothDampAngle(currentAngle, targetAngle, ref angleVelocity, angularSmoothLag, angularMaxSpeed);
126     }
127  
128     // When jumping don‘t move camera upwards but only down!
129     if (controller.IsJumping ())
130     {
131         // We‘d be moving the camera upwards, do that only if it‘s really high
132         float newTargetHeight = targetCenter.y + height;
133         if (newTargetHeight < targetHeight || newTargetHeight - targetHeight > 5)
134             targetHeight = targetCenter.y + height;
135     }
136     // When walking always update the target height
137     else
138     {
139         targetHeight = targetCenter.y + height;
140     }
141  
142     // Damp the height
143     float currentHeight = cameraTransform.position.y;
144     currentHeight = Mathf.SmoothDamp (currentHeight, targetHeight, ref heightVelocity, heightSmoothLag);
145  
146     // Convert the angle into a rotation, by which we then reposition the camera
147     Quaternion currentRotation = Quaternion.Euler (0, currentAngle, 0);
148  
149     // Set the position of the camera on the x-z plane to:
150     // distance meters behind the target
151     cameraTransform.position = targetCenter;
152     cameraTransform.position += currentRotation * Vector3.back * distance;
153  
154     // Set the height of the camera
155     cameraTransform.position = new Vector3(cameraTransform.position.x,currentHeight,cameraTransform.position.z);
156  
157     // Always look at the target    
158     SetUpRotation(targetCenter, targetHead);
159 }
160  
161 void LateUpdate () {
162     Apply (transform, Vector3.zero);
163 }
164  
165 void  Cut (Transform dummyTarget , Vector3 dummyCenter)
166 {
167     float oldHeightSmooth = heightSmoothLag;
168     float oldSnapMaxSpeed = snapMaxSpeed;
169     float oldSnapSmooth = snapSmoothLag;
170  
171     snapMaxSpeed = 10000;
172     snapSmoothLag = 0.001f;
173     heightSmoothLag = 0.001f;
174  
175     snap = true;
176     Apply (transform, Vector3.zero);
177  
178     heightSmoothLag = oldHeightSmooth;
179     snapMaxSpeed = oldSnapMaxSpeed;
180     snapSmoothLag = oldSnapSmooth;
181 }
182  
183 void SetUpRotation (Vector3 centerPos,Vector3  headPos)
184 {
185     // Now it‘s getting hairy. The devil is in the details here, the big issue is jumping of course.
186     // * When jumping up and down we don‘t want to center the guy in screen space.
187     //  This is important to give a feel for how high you jump and avoiding large camera movements.
188     //   
189     // * At the same time we dont want him to ever go out of screen and we want all rotations to be totally smooth.
190     //
191     // So here is what we will do:
192     //
193     // 1. We first find the rotation around the y axis. Thus he is always centered on the y-axis
194     // 2. When grounded we make him be centered
195     // 3. When jumping we keep the camera rotation but rotate the camera to get him back into view if his head is above some threshold
196     // 4. When landing we smoothly interpolate towards centering him on screen
197     Vector3 cameraPos = cameraTransform.position;
198     Vector3 offsetToCenter = centerPos - cameraPos;
199  
200     // Generate base rotation only around y-axis
201     Quaternion yRotation = Quaternion.LookRotation(new Vector3(offsetToCenter.x, 0, offsetToCenter.z));
202  
203     Vector3 relativeOffset = Vector3.forward * distance + Vector3.down * height;
204     cameraTransform.rotation = yRotation * Quaternion.LookRotation(relativeOffset);
205  
206     // Calculate the projected center position and top position in world space
207     Ray centerRay = cameraTransform.camera.ViewportPointToRay(new Vector3(0.5f, 0.5f, 1f));
208     Ray topRay = cameraTransform.camera.ViewportPointToRay(new Vector3(0.5f, clampHeadPositionScreenSpace, 1f));
209  
210     Vector3 centerRayPos = centerRay.GetPoint(distance);
211     Vector3 topRayPos = topRay.GetPoint(distance);
212  
213     float centerToTopAngle = Vector3.Angle(centerRay.direction, topRay.direction);
214  
215     float heightToAngle = centerToTopAngle / (centerRayPos.y - topRayPos.y);
216  
217     float extraLookAngle = heightToAngle * (centerRayPos.y - centerPos.y);
218     if (extraLookAngle < centerToTopAngle)
219     {
220         extraLookAngle = 0;
221     }
222     else
223     {
224         extraLookAngle = extraLookAngle - centerToTopAngle;
225         cameraTransform.rotation *= Quaternion.Euler(-extraLookAngle, 0, 0);
226     }
227 }
228  
229     Vector3 GetCenterOffset ()
230     {
231         return centerOffset;
232     }
233  
234 }

ThirdPersonController.cs  主要更新第三人称视角控制主角时播放的各种动画,主角的移动等

ThirdPersonController.cs 代码:

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

MouseLook.cs 自带的C#  代码:

 1 using UnityEngine;
 2 using System.Collections;
 3 
 4 /// MouseLook rotates the transform based on the mouse delta.
 5 /// Minimum and Maximum values can be used to constrain the possible rotation
 6 
 7 /// To make an FPS style character:
 8 /// - Create a capsule.
 9 /// - Add the MouseLook script to the capsule.
10 ///   -> Set the mouse look to use LookX. (You want to only turn character but not tilt it)
11 /// - Add FPSInputController script to the capsule
12 ///   -> A CharacterMotor and a CharacterController component will be automatically added.
13 
14 /// - Create a camera. Make the camera a child of the capsule. Reset it‘s transform.
15 /// - Add a MouseLook script to the camera.
16 ///   -> Set the mouse look to use LookY. (You want the camera to tilt up and down like a head. The character already turns.)
17 [AddComponentMenu("Camera-Control/Mouse Look")]
18 public class MouseLook : MonoBehaviour {
19 
20     public enum RotationAxes { MouseXAndY = 0, MouseX = 1, MouseY = 2 }
21     public RotationAxes axes = RotationAxes.MouseXAndY;
22     public float sensitivityX = 15F;
23     public float sensitivityY = 15F;
24 
25     public float minimumX = -360F;
26     public float maximumX = 360F;
27 
28     public float minimumY = -60F;
29     public float maximumY = 60F;
30 
31     float rotationY = 0F;
32 
33     void Update ()
34     {
35         if (axes == RotationAxes.MouseXAndY)
36         {
37             float rotationX = transform.localEulerAngles.y + Input.GetAxis("Mouse X") * sensitivityX;
38             
39             rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
40             rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
41             
42             transform.localEulerAngles = new Vector3(-rotationY, rotationX, 0);
43         }
44         else if (axes == RotationAxes.MouseX)
45         {
46             transform.Rotate(0, Input.GetAxis("Mouse X") * sensitivityX, 0);
47         }
48         else
49         {
50             rotationY += Input.GetAxis("Mouse Y") * sensitivityY;
51             rotationY = Mathf.Clamp (rotationY, minimumY, maximumY);
52             
53             transform.localEulerAngles = new Vector3(-rotationY, transform.localEulerAngles.y, 0);
54         }
55     }
56     
57     void Start ()
58     {
59         // Make the rigid body not change rotation
60         if (GetComponent<Rigidbody>())
61             GetComponent<Rigidbody>().freezeRotation = true;
62     }
63 }

 

C#版官方角色控制器脚本

标签:

原文地址:http://www.cnblogs.com/shakyamuni/p/5115371.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!