using UnityEngine;

 /// <summary>
 /// 摄像机跟随玩家
 /// </summary>
 public class CameraFollow : MonoBehaviour
 {
     /// <summary>
     /// 目标
     /// </summary>
     public Transform target;
     /// <summary>
     /// 和目标之间的偏移
     /// </summary>
     );
     /// <summary>
     /// 是否锁定旋转
     /// </summary>
     public bool lockRotation;
     /// <summary>
     /// 跟随速度
     /// </summary>
     ;
     /// <summary>
     /// 围绕目标旋转的速度
     /// </summary>
     ;
     /// <summary>
     /// 是否可以由鼠标控制旋转(只有在相机没有被固定的情况下)
     /// </summary>
     public bool mouseFreelook;
     /// <summary>
     /// 旋转阻尼
     /// </summary>
     ;
     /// <summary>
     /// 摄像机在水中时的过滤物体
     /// </summary>
     public GameObject waterFilter;
     /// <summary>
     ///
     /// </summary>
     public string[] avoidClippingTags;                                      

     /// <summary>
     /// Camera Target
     /// </summary>
     private Transform followTarget;
     /// <summary>
     /// 暂未用到
     /// </summary>
     private bool camColliding;

     //setup objects
     void Awake()
     {
         //创建跟随物体(Camera Target)
         followTarget = new GameObject().transform;
         followTarget.name = "Camera Target";
         if(waterFilter)
             waterFilter.GetComponent<Renderer>().enabled = false;
         if(!target)
             Debug.LogError("'CameraFollow script' has no target assigned to it", transform);

         //如果用鼠标控制旋转,旋转阻尼为0
         if(mouseFreelook)
             rotateDamping = 0f;
     }

     void Update()
     {
         //没有目标不处理
         if (!target)
             return;
         //平滑跟随
         SmoothFollow ();
         //平滑朝向玩家
         )
             SmoothLookAt();
         //直接朝向玩家
         else
             transform.LookAt(target.position);
     }

     void OnTriggerEnter(Collider other)
     {
         //打开水遮罩
         if (other.tag == "Water" && waterFilter)
             waterFilter.GetComponent<Renderer>().enabled = true;
     }

     void OnTriggerExit(Collider other)
     {
         //关闭水遮罩
         if (other.tag == "Water" && waterFilter)
             waterFilter.GetComponent<Renderer>().enabled = false;
     }

     /// <summary>
     /// 平滑朝向目标
     /// </summary>
     void SmoothLookAt()
     {
         Quaternion rotation = Quaternion.LookRotation (target.position - transform.position);
         transform.rotation = Quaternion.Slerp (transform.rotation, rotation, rotateDamping * Time.deltaTime);
     }

     /// <summary>
     /// 平滑跟随目标
     /// </summary>
     void SmoothFollow()
     {
         followTarget.position = target.position;
         followTarget.Translate(targetOffset, Space.Self);
         if (lockRotation)
             followTarget.rotation = target.rotation;

         //鼠标控制围绕目标旋转
         if(mouseFreelook)
         {
             float axisX = Input.GetAxis ("Mouse X") * inputRotationSpeed * Time.deltaTime;
             followTarget.RotateAround (target.position,Vector3.up, axisX);
             float axisY = Input.GetAxis ("Mouse Y") * inputRotationSpeed * Time.deltaTime;
             followTarget.RotateAround (target.position, transform.right, -axisY);
         }
         //键盘控制围绕目标旋转
         else
         {
             float axis = Input.GetAxis ("CamHorizontal") * inputRotationSpeed * Time.deltaTime;
             followTarget.RotateAround (target.position, Vector3.up, axis);
         }

         //计算相机的下一帧位置
         Vector3 nextFramePosition = Vector3.Lerp(transform.position, followTarget.position, followSpeed * Time.deltaTime);
         Vector3 direction = nextFramePosition - target.position;
         //射线检测这个位置
         RaycastHit hit;
         if(Physics.Raycast (target.position, direction, out hit, direction.magnitude + 0.3f))
         {
             transform.position = nextFramePosition;
             foreach(string tag in avoidClippingTags)
                 //如果这个位置有物体,修改相机位置
                 if(hit.transform.tag == tag)
                     transform.position = hit.point - direction.normalized * 0.3f;
         }
         else
         {
             //直接修改相机位置
             transform.position = nextFramePosition;
         }
     }
 }

CameraFollow

 using UnityEngine;

 /// <summary>
 /// 角色移动
 /// </summary>
 [RequireComponent(typeof(Rigidbody))]
 public class CharacterMotor:MonoBehaviour {
     /// <summary>
     /// 是否冻结z轴的移动
     /// </summary>
     public bool sidescroller;
     /// <summary>
     /// 当前速度
     /// </summary>
     [HideInInspector]
     public Vector3 currentSpeed;
     /// <summary>
     /// 到目标的距离
     /// </summary>
     [HideInInspector]
     public float DistanceToTarget;
     /// <summary>
     /// 刚体
     /// </summary>
     private Rigidbody rigid;

     void Awake() {
         //设置rigidbody
         rigid = GetComponent<Rigidbody>();
         rigid.interpolation = RigidbodyInterpolation.Interpolate;
         if(sidescroller)
             rigid.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ;
         else
             rigid.constraints = RigidbodyConstraints.FreezeRotation;
         //添加光滑的物理材质
         if(GetComponent<Collider>().material.name == "Default (Instance)") {
             PhysicMaterial pMat = new PhysicMaterial();
             pMat.name = "Frictionless";
             pMat.frictionCombine = PhysicMaterialCombine.Multiply;
             pMat.bounceCombine = PhysicMaterialCombine.Multiply;
             pMat.dynamicFriction = 0f;
             pMat.staticFriction = 0f;
             GetComponent<Collider>().material = pMat;
             Debug.LogWarning("No physics material found for CharacterMotor, a frictionless one has been created and assigned",transform);
         }
     }

     /// <summary>
     /// 移动刚体到指定位置
     /// </summary>
     public bool MoveTo(Vector3 destination,float acceleration,float stopDistance,bool ignoreY) {
         Vector3 relativePos = (destination - transform.position);
         //忽略y轴?
         if(ignoreY)
             relativePos.y = ;

         DistanceToTarget = relativePos.magnitude;
         if(DistanceToTarget <= stopDistance)
             return true;
         else
             rigid.AddForce(relativePos.normalized * acceleration * Time.deltaTime,ForceMode.VelocityChange);
         return false;
     }

     /// <summary>
     /// 旋转刚体朝向当前速度
     /// </summary>
     public void RotateToVelocity(float turnSpeed,bool ignoreY) {
         Vector3 dir;
         if(ignoreY)
             dir = new Vector3(rigid.velocity.x,0f,rigid.velocity.z);
         else
             dir = rigid.velocity;

         if(dir.magnitude > 0.1) {
             Quaternion dirQ = Quaternion.LookRotation(dir);
             Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,dir.magnitude * turnSpeed * Time.deltaTime);
             rigid.MoveRotation(slerp);
         }
     }

     /// <summary>
     /// 旋转刚体朝向指定方向
     /// </summary>
     public void RotateToDirection(Vector3 lookDir,float turnSpeed,bool ignoreY) {
         Vector3 characterPos = transform.position;
         //忽略y轴?
         if(ignoreY) {
             characterPos.y = ;
             lookDir.y = ;
         }

         Vector3 newDir = lookDir - characterPos;
         Quaternion dirQ = Quaternion.LookRotation(newDir);
         Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,turnSpeed * Time.deltaTime);
         rigid.MoveRotation(slerp);
     }

     /// <summary>
     /// 管理速度
     /// </summary>
     public void ManageSpeed(float deceleration,float maxSpeed,bool ignoreY) {
         currentSpeed = rigid.velocity;
         //忽略y轴
         if(ignoreY)
             currentSpeed.y = ;

         ) {
             rigid.AddForce((currentSpeed * -) * deceleration * Time.deltaTime,ForceMode.VelocityChange);
             if(rigid.velocity.magnitude > maxSpeed)
                 rigid.AddForce((currentSpeed * -) * deceleration * Time.deltaTime,ForceMode.VelocityChange);
         }
     }
 }

CharacterMotor

 using UnityEngine;

 /// <summary>
 /// 检查点
 /// </summary>
 [RequireComponent(typeof(CapsuleCollider))]
 [RequireComponent(typeof(AudioSource))]
 public class Checkpoint : MonoBehaviour
 {
     /// <summary>
     /// 激活颜色
     /// </summary>
     public Color activeColor = Color.green;
     /// <summary>
     /// 激活时的不透明度
     /// </summary>
     public float activeColorOpacity = 0.4f;          

     /// <summary>
     /// 生命
     /// </summary>
     private Health health;
     /// <summary>
     /// 默认颜色
     /// </summary>
     private Color defColor;
     /// <summary>
     /// 检查点列表
     /// </summary>
     private GameObject[] checkpoints;
     /// <summary>
     /// 渲染器
     /// </summary>
     private Renderer render;
     /// <summary>
     /// AudioSource
     /// </summary>
     private AudioSource aSource;

     void Awake()
     {
         render = GetComponent<Renderer>();
         aSource = GetComponent<AudioSource>();
         //标签不是Respawn,自动修改标签
         if(tag != "Respawn")
         {
             tag = "Respawn";
             Debug.LogWarning ("'Checkpoint' script attached to object without the 'Respawn' tag, tag has been assigned automatically", transform);
         }
         GetComponent<Collider>().isTrigger = true;
         //设置默认颜色和不透明度
         if(render)
             defColor = render.material.color;
         activeColor.a = activeColorOpacity;
     }

     void Start()
     {
         checkpoints = GameObject.FindGameObjectsWithTag("Respawn");
         health = GameObject.FindGameObjectWithTag("Player").GetComponent<Health>();
         if(!health)
             Debug.LogError("For Checkpoint to work, the Player needs 'Health' script attached", transform);
     }

     void OnTriggerEnter(Collider other)
     {
         //如果碰到玩家
         if(other.transform.tag == "Player" && health)
         {
             health.respawnPos = transform.position;

             if(render.material.color != activeColor)
             {
                 foreach (GameObject checkpoint in checkpoints)
                     checkpoint.GetComponent<Renderer>().material.color = defColor;
                 aSource.Play();
                 render.material.color = activeColor;
             }
         }
     }
 }

Checkpoint

 using UnityEngine;

 /// <summary>
 /// 金币
 /// </summary>
 [RequireComponent(typeof(SphereCollider))]
 public class Coin : MonoBehaviour
 {
     /// <summary>
     /// 被收集时的声音
     /// </summary>
     public AudioClip collectSound;
     /// <summary>
     /// 旋转
     /// </summary>
     , , );
     /// <summary>
     /// 玩家靠近时,增加的旋转
     /// </summary>
     , , );
     /// <summary>
     /// 金币向玩家移动的速度
     /// </summary>
     public float startSpeed = 3f;
     /// <summary>
     /// 金币向玩家移动的加速度
     /// </summary>
     public float speedGain = 0.2f;                             

     /// <summary>
     /// 是否被搜集
     /// </summary>
     private bool collected;
     /// <summary>
     /// 玩家
     /// </summary>
     private Transform player;
     /// <summary>
     /// 子物体的触发器
     /// </summary>
     private TriggerParent triggerParent;
     /// <summary>
     /// GUI
     /// </summary>
     private GUIManager gui;

     void Awake()
     {
         gui = FindObjectOfType(typeof(GUIManager)) as GUIManager ;
         if(tag != "Coin")
         {
             tag = "Coin";
             Debug.LogWarning ("'Coin' script attached to object not tagged 'Coin', tag added automatically", transform);
         }
         GetComponent<Collider>().isTrigger = true;
         triggerParent = GetComponentInChildren<TriggerParent>();
         //添加bounds子物体
         if(!triggerParent)
         {
             GameObject bounds = new GameObject();
             bounds.name = "Bounds";
             bounds.AddComponent<SphereCollider>();
             bounds.GetComponent<SphereCollider>().radius = 7f;
             bounds.GetComponent<SphereCollider>().isTrigger = true;
             bounds.transform.parent = transform;
             bounds.transform.position = transform.position;
             bounds.AddComponent<TriggerParent>();
             triggerParent = GetComponentInChildren<TriggerParent>();
             triggerParent.tagsToCheck = ];
             triggerParent.tagsToCheck[] = "Player";
             Debug.LogWarning ("No pickup radius 'bounds' trigger attached to coin: " + transform.name + ", one has been added automatically", bounds);
         }
     }

     void Start()
     {
         player = GameObject.FindGameObjectWithTag("Player").transform;
     }

     void Update()
     {

         transform.Rotate (rotation * Time.deltaTime, Space.World);

         if(triggerParent.collided)
             collected = true;

         //增加金币的旋转速度和移动速度,将金币移向玩家
         if (collected)
         {
             startSpeed += speedGain;
             rotation += rotationGain;
             transform.position = Vector3.Lerp (transform.position, player.position, startSpeed * Time.deltaTime);
         }
     }

     void OnTriggerEnter(Collider other)
     {
         if (other.tag == "Player")
             CoinGet();
     }

     /// <summary>
     /// 获取金币
     /// </summary>
     void CoinGet()
     {
         if(collectSound)
             AudioSource.PlayClipAtPoint(collectSound, transform.position);
         if (gui)
             gui.coinsCollected ++;
         Destroy(gameObject);
     }
 }

Coin

 using UnityEngine;

 /// <summary>
 /// 处理伤害
 /// </summary>
 public class DealDamage : MonoBehaviour
 {
     /// <summary>
     /// 受害人的生命
     /// </summary>
     private Health health;

     /// <summary>
     /// 攻击
     /// </summary>
     public void Attack(GameObject victim, int dmg, float pushHeight, float pushForce)
     {
         health = victim.GetComponent<Health>();        

         //推物体
         Vector3 pushDir = (victim.transform.position - transform.position);
         pushDir.y = 0f;
         pushDir.y = pushHeight * 0.1f;
         if (victim.GetComponent<Rigidbody>() && !victim.GetComponent<Rigidbody>().isKinematic)
         {
             victim.GetComponent<Rigidbody>().velocity = , , );
             victim.GetComponent<Rigidbody>().AddForce (pushDir.normalized * pushForce, ForceMode.VelocityChange);
             victim.GetComponent<Rigidbody>().AddForce (Vector3.up * pushHeight, ForceMode.VelocityChange);
         }
         //应用伤害
         if(health && !health.flashing)
             health.currentHealth -= dmg;
     }
 }

DealDamage

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 摧毁物体
 /// </summary>
 public class DestroyObject : MonoBehaviour
 {
     /// <summary>
     /// 摧毁声音
     /// </summary>
     public AudioClip destroySound;
     /// <summary>
     /// 延迟
     /// </summary>
     public float delay;
     /// <summary>
     /// 是否分离子物体并且不摧毁子物体
     /// </summary>
     public bool destroyChildren;
     /// <summary>
     /// 从父物体中心推开子物体的数量
     /// </summary>
     public float pushChildAmount;    

     void Start()
     {
         //获取子物体列表
         Transform[] children = new Transform[transform.childCount];
         ; i < transform.childCount; i++)
             children[i] = transform.GetChild(i);

         //分离子物体
         if (!destroyChildren)
             transform.DetachChildren();

         //给子物体添加一个推力和旋转
         foreach (Transform child in children)
         {
             Rigidbody rigid = child.GetComponent<Rigidbody>();
             )
             {
                 Vector3 pushDir = child.position - transform.position;
                 rigid.AddForce(pushDir * pushChildAmount, ForceMode.Force);
                 rigid.AddTorque(Random.insideUnitSphere, ForceMode.Force);
             }
         }

         //删除父物体
         if(destroySound)
             AudioSource.PlayClipAtPoint(destroySound, transform.position);
         Destroy (gameObject, delay);
     }
 }

DestroyObject

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 敌人AI
 /// </summary>
 [RequireComponent(typeof(CharacterMotor))]
 [RequireComponent(typeof(DealDamage))]
 public class EnemyAI : MonoBehaviour
 {
     /// <summary>
     /// 移动加速度
     /// </summary>
     public float acceleration = 35f;
     /// <summary>
     /// 移动减速度
     /// </summary>
     public float deceleration = 8f;
     /// <summary>
     /// 旋转速度
     /// </summary>
     public float rotateSpeed = 0.7f;
     /// <summary>
     /// 速度极限
     /// </summary>
     public float speedLimit = 10f;
     /// <summary>
     /// 玩家跳到敌人头上时应用到玩家身上的力
     /// </summary>
     , , );
     /// <summary>
     /// 玩家跳到敌人头上时的声音
     /// </summary>
     public AudioClip bounceSound;
     /// <summary>
     /// 玩家碰到敌人时受到的推力
     /// </summary>
     public float pushForce = 10f;
     /// <summary>
     /// 玩家碰到敌人时玩家的高度
     /// </summary>
     public float pushHeight = 7f;
     /// <summary>
     /// 敌人对玩家的伤害
     /// </summary>
     ;
     /// <summary>
     /// 是否追逐视野内的目标
     /// </summary>
     public bool chase = true;
     /// <summary>
     /// 追逐时是否忽略y轴
     /// </summary>
     public bool ignoreY = true;
     /// <summary>
     /// 追逐停止的距离
     /// </summary>
     public float chaseStopDistance = 0.7f;
     /// <summary>
     /// 视野范围
     /// </summary>
     public GameObject sightBounds;
     /// <summary>
     /// 攻击范围
     /// </summary>
     public GameObject attackBounds;
     /// <summary>
     /// Animator
     /// </summary>
     public Animator animatorController;
     /// <summary>
     /// 移动到路标点
     /// </summary>
     public MoveToPoints moveToPointsScript;                                          

     /// <summary>
     /// 视野触发器
     /// </summary>
     private TriggerParent sightTrigger;
     /// <summary>
     /// 攻击触发器
     /// </summary>
     private TriggerParent attackTrigger;
     /// <summary>
     ///  玩家移动
     /// </summary>
     private PlayerMove playerMove;
     /// <summary>
     /// 角色移动
     /// </summary>
     private CharacterMotor characterMotor;
     /// <summary>
     /// 处理伤害
     /// </summary>
     private DealDamage dealDamage;

     void Awake()
     {
         characterMotor = GetComponent<CharacterMotor>();
         dealDamage = GetComponent<DealDamage>();
         if(tag != "Enemy")
         {
             tag = "Enemy";
             Debug.LogWarning("'EnemyAI' script attached to object without 'Enemy' tag, it has been assign automatically", transform);
         }

         if(sightBounds)
         {
             sightTrigger = sightBounds.GetComponent<TriggerParent>();
             if(!sightTrigger)
                 Debug.LogError("'TriggerParent' script needs attaching to enemy 'SightBounds'", sightBounds);
         }
         if(!sightBounds)
             Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'SightBounds' or enemy will not be able to see", transform);

         if(attackBounds)
         {
             attackTrigger = attackBounds.GetComponent<TriggerParent>();
             if(!attackTrigger)
                 Debug.LogError("'TriggerParent' script needs attaching to enemy 'attackBounds'", attackBounds);
         }
         else
             Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'AttackBounds' or enemy will not be able to attack", transform);
     }

     void Update()
     {
         //追逐
         if (sightTrigger && sightTrigger.colliding && chase && sightTrigger.hitObject != null && sightTrigger.hitObject.activeInHierarchy)
         {
             characterMotor.MoveTo (sightTrigger.hitObject.transform.position, acceleration, chaseStopDistance, ignoreY);

             if(animatorController)
                 animatorController.SetBool("Moving", true);

             if(moveToPointsScript)
                 moveToPointsScript.enabled = false;
         }
         else
         {    

             if(animatorController)
                 animatorController.SetBool("Moving", false);

             if(moveToPointsScript)
                 moveToPointsScript.enabled = true;
         }

         //攻击
         if (attackTrigger && attackTrigger.collided)
         {
             dealDamage.Attack(attackTrigger.hitObject, attackDmg, pushHeight, pushForce);

             if(animatorController)
                 animatorController.SetBool("Attacking", true);
         }
         else if(animatorController)
             animatorController.SetBool("Attacking", false);
     }

     void FixedUpdate()
     {
         characterMotor.ManageSpeed(deceleration, speedLimit, ignoreY);
         characterMotor.RotateToVelocity (rotateSpeed, ignoreY);
     }

     /// <summary>
     /// 弹开玩家
     /// </summary>
     public void BouncedOn()
     {
         if(!playerMove)
             playerMove = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerMove>();
         if (bounceSound)
             AudioSource.PlayClipAtPoint(bounceSound, transform.position);
         if(playerMove)
         {
             Vector3 bounceMultiplier = new Vector3(0f, 1.5f, 0f) * playerMove.onEnemyBounce;
             playerMove.Jump (bounceForce + bounceMultiplier);
         }
         else
             Debug.LogWarning("'Player' tagged object landed on enemy, but without playerMove script attached, is unable to bounce");
     }
 }

EnemyAI

 using UnityEngine;

 /// <summary>
 /// 关卡目标
 /// </summary>
 [RequireComponent(typeof(CapsuleCollider))]
 public class Goal : MonoBehaviour
 {
     /// <summary>
     /// 举起玩家的力
     /// </summary>
     public float lift;
     /// <summary>
     /// 加载下一个关卡的等待时间
     /// </summary>
     public float loadDelay;
     /// <summary>
     /// 下一个场景的索引
     /// </summary>
     public int nextLevelIndex;                                                                

     /// <summary>
     /// 计时器
     /// </summary>
     private float counter;

     void Awake()
     {
         GetComponent<Collider>().isTrigger = true;
     }

     void OnTriggerStay(Collider other)
     {
         Rigidbody rigid = other.GetComponent<Rigidbody>();
         if(rigid)
             rigid.AddForce(Vector3.up * lift, ForceMode.Force);

         if (other.tag == "Player")
         {
             counter += Time.deltaTime;
             if(counter > loadDelay)
                 Application.LoadLevel (nextLevelIndex);
         }
     }

     void OnTriggerExit(Collider other)
     {
         if (other.tag == "Player")
             counter = 0f;
     }
 }

Goal

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// GUI
 /// </summary>
 public class GUIManager : MonoBehaviour
 {
     /// <summary>
     /// GUISkin
     /// </summary>
     public GUISkin guiSkin;
     /// <summary>
     /// 已收集的金币
     /// </summary>
     [HideInInspector]
     public int coinsCollected;
     /// <summary>
     /// 场景中的金币数量
     /// </summary>
     private int coinsInLevel;
     /// <summary>
     /// 生命
     /// </summary>
     private Health health;

     void Start()
     {
         coinsInLevel = GameObject.FindGameObjectsWithTag("Coin").Length;
         health = GameObject.FindGameObjectWithTag("Player").GetComponent<Health>();
     }

     void OnGUI()
     {
         GUI.skin = guiSkin;
         GUILayout.Space(5f);

         if(health)
             GUILayout.Label ("Health: " + health.currentHealth);
         )
             GUILayout.Label ("Cubes: " + coinsCollected + " / " + coinsInLevel);
     }
 }

GUIManager

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 障碍
 /// </summary>
 [RequireComponent(typeof(DealDamage))]
 [RequireComponent(typeof(AudioSource))]
 public class Hazard : MonoBehaviour
 {
     /// <summary>
     /// 推开受害者的力
     /// </summary>
     public float pushForce = 25f;
     /// <summary>
     /// 向上推的力
     /// </summary>
     public float pushHeight = 6f;
     /// <summary>
     /// 照成的伤害
     /// </summary>
     ;
     /// <summary>
     /// 是否是触发
     /// </summary>
     public bool triggerEnter;
     /// <summary>
     /// 是否是碰撞
     /// </summary>
     public bool collisionEnter = true;
     /// <summary>
     /// 影响的单位的标签
     /// </summary>
     public string[] effectedTags = {"Player"};
     /// <summary>
     /// 碰撞声音
     /// </summary>
     public AudioClip hitSound;                                      

     /// <summary>
     ///  处理伤害
     /// </summary>
     private DealDamage dealDamage;
     /// <summary>
     /// AudioSource
     /// </summary>
     private AudioSource aSource;

     //setup
     void Awake()
     {
         aSource = GetComponent<AudioSource>();
         aSource.playOnAwake = false;
         dealDamage = GetComponent<DealDamage>();
     }

     void OnCollisionEnter(Collision col)
     {
         //不是碰撞
         if(!collisionEnter)
             return;
         //遍历检查标签
         foreach(string tag in effectedTags)
             //标签相等
             if(col.transform.tag == tag)
             {
                 //处理伤害
                 dealDamage.Attack (col.gameObject, damage, pushHeight, pushForce);
                 //播放声音
                 if (hitSound)
                 {
                     aSource.clip = hitSound;
                     aSource.Play();
                 }
             }
     }

     void OnTriggerEnter(Collider other)
     {
         //不是触发器
         if(!triggerEnter)
             return;
         //遍历标签
         foreach(string tag in effectedTags)
             //标签相等
             if(other.transform.tag == tag)
                 //处理伤害
                 dealDamage.Attack (other.gameObject, damage, pushHeight, pushForce);
     }
 }

Hazard

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 生命
 /// </summary>
 [RequireComponent(typeof(AudioSource))]
 public class Health : MonoBehaviour
 {
     /// <summary>
     /// 撞击声音
     /// </summary>
     public AudioClip impactSound;
     /// <summary>
     /// 受到伤害时的声音
     /// </summary>
     public AudioClip hurtSound;
     /// <summary>
     /// 死亡声音
     /// </summary>
     public AudioClip deadSound;
     /// <summary>
     /// 当前生命
     /// </summary>
     ;
     /// <summary>
     /// 是否能受到撞击伤害
     /// </summary>
     public bool takeImpactDmg;
     /// <summary>
     /// 是否只能受到刚体伤害
     /// </summary>
     public bool onlyRigidbodyImpact;
     /// <summary>
     /// 是否可以重生
     /// </summary>
     public bool respawn;
     /// <summary>
     /// 不会受到撞击伤害的标签
     /// </summary>
     public string[] impactFilterTag;
     /// <summary>
     /// 受到伤害时的闪烁延迟
     /// </summary>
     public float hitFlashDelay = 0.1f;
     /// <summary>
     /// 闪烁持续时间
     /// </summary>
     public float flashDuration = 0.9f;
     /// <summary>
     /// 受到伤害时的闪烁颜色
     /// </summary>
     public Color hitFlashColor = Color.red;
     /// <summary>
     /// 闪烁的物体
     /// </summary>
     public Transform flashObject;
     /// <summary>
     ///
     /// </summary>
     public GameObject[] spawnOnDeath;                

     /// <summary>
     /// 是否死亡,是否闪烁
     /// </summary>
     [HideInInspector]
     public bool dead, flashing;
     /// <summary>
     /// 重生位置
     /// </summary>
     [HideInInspector]
     public Vector3 respawnPos;

     /// <summary>
     /// 原始颜色
     /// </summary>
     private Color originalColor;
     /// <summary>
     ///
     /// </summary>
     private int defHealth, h, hitForce;
     private bool hitColor = false;
     /// <summary>
     /// 下一个闪烁,停止闪烁时间
     /// </summary>
     private float nextFlash, stopFlashTime;
     /// <summary>
     /// 扔物体
     /// </summary>
     private Throwing throwing;
     /// <summary>
     /// 闪烁渲染器
     /// </summary>
     private Renderer flashRender;
     /// <summary>
     /// AudioSource
     /// </summary>
     private AudioSource aSource;

     void Awake()
     {
         aSource = GetComponent<AudioSource>();
         )
             Debug.LogWarning(transform.name + " has 'currentHealth' set to 0 or less in 'Health' script: it has died upon scene start");
         aSource.playOnAwake = false;
         if(flashObject == null)
             flashObject = transform;
         flashRender = flashObject.GetComponent<Renderer>();
         originalColor = flashRender.material.color;
         defHealth = currentHealth;
         respawnPos = transform.position;
     }

     void Update()
     {
         //受到伤害,闪烁
         if (currentHealth < h)
         {
             flashing = true;
             stopFlashTime = Time.time + flashDuration;
             if (hurtSound)
                 AudioSource.PlayClipAtPoint(hurtSound, transform.position);
         }
         h = currentHealth;

         if (flashing)
         {
             Flash ();
             if (Time.time > stopFlashTime)
             {
                 flashRender.material.color = originalColor;
                 flashing = false;
             }
         }

         dead = (currentHealth <= ) ? true : false;
         if (dead)
             Death();
     }

     /// <summary>
     /// 闪烁
     /// </summary>
     void Flash()
     {
         flashRender.material.color = (hitColor) ? hitFlashColor : originalColor;
         if(Time.time > nextFlash)
         {
             hitColor = !hitColor;
             nextFlash = Time.time + hitFlashDelay;
         }
     }

     /// <summary>
     /// 死亡
     /// </summary>
     void Death()
     {

         if(tag == "Player")
             throwing = GetComponent<Throwing>();
         if(throwing && throwing.heldObj && throwing.heldObj.tag == "Pickup")
             throwing.ThrowPickup();

         if (deadSound)
             AudioSource.PlayClipAtPoint(deadSound, transform.position);
         flashing = false;
         flashObject.GetComponent<Renderer>().material.color = originalColor;
         if(respawn)
         {
             Rigidbody rigid = GetComponent<Rigidbody>();
             if(rigid)
                 rigid.velocity *= ;
             transform.position = respawnPos;
             dead = false;
             currentHealth = defHealth;
         }
         else
             Destroy (gameObject);

         )
             foreach(GameObject obj in spawnOnDeath)
                 Instantiate(obj, transform.position, Quaternion.Euler(Vector3.zero));
     }

     void OnCollisionEnter(Collision col)
     {
         //播放撞击声音
         if(!aSource.isPlaying && impactSound)
         {
             aSource.clip = impactSound;
             aSource.volume = col.relativeVelocity.magnitude/;
             aSource.Play();
         }

         //不会受到撞击伤害,返回
         if (!takeImpactDmg)
             return;
         //找到标签,返回
         foreach(string tag in impactFilterTag)
             if(col.transform.tag == tag)
                 return;
         //只能受到刚体撞击且没有刚体,返回
         if(onlyRigidbodyImpact && !col.rigidbody)
             return;

         //计算受到的伤害
         if(col.rigidbody)
             hitForce = ( * col.rigidbody.mass);
         else
             hitForce = (;
         currentHealth -= hitForce;
         //print (transform.name + " took: " + hitForce + " dmg in collision with " + col.transform.name);
     }
 }

Health

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;

 /// <summary>
 /// 移动到指定的点
 /// </summary>
 [RequireComponent(typeof(Rigidbody))]
 public class MoveToPoints:MonoBehaviour {
     /// <summary>
     /// 移动速度
     /// </summary>
     public float speed;
     /// <summary>
     /// 延迟
     /// </summary>
     public float delay;
     /// <summary>
     /// 移动类型
     /// </summary>
     public type movementType;                               

     /// <summary>
     /// 移动类型
     /// </summary>
     public enum type {
         /// <summary>
         /// 在最后一个路标停止
         /// </summary>
         PlayOnce,
         /// <summary>
         /// 转圈
         /// </summary>
         Loop,
         /// <summary>
         /// 来回
         /// </summary>
         PingPong
     }
     /// <summary>
     /// 当前路标索引
     /// </summary>
     private int currentWp;
     /// <summary>
     /// 到达时间
     /// </summary>
     private float arrivalTime;
     /// <summary>
     /// 是否向前,是否到达
     /// </summary>
     private bool forward = true, arrived = false;
     /// <summary>
     /// 路标列表
     /// </summary>
     private List<Transform> waypoints = new List<Transform>();
     /// <summary>
     /// 角色移动
     /// </summary>
     private CharacterMotor characterMotor;
     /// <summary>
     /// 敌人AI
     /// </summary>
     private EnemyAI enemyAI;
     /// <summary>
     /// 刚体
     /// </summary>
     private Rigidbody rigid;

     void Awake() {
         //标签不是Enemy
         if(transform.tag != "Enemy") {
             //没有刚体,添加刚体
             if(!GetComponent<Rigidbody>())
                 gameObject.AddComponent<Rigidbody>();
             //动力学
             GetComponent<Rigidbody>().isKinematic = true;
             //不使用重力
             GetComponent<Rigidbody>().useGravity = false;
             //修改插值类型
             GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
         } else {
             //角色移动
             characterMotor = GetComponent<CharacterMotor>();
             //获取敌人AI
             enemyAI = GetComponent<EnemyAI>();
         }
         //获取刚体
         rigid = GetComponent<Rigidbody>();
         //遍历子物体
         foreach(Transform child in transform)
             //添加路标
             if(child.tag == "Waypoint")
                 waypoints.Add(child);
         //分离路标
         foreach(Transform waypoint in waypoints)
             waypoint.parent = null;

         )
             Debug.LogError("No waypoints found for 'MoveToPoints' script. To add waypoints: add child gameObjects with the tag 'Waypoint'",transform);
     }

     void Update() {
         //路标数量大于0
         ) {
             //没有到达
             if(!arrived) {
                 //与下一个路标的距离小于0.3
                 if(Vector3.Distance(transform.position,waypoints[currentWp].position) < 0.3f) {
                     //设置到达时间
                     arrivalTime = Time.time;
                     //修改到达标志位
                     arrived = true;
                 }
             //到达
             } else {
                 //当前时间大于到达时间加延迟
                 if(Time.time > arrivalTime + delay) {
                     //获取下一个路标
                     GetNextWP();
                     //修改到达标志位
                     arrived = false;
                 }
             }
         }
         //标签是Enemy,路标数量大于0
         ) {
             //没有到达位置
             if(!arrived) {
                 //玩家移动到指定路标
                 characterMotor.MoveTo(waypoints[currentWp].position,enemyAI.acceleration,0.1f,enemyAI.ignoreY);
                 //播放动画
                 if(enemyAI.animatorController)
                     enemyAI.animatorController.SetBool("Moving",true);
             //到达位置
             } else
                 //播放动画
                 if(enemyAI.animatorController)
                     enemyAI.animatorController.SetBool("Moving",false);
         }
     }

     void FixedUpdate() {
         //标签为Enemy
         if(transform.tag != "Enemy") {
             //没有到达且路标数量大于0
             ) {
                 //计算和路标的距离
                 Vector3 direction = waypoints[currentWp].position - transform.position;
                 //刚体移动
                 rigid.MovePosition(transform.position + (direction.normalized * speed * Time.fixedDeltaTime));
             }
         }
     }

     /// <summary>
     /// 获取下一个路标
     /// </summary>
     private void GetNextWP() {
         //一次
         if(movementType == type.PlayOnce) {
             currentWp++;
             if(currentWp == waypoints.Count)
                 enabled = false;
         }
         //循环
         if(movementType == type.Loop)
             currentWp = (currentWp == waypoints.Count - ) ?  : currentWp += ;
         //来回
         if(movementType == type.PingPong) {
             )
                 forward = false;
             )
                 forward = true;
             currentWp = (forward) ? currentWp +=  : currentWp -= ;
         }
     }

     void OnDrawGizmos() {
         Gizmos.color = Color.cyan;
         foreach(Transform child in transform) {
             if(child.tag == "Waypoint")
                 Gizmos.DrawSphere(child.position,.7f);
         }
     }
 }

MoveToPoints

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 玩家移动
 /// </summary>
 [RequireComponent(typeof(CharacterMotor))]
 [RequireComponent(typeof(DealDamage))]
 [RequireComponent(typeof(AudioSource))]
 [RequireComponent(typeof(Rigidbody))]
 public class PlayerMove:MonoBehaviour {
     /// <summary>
     /// 是否是卷轴模式
     /// </summary>
     public bool sidescroller;
     /// <summary>
     /// 主相机,FloorChecks游戏物体Transform
     /// </summary>
     public Transform mainCam, floorChecks;
     /// <summary>
     /// Animator
     /// </summary>
     public Animator animator;
     /// <summary>
     /// 跳跃声音
     /// </summary>
     public AudioClip jumpSound;
     /// <summary>
     /// 着陆声音
     /// </summary>
     public AudioClip landSound;

     /// <summary>
     /// 加速度
     /// </summary>
     public float accel = 70f;
     /// <summary>
     /// 空中加速度
     /// </summary>
     public float airAccel = 18f;
     /// <summary>
     /// 减速度
     /// </summary>
     public float decel = 7.6f;
     /// <summary>
     /// 空中减速度
     /// </summary>
     public float airDecel = 1.1f;
     /// <summary>
     /// 旋转速度,空中旋转速度
     /// </summary>
     [Range(0f,5f)]
     public float rotateSpeed = 0.7f, airRotateSpeed = 0.4f;
     /// <summary>
     /// 最高移动速度
     /// </summary>
     ;
     /// <summary>
     /// 最大坡度,最大滑坡速度
     /// </summary>
     , slideAmount = ;
     /// <summary>
     /// 移动平台的摩擦力
     /// </summary>
     public float movingPlatformFriction = 7.7f;

     /// <summary>
     /// 常规跳跃力
     /// </summary>
     ,,);
     /// <summary>
     /// 2连跳力
     /// </summary>
     ,,);
     /// <summary>
     /// 3连跳力
     /// </summary>
     ,,);
     /// <summary>
     /// 两次跳跃间的延迟
     /// </summary>
     public float jumpDelay = 0.1f;
     /// <summary>
     /// 着陆前仍然可以按下跳跃的时间
     /// </summary>
     public float jumpLeniancy = 0.17f;
     [HideInInspector]
     public int onEnemyBounce;
     /// <summary>
     /// 跳跃类型
     /// </summary>
     private int onJump;
     /// <summary>
     /// 是否着陆
     /// </summary>
     private bool grounded;
     /// <summary>
     /// 检查是否着陆的Transform列表(玩家身体的下面9个点)
     /// </summary>
     private Transform[] floorCheckers;
     /// <summary>
     ///
     /// </summary>
     private Quaternion screenMovementSpace;
     /// <summary>
     /// 按下跳跃的时间,着陆后的时间,当前加速度,当前减速度,当前旋转速度,斜率
     /// </summary>
     private float airPressTime, groundedCount, curAccel, curDecel, curRotateSpeed, slope;
     /// <summary>
     /// 方向,移动方向,屏幕向前移动,屏幕向右移动,移动物体的速度
     /// </summary>
     private Vector3 direction, moveDirection, screenMovementForward, screenMovementRight, movingObjSpeed;

     /// <summary>
     /// 角色移动
     /// </summary>
     private CharacterMotor characterMotor;
     /// <summary>
     /// 敌人AI
     /// </summary>
     private EnemyAI enemyAI;
     /// <summary>
     /// 处理伤害
     /// </summary>
     private DealDamage dealDamage;
     /// <summary>
     /// Rigidbody
     /// </summary>
     private Rigidbody rigid;
     /// <summary>
     /// AudioSource
     /// </summary>
     private AudioSource aSource;

     void Awake() {
         //没有检查列表
         if(!floorChecks) {
             //添加
             floorChecks = new GameObject().transform;
             floorChecks.name = "FloorChecks";
             floorChecks.parent = transform;
             floorChecks.position = transform.position;
             //添加单个子物体
             GameObject check = new GameObject();
             check.name = "Check1";
             check.transform.parent = floorChecks;
             check.transform.position = transform.position;
             Debug.LogWarning("No 'floorChecks' assigned to PlayerMove script, so a single floorcheck has been created",floorChecks);
         }
         //标签不是Player
         if(tag != "Player") {
             //标签改为Player
             tag = "Player";
             Debug.LogWarning("PlayerMove script assigned to object without the tag 'Player', tag has been assigned automatically",transform);
         }

         //获取主摄像机
         mainCam = GameObject.FindGameObjectWithTag("MainCamera").transform;
         //获取处理伤害
         dealDamage = GetComponent<DealDamage>();
         //获取角色移动
         characterMotor = GetComponent<CharacterMotor>();
         //获取刚体
         rigid = GetComponent<Rigidbody>();
         //获取AudioSource
         aSource = GetComponent<AudioSource>();

         //设置检查列表
         floorCheckers = new Transform[floorChecks.childCount];
         ;i < floorCheckers.Length;i++)
             floorCheckers[i] = floorChecks.GetChild(i);
     }

     void Update() {
         //激活刚体
         rigid.WakeUp();
         //计算跳跃
         JumpCalculations();

         //根据玩家是否着地设置当前加速度
         curAccel = (grounded) ? accel : airAccel;
         //根据玩家是否着地设置当前减速度
         curDecel = (grounded) ? decel : airDecel;
         //根据玩家是否着地设置当前旋转速度
         curRotateSpeed = (grounded) ? rotateSpeed : airRotateSpeed;

         screenMovementSpace = Quaternion.Euler(,mainCam.eulerAngles.y,);
         screenMovementForward = screenMovementSpace * Vector3.forward;
         screenMovementRight = screenMovementSpace * Vector3.right;

         float h = Input.GetAxisRaw("Horizontal");
         float v = Input.GetAxisRaw("Vertical");

         //不是卷轴模式
         if(!sidescroller)
             direction = (screenMovementForward * v) + (screenMovementRight * h);
         //是卷轴模式
         else
             //方向等于水平轴的输入*Vector3.right
             direction = Vector3.right * h;
         //移动方向等于当前位置加方向
         moveDirection = transform.position + direction;
     }

     void FixedUpdate() {
         //检查是否着地
         grounded = IsGrounded();
         //角色移动
         characterMotor.MoveTo(moveDirection,curAccel,0.7f,true);
         //旋转角色
          && direction.magnitude != )
             characterMotor.RotateToDirection(moveDirection,curRotateSpeed * ,true);
         //管理角色速度
         characterMotor.ManageSpeed(curDecel,maxSpeed + movingObjSpeed.magnitude,true);
         //播放动画
         if(animator) {
             animator.SetFloat("DistanceToTarget",characterMotor.DistanceToTarget);
             animator.SetBool("Grounded",grounded);
             animator.SetFloat("YVelocity",GetComponent<Rigidbody>().velocity.y);
         }
     }

     void OnCollisionStay(Collision other) {
         if(other.collider.tag != "Untagged" || grounded == false)
             return;
         //在小坡度上停止下滑
          && slope < slopeLimit && rigid.velocity.magnitude < ) {
             rigid.velocity = Vector3.zero;
         }
     }

     /// <summary>
     /// 检查是否着陆
     /// </summary>
     private bool IsGrounded() {
         //计算距离
         float dist = GetComponent<Collider>().bounds.extents.y;

         //遍历所有检查点
         foreach(Transform check in floorCheckers) {
             RaycastHit hit;
             //向下发射射线
             if(Physics.Raycast(check.position,Vector3.down,out hit,dist + 0.05f)) {
                 //如果不是触发器
                 if(!hit.transform.GetComponent<Collider>().isTrigger) {
                     //计算斜率
                     slope = Vector3.Angle(hit.normal,Vector3.up);
                     //斜率大于最大斜率,不是Pushable
                     if(slope > slopeLimit && hit.transform.tag != "Pushable") {
                         //计算滑动方向
                         Vector3 slide = new Vector3(0f,-slideAmount,0f);
                         //刚体施加滑动力
                         rigid.AddForce(slide,ForceMode.Force);
                     }
                     //碰到敌人,y轴速度小于0
                     ) {
                         //获取敌人AI
                         enemyAI = hit.transform.GetComponent<EnemyAI>();
                         //弹开玩家
                         enemyAI.BouncedOn();
                         //
                         onEnemyBounce++;
                         //处理伤害
                         dealDamage.Attack(hit.transform.gameObject,,0f,0f);
                     } else
                         //
                         onEnemyBounce = ;
                     //移动平台或Pushable
                     if(hit.transform.tag == "MovingPlatform" || hit.transform.tag == "Pushable") {
                         //移动物体的速度为刚体的速度
                         movingObjSpeed = hit.transform.GetComponent<Rigidbody>().velocity;
                         //移动物体的y轴速度为0
                         movingObjSpeed.y = 0f;
                         //根据移动物体的速度和摩檫力给玩家刚体添加力
                         rigid.AddForce(movingObjSpeed * movingPlatformFriction * Time.fixedDeltaTime,ForceMode.VelocityChange);
                     } else {
                         //移动物体的速度归0
                         movingObjSpeed = Vector3.zero;
                     }
                     return true;
                 }
             }
         }
         //移动物体的速度归0
         movingObjSpeed = Vector3.zero;
         return false;
     }

     /// <summary>
     /// 计算跳跃
     /// </summary>
     private void JumpCalculations() {
         //保存着陆后的时间
         groundedCount = (grounded) ? groundedCount += Time.deltaTime : 0f;

         //着陆时间小于0.25并且不等于0,正在播放声音,y轴的速度小于1
          && !GetComponent<AudioSource>().isPlaying && landSound && GetComponent<Rigidbody>().velocity.y < ) {
             //根据y轴的速度修改音量
             aSource.volume = Mathf.Abs(GetComponent<Rigidbody>().velocity.y) / ;
             //修改声音
             aSource.clip = landSound;
             //播放声音
             aSource.Play();
         }
         //按下jump且没有着陆
         if(Input.GetButtonDown("Jump") && !grounded)
             //修改按下跳跃的时间为当前时间
             airPressTime = Time.time;

         //着陆,斜率小于最大斜率
         if(grounded && slope < slopeLimit) {
             //按下Jump
             if(Input.GetButtonDown("Jump") || airPressTime + jumpLeniancy > Time.time) {
                 //切换跳跃类型
                 onJump = (groundedCount < jumpDelay) ? Mathf.Min(,onJump + ) : ;

                 )
                     Jump(jumpForce);
                 )
                     Jump(secondJumpForce);
                 ) {
                     Jump(thirdJumpForce);
                     onJump--;
                 }
             }
         }
     }

     /// <summary>
     /// 跳跃
     /// </summary>
     public void Jump(Vector3 jumpVelocity) {
         //播放跳跃声音
         if(jumpSound) {
             aSource.volume = ;
             aSource.clip = jumpSound;
             aSource.Play();
         }
         //改变刚体的y轴速度
         rigid.velocity = new Vector3(rigid.velocity.x,0f,rigid.velocity.z);
         //给刚体添加力
         rigid.AddRelativeForce(jumpVelocity,ForceMode.Impulse);
         //重置按下跳跃的时间
         airPressTime = 0f;
     }
 }

PlayerMove

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 让玩家拾取,扔,推物体
 /// </summary>
 [RequireComponent(typeof(AudioSource))]
 [RequireComponent(typeof(Rigidbody))]
 [RequireComponent(typeof(PlayerMove))]
 public class Throwing : MonoBehaviour
 {
     /// <summary>
     /// 拾取声音
     /// </summary>
     public AudioClip pickUpSound;
     /// <summary>
     /// 扔声音
     /// </summary>
     public AudioClip throwSound;
     /// <summary>
     /// 用来抓物体的子游戏物体
     /// </summary>
     public GameObject grabBox;
     /// <summary>
     /// 举起物体的偏移
     /// </summary>
     public Vector3 holdOffset;
     /// <summary>
     /// 扔的力
     /// </summary>
     , , );
     /// <summary>
     /// 转向物体的速度
     /// </summary>
     ;
     /// <summary>
     /// 检查玩家头部的范围
     /// </summary>
     public float checkRadius = 0.5f;
     /// <summary>
     /// 拾取物体的重量
     /// </summary>
     [Range(0.1f, 1f)]
     public float weightChange = 0.3f;
     /// <summary>
     /// 未用
     /// </summary>
     [Range(10f, 1000f)]
     , holdingBreakTorque = ;
     /// <summary>
     /// Animator
     /// </summary>
     public Animator animator;
     /// <summary>
     /// 手臂动画层
     /// </summary>
     public int armsAnimationLayer;                                

     /// <summary>
     /// 举起或抓住的物体
     /// </summary>
     [HideInInspector]
     public GameObject heldObj;
     /// <summary>
     /// 举起物体的位置
     /// </summary>
     private Vector3 holdPos;
     /// <summary>
     /// 连接物体和角色的关节
     /// </summary>
     private FixedJoint joint;
     /// <summary>
     /// 举起物体的时间,扔物体的时间,默认旋转速度
     /// </summary>
     private float timeOfPickup, timeOfThrow, defRotateSpeed;
     /// <summary>
     /// gizmo颜色
     /// </summary>
     private Color gizmoColor;
     /// <summary>
     /// AudioSource
     /// </summary>
     private AudioSource aSource;
     /// <summary>
     /// 玩家移动
     /// </summary>
     private PlayerMove playerMove;
     /// <summary>
     /// 父物体下的子物体的触发器
     /// </summary>
     private TriggerParent triggerParent;
     /// <summary>
     /// 默认刚体插值类型
     /// </summary>
     private RigidbodyInterpolation objectDefInterpolation;

     void Awake()
     {
         //获取AudioSource
         aSource = GetComponent<AudioSource>();
         //没有抓物体的子物体
         if(!grabBox)
         {
             //新建
             grabBox = new GameObject();
             //添加碰撞器
             grabBox.AddComponent<BoxCollider>();
             //设置为触发器
             grabBox.GetComponent<Collider>().isTrigger = true;
             //设置玩家为父物体
             grabBox.transform.parent = transform;
             //修改局部坐标
             grabBox.transform.localPosition = new Vector3(0f, 0f, 0.5f);
             //修改层(Ignore Raycast)
             grabBox.layer = ;
             Debug.LogWarning("No grabBox object assigned to 'Throwing' script, one has been created and assigned for you", grabBox);
         }
         //获取玩家移动脚本
         playerMove = GetComponent<PlayerMove>();
         //设置默认旋转速度
         defRotateSpeed = playerMove.rotateSpeed;
         //Animator不为空
         if(animator)
             //设置手臂动画层的权重
             animator.SetLayerWeight(armsAnimationLayer, );
     }

     void Update()
     {
         //按下Grab键,有举起或抓住的物体,当前时间比举起物体的时间大0.1f
         if (Input.GetButtonDown ("Grab") && heldObj && Time.time > timeOfPickup + 0.1f)
         {
             //举起物体的标签为"Pickup"
             if(heldObj.tag == "Pickup")
                 //扔掉举起的物体
                 ThrowPickup();
         }
         //有Animator
         if(animator)
             //有举起的物体且物体标签为"Pickup"
             if(heldObj && heldObj.tag == "Pickup")
                 animator.SetBool ("HoldingPickup", true);
             else
                 animator.SetBool ("HoldingPickup", false);
             //有抓住的物体且物体标签为"Pushable"
             if(heldObj && heldObj.tag == "Pushable")
                 animator.SetBool ("HoldingPushable", true);
             else
                 animator.SetBool ("HoldingPushable", false);

         //有抓住的物体且物体标签为"Pushable"
         if (heldObj && heldObj.tag == "Pushable")
         {
             //按下Grab
             if(Input.GetButtonUp ("Grab"))
             {
                 //丢弃物体
                 DropPushable();
             }
             //没有关节
             if(!joint)
             {
                 //丢弃物体
                 DropPushable();
                 print ("'Pushable' object dropped because the 'holdingBreakForce' or 'holdingBreakTorque' was exceeded");
             }
         }
     }

     void OnTriggerStay(Collider other)
     {
         //按下Grab
         if(Input.GetButton("Grab"))
         {
             //标签为"Pickup",没有举起的物体,当前时间大于扔物体的时间加0.2
             if(other.tag == "Pickup" && heldObj == null && timeOfThrow + 0.2f < Time.time)
                 //举起物体
                 LiftPickup(other);
             //标签为"Pushable",没有抓住的物体,当前时间大于扔物体的时间加0.2
             if(other.tag == "Pushable" && heldObj == null && timeOfThrow + 0.2f < Time.time)
                 //抓物体
                 GrabPushable(other);
         }
     }

     /// <summary>
     /// 抓住物体
     /// </summary>
     private void GrabPushable(Collider other)
     {
         //抓住的物体为碰撞的物体
         heldObj = other.gameObject;
         //获取物体的插值类型
         objectDefInterpolation = heldObj.GetComponent<Rigidbody>().interpolation;
         //修改物体的插值为内插值
         heldObj.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
         //添加关节,连接玩家和物体
         AddJoint ();
         //设置破坏关节的力为无限
         joint.breakForce = Mathf.Infinity;
         //设置破坏关节的扭矩力为无限
         joint.breakTorque = Mathf.Infinity;
         //设置玩家移动的旋转速度为0
         playerMove.rotateSpeed = ;
     }

     /// <summary>
     /// 举起物体
     /// </summary>
     private void LiftPickup(Collider other)
     {
         //获取物体的网格
         Mesh otherMesh = other.GetComponent<MeshFilter>().mesh;
         //计算举起的位置
         holdPos = transform.position + transform.forward * holdOffset.z + transform.right * holdOffset.x + transform.up * holdOffset.y;
         //举起的位置的y值加碰撞器的范围的y值加碰撞物体网格的范围的y值
         holdPos.y += (GetComponent<Collider>().bounds.extents.y) + (otherMesh.bounds.extents.y);

         //检测举起位置的圆形范围
         if(!Physics.CheckSphere(holdPos,checkRadius)) {
             //修改gizmo颜色
             gizmoColor = Color.green;
             //缓存举起的物体
             heldObj = other.gameObject;
             //修改默认插值类型
             objectDefInterpolation = heldObj.GetComponent<Rigidbody>().interpolation;
             //修改举起物体的插值类型
             heldObj.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
             //修改举起物体的位置
             heldObj.transform.position = holdPos;
             //修改举起物体的旋转
             heldObj.transform.rotation = transform.rotation;
             //添加关节,连接物体和玩家
             AddJoint();
             //修改举起物体的质量
             heldObj.GetComponent<Rigidbody>().mass *= weightChange;
             //修改举起物体的时间为当前时间
             timeOfPickup = Time.time;
         } else {
             //修改gizmo颜色
             gizmoColor = Color.red;
             print("Can't lift object here. If nothing is above the player, perhaps you need to add a layerMask parameter to line 136 of the code in this script," +
                 "the CheckSphere function, in order to make sure it isn't detecting something above the players head that is invisible");
         }
     }

     /// <summary>
     /// 放下物体
     /// </summary>
     private void DropPushable()
     {
         //修改抓住物体的插值类型
         heldObj.GetComponent<Rigidbody>().interpolation = objectDefInterpolation;
         //销毁关节
         Destroy (joint);
         //修改玩家移动的旋转速度为默认旋转速度
         playerMove.rotateSpeed = defRotateSpeed;
         heldObj = null;
         timeOfThrow = Time.time;
     }

     /// <summary>
     /// 扔掉物体
     /// </summary>
     public void ThrowPickup()
     {
         //播放扔物体声音
         if(throwSound)
         {
             aSource.volume = ;
             aSource.clip = throwSound;
             aSource.Play ();
         }
         //删除关节
         Destroy (joint);
         //获取举起物体的刚体
         Rigidbody r = heldObj.GetComponent<Rigidbody>();
         //恢复物体的插值类型
         r.interpolation = objectDefInterpolation;
         //恢复物体的质量
         r.mass /= weightChange;
         //给刚体添加力
         r.AddRelativeForce (throwForce, ForceMode.VelocityChange);

         heldObj = null;
         timeOfThrow = Time.time;
     }

     /// <summary>
     /// 添加关节,连接玩家和物体
     /// </summary>
     private void AddJoint()
     {
         //如果有物体
         if (heldObj)
         {
             //播放拾取声音
             if(pickUpSound)
             {
                 aSource.volume = ;
                 aSource.clip = pickUpSound;
                 aSource.Play ();
             }
             //在物体上添加关节
             joint = heldObj.AddComponent<FixedJoint>();
             //设置关节的连接物体为玩家的刚体
             joint.connectedBody = GetComponent<Rigidbody>();
         }
     }

     void OnDrawGizmosSelected()
     {
         Gizmos.color = gizmoColor;
         Gizmos.DrawSphere (holdPos, checkRadius);
     }
 }

Throwing

 using UnityEngine;
 using System.Collections;

 /// <summary>
 /// 父物体下的子物体的触发器
 /// </summary>
 public class TriggerParent:MonoBehaviour {

     /// <summary>
     /// 要检查的标签列表
     /// </summary>
     public string[] tagsToCheck;            

     /// <summary>
     /// 是否发生了碰撞,是否在碰撞中
     /// </summary>
     [HideInInspector]
     public bool collided, colliding;
     /// <summary>
     /// 撞击的物体
     /// </summary>
     [HideInInspector]
     public GameObject hitObject;

     void Awake() {
         //没有Collider或有Collider但不是触发器
         if(!GetComponent<Collider>() || (GetComponent<Collider>() && !GetComponent<Collider>().isTrigger))
             Debug.LogError("'TriggerParent' script attached to object which does not have a trigger collider",transform);
     }

     void OnTriggerEnter(Collider other) {
         //标签列表长度大于0且没有碰撞过
          && !collided) {
             //遍历标签
             foreach(string tag in tagsToCheck) {
                 //找到标签
                 if(other.tag == tag) {
                     //已发生碰撞
                     collided = true;
                     //存储碰撞物体
                     hitObject = other.gameObject;
                     break;
                 }

             }
         } else
             //已发生碰撞
             collided = true;
         //存储碰撞物体
         hitObject = other.gameObject;
     }

     void OnTriggerStay(Collider other) {
         //标签列表长度大于0
         ) {
             //遍历标签
             foreach(string tag in tagsToCheck) {
                 //找到标签
                 if(other.tag == tag) {
                     //正在碰撞
                     colliding = true;
                     //存储碰撞物体
                     hitObject = other.gameObject;
                     break;
                 }
             }
         } else {
             //存储碰撞物体
             hitObject = other.gameObject;
             //正在碰撞
             colliding = true;
         }
     }

     void OnTriggerExit(Collider other) {
         //标签列表长度大于0
         ) {
             //遍历标签
             foreach(string tag in tagsToCheck) {
                 //找到标签
                 if(other.tag == tag) {
                     colliding = false;
                     hitObject = null;
                     break;
                 }
             }
         } else
             return;
     }

     void LateUpdate() {
         //重置collided,hitObject
         if(collided) {
             collided = false;
             hitObject = null;
         }
     }
 }

TriggerParent

 using UnityEngine;
 using System.Collections;
 using System.Collections.Generic;

 /// <summary>
 /// 水
 /// </summary>
 [RequireComponent(typeof(BoxCollider))]
 public class Water:MonoBehaviour {
     /// <summary>
     /// 玩家进水的声音
     /// </summary>
     public AudioClip splashSound;
     /// <summary>
     /// 水的推力
     /// </summary>
     ,);
     /// <summary>
     /// 玩家是否会受到水的阻力影响
     /// </summary>
     public bool effectPlayerDrag;
     /// <summary>
     /// 刚体受到的水的阻力(不包含玩家)
     /// </summary>
     public float resistance = 0.4f;
     /// <summary>
     /// 刚体受到的角阻力(不包含玩家)
     /// </summary>
     public float angularResistance = 0.2f;                

     /// <summary>
     /// 刚体受到的阻力字典
     /// </summary>
     private Dictionary<GameObject,float> dragStore = new Dictionary<GameObject,float>();
     /// <summary>
     /// 刚体受到的角阻力字典
     /// </summary>
     private Dictionary<GameObject,float> angularStore = new Dictionary<GameObject,float>();

     void Awake() {
         //自动修改"Water"标签
         if(tag != "Water") {
             tag = "Water";
             Debug.LogWarning("'Water' script attached to an object not tagged 'Water', it been assigned the tag 'Water'",transform);
         }
         //设置Trigger
         GetComponent<Collider>().isTrigger = true;
     }

     void OnTriggerEnter(Collider other) {
         //获取物体的刚体
         Rigidbody r = other.GetComponent<Rigidbody>();
         //刚体不为空
         if(r) {
             //播放入水声音
             if(splashSound) {
                 ;
                 AudioSource.PlayClipAtPoint(splashSound,other.transform.position,volume);
             }

             //是玩家且不受水的阻力影响
             if(r.tag == "Player" && !effectPlayerDrag)
                 return;

             //存储受到的阻力
             dragStore.Add(r.gameObject,r.drag);
             //存储受到的角阻力
             angularStore.Add(r.gameObject,r.angularDrag);

             //修改刚体受到的阻力
             r.drag = resistance;
             //修改刚体受到的角阻力
             r.angularDrag = angularResistance;
         } else if(splashSound)
             //播放入水声音
             AudioSource.PlayClipAtPoint(splashSound,other.transform.position);
     }

     void OnTriggerStay(Collider other) {
         //计算表面高度
         float surface = transform.position.y + GetComponent<Collider>().bounds.extents.y;
         Rigidbody rigid = other.GetComponent<Rigidbody>();
         if(rigid) {
             //计算物体相对于表面高度的深度
             float depth = surface - other.transform.position.y;
             //深度大于0.4
             if(depth > 0.4f)
                 //用一个较小的力往上推刚体
                 rigid.AddForce(force,ForceMode.Force);
             //深度小于等于0.4
             else
                 //用一个较大的力往上推刚体
                 rigid.AddForce(force * (depth * ),ForceMode.Force);
         }
     }

     void OnTriggerExit(Collider other) {
         //获取物体的刚体
         Rigidbody r = other.GetComponent<Rigidbody>();
         //有刚体
         if(r) {
             //是玩家且不受阻力水的阻力影响
             if(r.tag == "Player" && !effectPlayerDrag)
                 return;

             //阻力和角阻力字典包含刚体的游戏物体
             if(dragStore.ContainsKey(r.gameObject) && angularStore.ContainsKey(r.gameObject)) {
                 //恢复阻力
                 r.drag = dragStore[r.gameObject];
                 //恢复角阻力
                 r.angularDrag = angularStore[r.gameObject];
                 //移除阻力
                 dragStore.Remove(r.gameObject);
                 //移除角阻力
                 angularStore.Remove(r.gameObject);
             } else {
                 //重置阻力
                 r.drag = 0f;
                 //重置角阻力
                 r.angularDrag = 0.05f;
                 print("Object left water: couldn't get drag values, restored to defaults");
             }
         }
     }
 }

Water

视频:https://pan.baidu.com/s/1mhF7hmo

项目:https://pan.baidu.com/s/1pL6nMTP

Complete Physics Platformer Kit 学习的更多相关文章

  1. iOS7 Sprite Kit 学习

    iOS7 Sprite Kit 学习 iOS 7有一个新功能 Sprite Kit 这个有点类似cocos2d 感觉用法都差不多.下面简单来介绍下Sprite Kit About Sprite Kit ...

  2. S老师 Top-Down RPG Starter Kit 学习

    character creation using UnityEngine; using System.Collections; public class CharacterCreation : Mon ...

  3. Sprite Kit编程指南(1)-深入Sprite Kit

    深入Sprite Kit 学习Sprite Kit最好的方法是在实践中观察它.此示例创建一对场景和各自的动画内容.通过这个例子,你将学习使用Sprite Kit内容的一些基础技术,包括: ·      ...

  4. [Unity3D]Unity资料大全免费分享

     都是网上找的连七八糟的资料了,整理好分享的,有学习资料,视频,源码,插件……等等 东西比较多,不是所有的都是你需要的,可以按  ctrl+F 来搜索你要的东西,如果有广告,不用理会,关掉就可以了,如 ...

  5. 【转】iOS 开发怎么入门?

    原文网址:http://www.zhihu.com/question/20264108 iOS 开发怎么入门? 请问有设计模式.内存管理方面的资料吗?最好有除了官方文档之外的其它内容,10 条评论 分 ...

  6. DirectX SDK版本与Visual Studio版本

    对于刚刚接触 DirectShow 的人来说,安装配置是一个令人头疼的问题,经常出现的情况是最基本的 baseclass 就无法编译.一开始我也为此费了很大的功夫,比如说修改代码.修改编译选项使其编译 ...

  7. How to Write Doc Comments for the Javadoc Tool

    http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html This document describe ...

  8. DirectX

    DirectX 9.0 Complete Software Development Kit (SDK) :(2002-12-19) 点击下载 DirectX 9.0 SDK Update - (Sum ...

  9. 转 springboot 教程

    转 Spring Boot 揭秘与实战 系列 拓展阅读: https://zhuanlan.zhihu.com/dreawer?topic=Java 发表于 2016-12-21 | Spring框架 ...

随机推荐

  1. SQL-33 创建一个actor表,包含如下列信息

    题目描述   创建一个actor表,包含如下列信息 列表 类型 是否为NULL 含义 actor_id smallint(5) not null 主键id first_name varchar(45) ...

  2. 国行 lg g3 D858 刷 lg g3 D858hk 教程(备忘)

    纯手打,转载请注明出处~ 刷机有风险,出现问题概不负责! 本着自娱自乐的宗旨 ,分享一下,出了问题不负责! 准备的材料: 1,手机一枚(废话)国行lg g3 d858 2,root 工具 用来root ...

  3. MERGE INTO 解决大数据量 10w 更新缓慢的问题

    有个同事处理更新数据缓慢的问题,数据量超10w的量,更新速度太慢耗时较长,然后改成了 MERGE INTO 效率显著提高. 使用方法如下 MERGE INTO 表A USING 表B ON 关联条件 ...

  4. Windows 窗体设计器生成的代码

    namespace 窗体的浮动及隐藏{    partial class Form1    {        /// <summary>        /// 必需的设计器变量.      ...

  5. 基于ArduinoLeonardo板子的BadUSB攻击实战

    0X00 前言 在Freebuf上许多同学已经对HID攻击谈了自己的看法,如维克斯同学的<利用Arduino快速制作Teensy BadUSB>无论从科普还是实践都给我们详尽的描述了Bad ...

  6. django本身提供了runserver,为什么不能用来部署(runserver与uWSGI的区别)

    runserver方法是调试django时经常用到的运行方式,它使用django自带的. WSGI Server 运行,主要在测试和开发使用,并且runserver 开启的方式也是单线程. uWSGI ...

  7. git 清空缓冲区

    git rm与git rm --cached 当我们需要删除暂存区或分支上的文件, 同时工作区也不需要这个文件了, 可以使用 git rm file_path git commit -m 'delet ...

  8. XML Schema——笔记整理

    什么是 XML Schema? 定义可出现在文档中的元素 定义可出现在文档中的属性 定义哪个元素是子元素 定义子元素的次序 定义子元素的数目 定义元素是否为空,或者是否可包含文本 定义元素和属性的数据 ...

  9. Eclipse 通过JPA自动生成注解实体

    hibernate是JPA最常用的实现之一,而且hiberante自身也对注释语法进行了支持.现在再不用去看那一堆堆的XML映射了.而且eclipse还提供了从数据库直接生成Entity Class的 ...

  10. 运放积分电路MULTISIM

    有些需要反馈回路