//--------------------------------------------------------------------------------------MyCameraScrolling.js
private var target : Transform;//摄像机要跟随的目标
var distance = 25.0;//摄像机距离目标多远
var springiness = 40.0;//相机跟随目标的严格程度,值越小摄像机会变懒
 private var targetLock = false;
private var savedInterpolationSetting = RigidbodyInterpolation.None;
 function Awake () {
  // Set up our convenience references.
  
 } function SetTarget (newTarget : Transform, snap : boolean){
  
  if  (target) {//假如摄像机跟随的目标不为空 
   targetRigidbody = target.GetComponent (Rigidbody);//获取刚体组件
   if  (targetRigidbody)//目标具有刚体属性
    targetRigidbody.interpolation = savedInterpolationSetting;//设置刚体插值
  }
  
  target = newTarget;//重新设置目标
  
  if (target) {
   targetRigidbody = target.GetComponent (Rigidbody);
   if (targetRigidbody) {
    savedInterpolationSetting = targetRigidbody.interpolation;
    targetRigidbody.interpolation = RigidbodyInterpolation.Interpolate;
   }
  }
  
  if  (snap) {//是否关闭摄像机
   transform.position = GetGoalPosition ();
  }
  
 }function SetTarget (newTarget : Transform) {
  SetTarget (newTarget, false);
 } function LateUpdate () {
  // Where should our camera be looking right now?
  var goalPosition = GetGoalPosition ();
  
  // Interpolate between the current camera position and the goal position.
  // See the documentation on Vector3.Lerp () for more information.
  transform.position = Vector3.Lerp (transform.position, goalPosition, Time.deltaTime * springiness);
  transform.LookAt(target.position);//摄像机注视着玩家
 }function GetGoalPosition () {
 if  (!target)//如果没有目标就返回摄像机的位置
   return transform.position;
   
  var heightOffset = 6.0;//摄像机偏离目标的高度
  var distanceModifier = 1.0;//摄像机与目标的水平便宜量
  
  // 默认情况下,我们不会考虑任何目标速度的计算;
  var velocityLookAhead = 0.0;
  var maxLookAhead = Vector2 (0.0, 0.0);
  
  // 获取目标的额外属性组件,这里指的是-----脚本
  // 根据相对高度和距离粗略计算摄像机位置, 不考虑目标的速度。这个vector的x为0是 因为摄像机时正对着目标的所以x为0 摄像机是在目标的侧面而不是目标的背面
  var goalPosition = target.position + Vector3 (0, heightOffset, -distance * distanceModifier);
  
  //下面开始将目标的速度考虑在内
  var targetVelocity = Vector3.zero;//初始化无速度
  
  var targetRigidbody = target.GetComponent (Rigidbody);
  if (targetRigidbody)//获取目标的速度
   targetVelocity = targetRigidbody.velocity;
   
  // If we find a PlatformerController on the target, we can access a velocity from that!
  targetPlatformerController = target.GetComponent (MyPlatformerController);
  if (targetPlatformerController)
   targetVelocity = targetPlatformerController.GetVelocity ();//从该脚本中获取目标的速度
   
  var lookAhead = targetVelocity * velocityLookAhead;
  
  //限制lookAhead。x的值在-maxLookAhead.x和maxLookAhead.x之间
  //限制value的值在min和max之间, 如果value小于min,返回min。 如果value大于max,返回max,否则返回value 
  
  lookAhead.x = Mathf.Clamp (lookAhead.x, -maxLookAhead.x, maxLookAhead.x);
  lookAhead.y = Mathf.Clamp (lookAhead.y, -maxLookAhead.y, maxLookAhead.y);
  
  // We never want to take z velocity into account as this is 2D.  Just make sure it's zero.
  lookAhead.z = 0.0;
  
  goalPosition += lookAhead;
  
  var clampOffset = Vector3.zero;
  
  var cameraPositionSave = transform.position;//摄像机的旧的位置
  transform.position = goalPosition;//重新设置摄像机的位置
  
  //一下四行计算的是摄像机有没有超过整个大场景边框
  /*var targetViewportPosition = camera.WorldToViewportPoint (target.position);//目标在窗口(记住是窗口)中的位置
  var upperRightCameraInWorld = camera.ViewportToWorldPoint (Vector3 (1.0, 1.0, targetViewportPosition.z));
  // Find out how far outside the world the camera is right now.
  clampOffset.x = Mathf.Min (levelBounds.xMax - upperRightCameraInWorld.x, 0.0);
  clampOffset.y = Mathf.Min ((levelBounds.yMax - upperRightCameraInWorld.y), 0.0);*/
  
  return goalPosition;
 }
 function Start () {}
function Update () {
}
 
//-------------------------------------------------MyCameraForcus.js
private var cameraScrolling : MyCameraScrolling;
// Who is the player controlling
 private var selected = 0;// List of objects to control
 public var targets : Transform;function Awake () {
 // Get the reference to our CameraScrolling script attached to this camera;
  cameraScrolling = GetComponent(MyCameraScrolling);
  
  // Set the scrolling camera's target to be our character at the start.
  cameraScrolling.SetTarget (targets, true);
  
 } 
//-------------------------------------------------------------MyPlatformerController.js
 //是否需要对输入做出反应
 //sendmessage第二个参数的用法请看下面
 //SendMessageOptions.RequireReceiver //如果没有找到相应函数,会报错(默认是这个状态)
 //SendMessageOptions.DontRequireReceiver //即使没有找到相应函数,也不会报错,自动忽略
 var canControl = true;var spawnPoint : Transform;//玩家重生点
class MyPlatformerControllerMovement {
  // The speed when walking 
  var walkSpeed = 3.0;
  // when pressing "Fire1" button (control) we start running
  var runSpeed = 10.0; var inAirControlAcceleration = 1.0;
 // The gravity for the character
  var gravity = 60.0;
  var maxFallSpeed = 20.0; // How fast does the character change speeds?  Higher is faster.
  var speedSmoothing = 5.0; // This controls how fast the graphics of the character "turn around" when the player turns around using the controls.
  var rotationSmoothing = 10.0; // The current move direction in x-y.  This will always been (1,0,0) or (-1,0,0)
  // The next line, @System.NonSerialized , tells Unity to not serialize the variable or show it in the inspector view.  Very handy for organization!
  @System.NonSerialized
  var direction = Vector3.zero; // The current vertical speed
  @System.NonSerialized
  var verticalSpeed = 0.0; // The current movement speed.  This gets smoothed by speedSmoothing.
  @System.NonSerialized
  var speed = 0.0; // Is the user pressing the left or right movement keys?
  @System.NonSerialized
  var isMoving = false; // The last collision flags returned from controller.Move
  @System.NonSerialized


 var collisionFlags : CollisionFlags; //这是unity3d的碰撞信息,具体可以参考http://game.ceeger.com/Script/Enumerations/CollisionFlags/CollisionFlags.None.html

// We will keep track of an approximation of the character's current velocity, so that we return it from GetVelocity () for our camera to use for prediction.
  @System.NonSerialized
  var velocity : Vector3;
  
  // This keeps track of our current velocity while we're not grounded?
  @System.NonSerialized
  var inAirVelocity = Vector3.zero;//在空中的时候的速度 // This will keep track of how long we have we been in the air (not grounded)
  @System.NonSerialized
  var hangTime = 0.0;//在空中停留的时间
 }var movement : MyPlatformerControllerMovement;
// We will contain all the jumping related variables in one helper class for clarity.
 class MyPlatformerControllerJumping {
  // Can the character jump?
  var enabled = true; // How high do we jump when pressing jump and letting go immediately
  var height = 1.0;
  // We add extraHeight units (meters) on top when holding the button down longer while jumping
  var extraHeight = 4.1;
  
  // This prevents inordinarily too quick jumping
  // The next line, @System.NonSerialized , tells Unity to not serialize the variable or show it in the inspector view.  Very handy for organization!
  @System.NonSerialized
  var repeatTime = 0.05; @System.NonSerialized
  var timeout = 0.15; // Are we jumping? (Initiated with jump button and not grounded yet)
  @System.NonSerialized
  var jumping = false;
  
  @System.NonSerialized
  var reachedApex = false;// 达到最高点?
   
  // Last time the jump button was clicked down
  @System.NonSerialized
  var lastButtonTime = -10.0;
  
  // Last time we performed a jump
  @System.NonSerialized
  var lastTime = -1.0; // the height we jumped from (Used to determine for how long to apply extra jump power after jumping.)
  @System.NonSerialized
  var lastStartHeight = 0.0;
 }var jump : MyPlatformerControllerJumping;
private var controller : CharacterController;
// Moving platform support.
 private var activePlatform : Transform;
 private var activeLocalPlatformPoint : Vector3;
 private var activeGlobalPlatformPoint : Vector3;
 private var lastPlatformVelocity : Vector3;private var areEmittersOn = false;//粒子是否开启 可能是跑步的时候的粒子效果
function Awake () {
  movement.direction = transform.TransformDirection (Vector3.forward);
  controller = GetComponent (CharacterController);
  Spawn ();
 }function Spawn () {
  // reset the character's speed
  movement.verticalSpeed = 0.0;
  movement.speed = 0.0;
  
  // reset the character's position to the spawnPoint
  transform.position = spawnPoint.position;//玩家位置被送到重生点
 }function OnDeath () {
  Spawn ();
 } function UpdateSmoothedMovementDirection () {
 //通过坐标轴名称返回一个不使用平滑滤波器的虚拟值。往左为-1往右边卫+1没有输入的时候为0
  var h = Input.GetAxisRaw ("Horizontal");
  Debug.Log(h);
  if (!canControl)
   h = 0.0;
  
  movement.isMoving = Mathf.Abs (h) > 0.1;
   
  if (movement.isMoving)
   movement.direction = Vector3 (h, 0, 0);
  
  // Grounded controls
  if (controller.isGrounded) {//判断玩家是否在地面上
   // Smooth the speed based on the current target direction
   var curSmooth = movement.speedSmoothing * Time.deltaTime;//玩家的加速度
   
   // Choose target speed
   var targetSpeed = Mathf.Min (Mathf.Abs(h), 1.0);
  
   // Pick speed modifier
   if (Input.GetButton ("Fire2") && canControl)
    targetSpeed *= movement.runSpeed;
   else
    targetSpeed *= movement.walkSpeed;
   
   movement.speed = Mathf.Lerp (movement.speed, targetSpeed, curSmooth);
   
   movement.hangTime = 0.0;//一旦落到地上空中滞留时间就设置为0;
  }
  else {
   // In air controls
   movement.hangTime += Time.deltaTime;
   if (movement.isMoving)
    movement.inAirVelocity += Vector3 (Mathf.Sign(h), 0, 0) * Time.deltaTime * movement.inAirControlAcceleration;//空中移动速度
  }
 }function FixedUpdate () {
  // Make sure we are absolutely always in the 2D plane.
  transform.position.z = 0;//时刻保持z不变}
 function ApplyJumping () {
  // Prevent jumping too fast after each other
  if (jump.lastTime + jump.repeatTime > Time.time)
   return; if (controller.isGrounded) {
   // Jump
   // - Only when pressing the button down
   // - With a timeout so you can press the button slightly before landing  
   if (jump.enabled && Time.time < jump.lastButtonTime + jump.timeout) {
    movement.verticalSpeed = CalculateJumpVerticalSpeed (jump.height);
    movement.inAirVelocity = lastPlatformVelocity;
       SendMessage ("DidJump", SendMessageOptions.DontRequireReceiver);
   }
  }
 }function ApplyGravity () {
  // Apply gravity
  var jumpButton = Input.GetButton ("Jump");
  
  if (!canControl)
   jumpButton = false;
  
  // When we reach the apex of the jump we send out a message
  if (jump.jumping && !jump.reachedApex && movement.verticalSpeed <= 0.0) {//达到最高点
   jump.reachedApex = true;
   SendMessage ("DidJumpReachApex", SendMessageOptions.DontRequireReceiver);//不接受输入
  }
  
  // * When jumping up we don't apply gravity for some time when the user is holding the jump button
  //   This gives more control over jump height by pressing the button longer
  var extraPowerJump =  jump.jumping && movement.verticalSpeed > 0.0 && jumpButton && transform.position.y < jump.lastStartHeight + jump.extraHeight && !IsTouchingCeiling ();
  
  if (extraPowerJump == true)//额外的跳跃不需要重力,因为不符可重力学
  
   return;
  else if (controller.isGrounded)
   movement.verticalSpeed = -movement.gravity * Time.deltaTime;//当在地面的时候才垂直速度固定
  else
   movement.verticalSpeed -= movement.gravity * Time.deltaTime;//在空中的时候根据重力加速度 进行速度递减
   
  // Make sure we don't fall any faster than maxFallSpeed.  This gives our character a terminal velocity.
  //玩家往上的时候速度为正故  movement.verticalSpeed肯定大于-movement.maxFallSpeed,当玩家掉下的时候速度为负数,故可以和-movement.maxFallSpeed比较大小
  movement.verticalSpeed = Mathf.Max (movement.verticalSpeed, -movement.maxFallSpeed);
 } function CalculateJumpVerticalSpeed (targetJumpHeight : float) {//根据v = sqrt(2Gh)来计算出速度
  // From the jump height and gravity we deduce the upwards speed 
  // for the character to reach at the apex.
  return Mathf.Sqrt (2 * targetJumpHeight * movement.gravity);
 }function DidJump () {
  jump.jumping = true;
  jump.reachedApex = false;
  jump.lastTime = Time.time;
  jump.lastStartHeight = transform.position.y;
  jump.lastButtonTime = -10;
 } function UpdateEffects () {
  wereEmittersOn = areEmittersOn;
  areEmittersOn = jump.jumping && movement.verticalSpeed > 0.0;
  
  // By comparing the previous value of areEmittersOn to the new one, we will only update the particle emitters when needed
  if (wereEmittersOn != areEmittersOn) 
  {
   for (var emitter in GetComponentsInChildren (ParticleEmitter)) {
    emitter.emit = areEmittersOn;
   }
  }
 }function Update () {
  if (Input.GetButtonDown ("Jump") && canControl) {//按下跳跃键并且可以控制
    jump.lastButtonTime = Time.time;//记录当前按键的时间
  }
  
  UpdateSmoothedMovementDirection();
  ApplyGravity (); ApplyJumping ();
  
  if (activePlatform != null) {
   var newGlobalPlatformPoint = activePlatform.TransformPoint(activeLocalPlatformPoint);//自身坐标转化为世界坐标
   var moveDistance = (newGlobalPlatformPoint - activeGlobalPlatformPoint);
   transform.position = transform.position + moveDistance;
   lastPlatformVelocity = (newGlobalPlatformPoint - activeGlobalPlatformPoint) / Time.deltaTime;
  } else {
   lastPlatformVelocity = Vector3.zero; 
  }
  
  activePlatform = null;
  
  // Save lastPosition for velocity calculation.
  lastPosition = transform.position;
  
  var currentMovementOffset = movement.direction * movement.speed + Vector3 (0, movement.verticalSpeed, 0) + movement.inAirVelocity;
  
  // We always want the movement to be framerate independent.  Multiplying by Time.deltaTime does this.
  currentMovementOffset *= Time.deltaTime;
  
     // Move our character!
  movement.collisionFlags = controller.Move (currentMovementOffset);
  
  // Calculate the velocity based on the current and previous position.  
  // This means our velocity will only be the amount the character actually moved as a result of collisions.
  movement.velocity = (transform.position - lastPosition) / Time.deltaTime;
  
  if (activePlatform != null) {
   activeGlobalPlatformPoint = transform.position;
   activeLocalPlatformPoint = activePlatform.InverseTransformPoint (transform.position);
  }
  
  // Set rotation to the move direction 
  if (movement.direction.sqrMagnitude > 0.01)
   transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.LookRotation (movement.direction), Time.deltaTime * movement.rotationSmoothing);
  
  // We are in jump mode but just became grounded
  if (controller.isGrounded) {
   movement.inAirVelocity = Vector3.zero;
   if (jump.jumping) {
    jump.jumping = false;
    SendMessage ("DidLand", SendMessageOptions.DontRequireReceiver);   var jumpMoveDirection = movement.direction * movement.speed + movement.inAirVelocity;
    if (jumpMoveDirection.sqrMagnitude > 0.01)
     movement.direction = jumpMoveDirection.normalized;
   }
  }  // Update special effects like rocket pack particle effects
  UpdateEffects ();
 } function GetSpeed () {
  return movement.speed;
 }function GetVelocity () {
  return movement.velocity;
 } function IsMoving () {
  return movement.isMoving;
 }function IsJumping () {
  return jump.jumping;
 }function IsTouchingCeiling () {//头碰到了顶部
  return (movement.collisionFlags & CollisionFlags.CollidedAbove) != 0;
 }function GetDirection () {
  return movement.direction;
 }function GetHangTime() {
  return movement.hangTime;
 }function Reset () {
  gameObject.tag = "Player";
 }function SetControllable (controllable : boolean) {
  canControl = controllable;
 }// Require a character controller to be attached to the same game object
 @script RequireComponent (CharacterController)
 //AddComponentMenu属性允许你在"Component"菜单中放置一个无论在哪的脚本,而不是仅仅在"Component->Scripts"菜单中。
 //@script AddComponentMenu ("2D Platformer/Platformer Controller")