博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Complete Physics Platformer Kit 学习
阅读量:6265 次
发布时间:2019-06-22

本文共 62253 字,大约阅读时间需要 207 分钟。

1 using UnityEngine;  2   3 ///   4 /// 摄像机跟随玩家  5 ///   6 public class CameraFollow : MonoBehaviour   7 {  8     ///   9     /// 目标 10     ///  11     public Transform target;                                     12     ///  13     /// 和目标之间的偏移 14     ///  15     public Vector3 targetOffset =  new Vector3(0f, 3.5f, 7);     16     ///  17     /// 是否锁定旋转 18     ///  19     public bool lockRotation;                                    20     ///  21     /// 跟随速度 22     ///  23     public float followSpeed = 6;                                24     ///  25     /// 围绕目标旋转的速度 26     ///  27     public float inputRotationSpeed = 100;                       28     ///  29     /// 是否可以由鼠标控制旋转(只有在相机没有被固定的情况下) 30     ///  31     public bool mouseFreelook;                                     32     ///  33     /// 旋转阻尼 34     ///  35     public float rotateDamping = 100;                            36     ///  37     /// 摄像机在水中时的过滤物体 38     ///  39     public GameObject waterFilter;                               40     ///  41     ///  42     ///  43     public string[] avoidClippingTags;                                       44      45     ///  46     /// Camera Target 47     ///  48     private Transform followTarget; 49     ///  50     /// 暂未用到 51     ///  52     private bool camColliding; 53      54     //setup objects 55     void Awake() 56     { 57         //创建跟随物体(Camera Target) 58         followTarget = new GameObject().transform; 59         followTarget.name = "Camera Target"; 60         if(waterFilter) 61             waterFilter.GetComponent
().enabled = false; 62 if(!target) 63 Debug.LogError("'CameraFollow script' has no target assigned to it", transform); 64 65 //如果用鼠标控制旋转,旋转阻尼为0 66 if(mouseFreelook) 67 rotateDamping = 0f; 68 } 69 70 void Update() 71 { 72 //没有目标不处理 73 if (!target) 74 return; 75 //平滑跟随 76 SmoothFollow (); 77 //平滑朝向玩家 78 if(rotateDamping > 0) 79 SmoothLookAt(); 80 //直接朝向玩家 81 else 82 transform.LookAt(target.position); 83 } 84 85 86 void OnTriggerEnter(Collider other) 87 { 88 //打开水遮罩 89 if (other.tag == "Water" && waterFilter) 90 waterFilter.GetComponent
().enabled = true; 91 } 92 93 void OnTriggerExit(Collider other) 94 { 95 //关闭水遮罩 96 if (other.tag == "Water" && waterFilter) 97 waterFilter.GetComponent
().enabled = false; 98 } 99 100 ///
101 /// 平滑朝向目标102 /// 103 void SmoothLookAt()104 {105 Quaternion rotation = Quaternion.LookRotation (target.position - transform.position);106 transform.rotation = Quaternion.Slerp (transform.rotation, rotation, rotateDamping * Time.deltaTime);107 }108 109 ///
110 /// 平滑跟随目标111 /// 112 void SmoothFollow()113 {114 followTarget.position = target.position;115 followTarget.Translate(targetOffset, Space.Self);116 if (lockRotation)117 followTarget.rotation = target.rotation;118 119 //鼠标控制围绕目标旋转120 if(mouseFreelook)121 {122 float axisX = Input.GetAxis ("Mouse X") * inputRotationSpeed * Time.deltaTime;123 followTarget.RotateAround (target.position,Vector3.up, axisX);124 float axisY = Input.GetAxis ("Mouse Y") * inputRotationSpeed * Time.deltaTime;125 followTarget.RotateAround (target.position, transform.right, -axisY);126 }127 //键盘控制围绕目标旋转128 else129 {130 float axis = Input.GetAxis ("CamHorizontal") * inputRotationSpeed * Time.deltaTime;131 followTarget.RotateAround (target.position, Vector3.up, axis);132 }133 134 //计算相机的下一帧位置135 Vector3 nextFramePosition = Vector3.Lerp(transform.position, followTarget.position, followSpeed * Time.deltaTime);136 Vector3 direction = nextFramePosition - target.position;137 //射线检测这个位置138 RaycastHit hit;139 if(Physics.Raycast (target.position, direction, out hit, direction.magnitude + 0.3f))140 {141 transform.position = nextFramePosition;142 foreach(string tag in avoidClippingTags)143 //如果这个位置有物体,修改相机位置144 if(hit.transform.tag == tag)145 transform.position = hit.point - direction.normalized * 0.3f;146 }147 else148 {149 //直接修改相机位置150 transform.position = nextFramePosition;151 }152 }153 }
CameraFollow
1 using UnityEngine;  2   3 ///   4 /// 角色移动  5 ///   6 [RequireComponent(typeof(Rigidbody))]  7 public class CharacterMotor:MonoBehaviour {  8     ///   9     /// 是否冻结z轴的移动 10     ///  11     public bool sidescroller; 12     ///  13     /// 当前速度 14     ///  15     [HideInInspector] 16     public Vector3 currentSpeed; 17     ///  18     /// 到目标的距离 19     ///  20     [HideInInspector] 21     public float DistanceToTarget; 22     ///  23     /// 刚体 24     ///  25     private Rigidbody rigid; 26  27     void Awake() { 28         //设置rigidbody 29         rigid = GetComponent
(); 30 rigid.interpolation = RigidbodyInterpolation.Interpolate; 31 if(sidescroller) 32 rigid.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ; 33 else 34 rigid.constraints = RigidbodyConstraints.FreezeRotation; 35 //添加光滑的物理材质 36 if(GetComponent
().material.name == "Default (Instance)") { 37 PhysicMaterial pMat = new PhysicMaterial(); 38 pMat.name = "Frictionless"; 39 pMat.frictionCombine = PhysicMaterialCombine.Multiply; 40 pMat.bounceCombine = PhysicMaterialCombine.Multiply; 41 pMat.dynamicFriction = 0f; 42 pMat.staticFriction = 0f; 43 GetComponent
().material = pMat; 44 Debug.LogWarning("No physics material found for CharacterMotor, a frictionless one has been created and assigned",transform); 45 } 46 } 47 48 ///
49 /// 移动刚体到指定位置 50 /// 51 public bool MoveTo(Vector3 destination,float acceleration,float stopDistance,bool ignoreY) { 52 Vector3 relativePos = (destination - transform.position); 53 //忽略y轴? 54 if(ignoreY) 55 relativePos.y = 0; 56 57 DistanceToTarget = relativePos.magnitude; 58 if(DistanceToTarget <= stopDistance) 59 return true; 60 else 61 rigid.AddForce(relativePos.normalized * acceleration * Time.deltaTime,ForceMode.VelocityChange); 62 return false; 63 } 64 65 ///
66 /// 旋转刚体朝向当前速度 67 /// 68 public void RotateToVelocity(float turnSpeed,bool ignoreY) { 69 Vector3 dir; 70 if(ignoreY) 71 dir = new Vector3(rigid.velocity.x,0f,rigid.velocity.z); 72 else 73 dir = rigid.velocity; 74 75 if(dir.magnitude > 0.1) { 76 Quaternion dirQ = Quaternion.LookRotation(dir); 77 Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,dir.magnitude * turnSpeed * Time.deltaTime); 78 rigid.MoveRotation(slerp); 79 } 80 } 81 82 ///
83 /// 旋转刚体朝向指定方向 84 /// 85 public void RotateToDirection(Vector3 lookDir,float turnSpeed,bool ignoreY) { 86 Vector3 characterPos = transform.position; 87 //忽略y轴? 88 if(ignoreY) { 89 characterPos.y = 0; 90 lookDir.y = 0; 91 } 92 93 Vector3 newDir = lookDir - characterPos; 94 Quaternion dirQ = Quaternion.LookRotation(newDir); 95 Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,turnSpeed * Time.deltaTime); 96 rigid.MoveRotation(slerp); 97 } 98 99 ///
100 /// 管理速度101 /// 102 public void ManageSpeed(float deceleration,float maxSpeed,bool ignoreY) {103 currentSpeed = rigid.velocity;104 //忽略y轴105 if(ignoreY)106 currentSpeed.y = 0;107 108 if(currentSpeed.magnitude > 0) {109 rigid.AddForce((currentSpeed * -1) * deceleration * Time.deltaTime,ForceMode.VelocityChange);110 if(rigid.velocity.magnitude > maxSpeed)111 rigid.AddForce((currentSpeed * -1) * deceleration * Time.deltaTime,ForceMode.VelocityChange);112 }113 }114 }
CharacterMotor
1 using UnityEngine; 2  3 ///  4 /// 检查点 5 ///  6 [RequireComponent(typeof(CapsuleCollider))] 7 [RequireComponent(typeof(AudioSource))] 8 public class Checkpoint : MonoBehaviour  9 {10     /// 11     /// 激活颜色12     /// 13     public Color activeColor = Color.green;    14     /// 15     /// 激活时的不透明度16     /// 17     public float activeColorOpacity = 0.4f;          18     19     /// 20     /// 生命21     /// 22     private Health health;23     /// 24     /// 默认颜色25     /// 26     private Color defColor;27     /// 28     /// 检查点列表29     /// 30     private GameObject[] checkpoints;31     /// 32     /// 渲染器33     /// 34     private Renderer render;35     /// 36     /// AudioSource37     /// 38     private AudioSource aSource;39 40     void Awake()41     {42         render = GetComponent
();43 aSource = GetComponent
();44 //标签不是Respawn,自动修改标签45 if(tag != "Respawn")46 {47 tag = "Respawn";48 Debug.LogWarning ("'Checkpoint' script attached to object without the 'Respawn' tag, tag has been assigned automatically", transform); 49 }50 GetComponent
().isTrigger = true;51 //设置默认颜色和不透明度52 if(render)53 defColor = render.material.color;54 activeColor.a = activeColorOpacity;55 }56 57 58 void Start()59 {60 checkpoints = GameObject.FindGameObjectsWithTag("Respawn");61 health = GameObject.FindGameObjectWithTag("Player").GetComponent
();62 if(!health)63 Debug.LogError("For Checkpoint to work, the Player needs 'Health' script attached", transform);64 }65 66 67 void OnTriggerEnter(Collider other)68 {69 //如果碰到玩家70 if(other.transform.tag == "Player" && health)71 {72 health.respawnPos = transform.position;73 74 if(render.material.color != activeColor)75 {76 foreach (GameObject checkpoint in checkpoints)77 checkpoint.GetComponent
().material.color = defColor;78 aSource.Play();79 render.material.color = activeColor;80 }81 }82 }83 }
Checkpoint
1 using UnityEngine;  2   3 ///   4 /// 金币  5 ///   6 [RequireComponent(typeof(SphereCollider))]  7 public class Coin : MonoBehaviour   8 {  9     ///  10     /// 被收集时的声音 11     ///  12     public AudioClip collectSound;                             13     ///  14     /// 旋转 15     ///  16     public Vector3 rotation = new Vector3(0, 80, 0);         17     ///  18     /// 玩家靠近时,增加的旋转 19     ///  20     public Vector3 rotationGain = new Vector3(10, 20, 10);     21     ///  22     /// 金币向玩家移动的速度 23     ///  24     public float startSpeed = 3f;                             25     ///  26     /// 金币向玩家移动的加速度 27     ///  28     public float speedGain = 0.2f;                              29      30     ///  31     /// 是否被搜集 32     ///  33     private bool collected; 34     ///  35     /// 玩家 36     ///  37     private Transform player; 38     ///  39     /// 子物体的触发器 40     ///  41     private TriggerParent triggerParent; 42     ///  43     /// GUI 44     ///  45     private GUIManager gui; 46      47  48     void Awake() 49     { 50         gui = FindObjectOfType(typeof(GUIManager)) as GUIManager ; 51         if(tag != "Coin") 52         { 53             tag = "Coin"; 54             Debug.LogWarning ("'Coin' script attached to object not tagged 'Coin', tag added automatically", transform); 55         } 56         GetComponent
().isTrigger = true; 57 triggerParent = GetComponentInChildren
(); 58 //添加bounds子物体 59 if(!triggerParent) 60 { 61 GameObject bounds = new GameObject(); 62 bounds.name = "Bounds"; 63 bounds.AddComponent
(); 64 bounds.GetComponent
().radius = 7f; 65 bounds.GetComponent
().isTrigger = true; 66 bounds.transform.parent = transform; 67 bounds.transform.position = transform.position; 68 bounds.AddComponent
(); 69 triggerParent = GetComponentInChildren
(); 70 triggerParent.tagsToCheck = new string[1]; 71 triggerParent.tagsToCheck[0] = "Player"; 72 Debug.LogWarning ("No pickup radius 'bounds' trigger attached to coin: " + transform.name + ", one has been added automatically", bounds); 73 } 74 } 75 76 void Start() 77 { 78 player = GameObject.FindGameObjectWithTag("Player").transform; 79 } 80 81 void Update() 82 { 83 84 transform.Rotate (rotation * Time.deltaTime, Space.World); 85 86 if(triggerParent.collided) 87 collected = true; 88 89 //增加金币的旋转速度和移动速度,将金币移向玩家 90 if (collected) 91 { 92 startSpeed += speedGain; 93 rotation += rotationGain; 94 transform.position = Vector3.Lerp (transform.position, player.position, startSpeed * Time.deltaTime); 95 } 96 } 97 98 void OnTriggerEnter(Collider other) 99 {100 if (other.tag == "Player")101 CoinGet();102 }103 104 ///
105 /// 获取金币106 /// 107 void CoinGet()108 {109 if(collectSound)110 AudioSource.PlayClipAtPoint(collectSound, transform.position);111 if (gui)112 gui.coinsCollected ++;113 Destroy(gameObject);114 }115 }
Coin
1 using UnityEngine; 2  3 ///  4 /// 处理伤害 5 ///  6 public class DealDamage : MonoBehaviour  7 { 8     ///  9     /// 受害人的生命10     /// 11     private Health health;12     13     /// 14     /// 攻击15     /// 16     public void Attack(GameObject victim, int dmg, float pushHeight, float pushForce)17     {18         health = victim.GetComponent
(); 19 20 //推物体21 Vector3 pushDir = (victim.transform.position - transform.position);22 pushDir.y = 0f;23 pushDir.y = pushHeight * 0.1f;24 if (victim.GetComponent
() && !victim.GetComponent
().isKinematic)25 {26 victim.GetComponent
().velocity = new Vector3(0, 0, 0);27 victim.GetComponent
().AddForce (pushDir.normalized * pushForce, ForceMode.VelocityChange);28 victim.GetComponent
().AddForce (Vector3.up * pushHeight, ForceMode.VelocityChange);29 }30 //应用伤害31 if(health && !health.flashing)32 health.currentHealth -= dmg;33 }34 }
DealDamage
1 using UnityEngine; 2 using System.Collections; 3  4 ///  5 /// 摧毁物体 6 ///  7 public class DestroyObject : MonoBehaviour  8 { 9     /// 10     /// 摧毁声音11     /// 12     public AudioClip destroySound;    13     /// 14     /// 延迟15     /// 16     public float delay;                               17     /// 18     /// 是否分离子物体并且不摧毁子物体19     /// 20     public bool destroyChildren;    21     /// 22     /// 从父物体中心推开子物体的数量23     /// 24     public float pushChildAmount;    25     26     27     void Start()28     {29         //获取子物体列表30         Transform[] children = new Transform[transform.childCount];31         for (int i = 0; i < transform.childCount; i++)32             children[i] = transform.GetChild(i);33         34         //分离子物体35         if (!destroyChildren)36             transform.DetachChildren();37         38         //给子物体添加一个推力和旋转39         foreach (Transform child in children)40         {41             Rigidbody rigid = child.GetComponent
();42 if(rigid && pushChildAmount != 0)43 {44 Vector3 pushDir = child.position - transform.position;45 rigid.AddForce(pushDir * pushChildAmount, ForceMode.Force);46 rigid.AddTorque(Random.insideUnitSphere, ForceMode.Force);47 }48 }49 50 //删除父物体51 if(destroySound)52 AudioSource.PlayClipAtPoint(destroySound, transform.position);53 Destroy (gameObject, delay);54 }55 }
DestroyObject
1 using UnityEngine;  2 using System.Collections;  3   4 ///   5 /// 敌人AI  6 ///   7 [RequireComponent(typeof(CharacterMotor))]  8 [RequireComponent(typeof(DealDamage))]  9 public class EnemyAI : MonoBehaviour  10 { 11     ///  12     /// 移动加速度 13     ///  14     public float acceleration = 35f;                     15     ///  16     /// 移动减速度 17     ///  18     public float deceleration = 8f;                         19     ///  20     /// 旋转速度 21     ///  22     public float rotateSpeed = 0.7f;                     23     ///  24     /// 速度极限 25     ///  26     public float speedLimit = 10f;                         27     ///  28     /// 玩家跳到敌人头上时应用到玩家身上的力 29     ///  30     public Vector3 bounceForce = new Vector3(0, 13, 0);     31     ///  32     /// 玩家跳到敌人头上时的声音 33     ///  34     public AudioClip bounceSound;                         35     ///  36     /// 玩家碰到敌人时受到的推力 37     ///  38     public float pushForce = 10f;                        39     ///  40     /// 玩家碰到敌人时玩家的高度 41     ///  42     public float pushHeight = 7f;                        43     ///  44     /// 敌人对玩家的伤害 45     ///  46     public int attackDmg = 1;                             47     ///  48     /// 是否追逐视野内的目标 49     ///  50     public bool chase = true;                            51     ///  52     /// 追逐时是否忽略y轴 53     ///  54     public bool ignoreY = true;                             55     ///  56     /// 追逐停止的距离 57     ///  58     public float chaseStopDistance = 0.7f;                 59     ///  60     /// 视野范围 61     ///  62     public GameObject sightBounds;                         63     ///  64     /// 攻击范围 65     ///  66     public GameObject attackBounds;                         67     ///  68     /// Animator 69     ///  70     public Animator animatorController;                     71     ///  72     /// 移动到路标点 73     ///  74     public MoveToPoints moveToPointsScript;                                           75      76     ///  77     /// 视野触发器 78     ///  79     private TriggerParent sightTrigger; 80     ///  81     /// 攻击触发器 82     ///  83     private TriggerParent attackTrigger; 84     ///  85     ///  玩家移动 86     ///  87     private PlayerMove playerMove; 88     ///  89     /// 角色移动 90     ///  91     private CharacterMotor characterMotor; 92     ///  93     /// 处理伤害 94     ///  95     private DealDamage dealDamage; 96      97      98     void Awake() 99     {        100         characterMotor = GetComponent
();101 dealDamage = GetComponent
();102 if(tag != "Enemy")103 {104 tag = "Enemy";105 Debug.LogWarning("'EnemyAI' script attached to object without 'Enemy' tag, it has been assign automatically", transform);106 }107 108 if(sightBounds)109 {110 sightTrigger = sightBounds.GetComponent
();111 if(!sightTrigger)112 Debug.LogError("'TriggerParent' script needs attaching to enemy 'SightBounds'", sightBounds);113 }114 if(!sightBounds)115 Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'SightBounds' or enemy will not be able to see", transform);116 117 if(attackBounds)118 {119 attackTrigger = attackBounds.GetComponent
();120 if(!attackTrigger)121 Debug.LogError("'TriggerParent' script needs attaching to enemy 'attackBounds'", attackBounds);122 }123 else124 Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'AttackBounds' or enemy will not be able to attack", transform);125 }126 127 void Update()128 {129 //追逐130 if (sightTrigger && sightTrigger.colliding && chase && sightTrigger.hitObject != null && sightTrigger.hitObject.activeInHierarchy)131 {132 characterMotor.MoveTo (sightTrigger.hitObject.transform.position, acceleration, chaseStopDistance, ignoreY);133 134 if(animatorController)135 animatorController.SetBool("Moving", true);136 137 if(moveToPointsScript)138 moveToPointsScript.enabled = false;139 }140 else141 { 142 143 if(animatorController)144 animatorController.SetBool("Moving", false);145 146 if(moveToPointsScript)147 moveToPointsScript.enabled = true;148 }149 150 //攻击151 if (attackTrigger && attackTrigger.collided)152 {153 dealDamage.Attack(attackTrigger.hitObject, attackDmg, pushHeight, pushForce);154 155 if(animatorController)156 animatorController.SetBool("Attacking", true); 157 }158 else if(animatorController)159 animatorController.SetBool("Attacking", false);160 }161 162 void FixedUpdate()163 {164 characterMotor.ManageSpeed(deceleration, speedLimit, ignoreY);165 characterMotor.RotateToVelocity (rotateSpeed, ignoreY);166 }167 168 ///
169 /// 弹开玩家170 /// 171 public void BouncedOn()172 { 173 if(!playerMove)174 playerMove = GameObject.FindGameObjectWithTag("Player").GetComponent
();175 if (bounceSound)176 AudioSource.PlayClipAtPoint(bounceSound, transform.position);177 if(playerMove)178 {179 Vector3 bounceMultiplier = new Vector3(0f, 1.5f, 0f) * playerMove.onEnemyBounce;180 playerMove.Jump (bounceForce + bounceMultiplier);181 }182 else183 Debug.LogWarning("'Player' tagged object landed on enemy, but without playerMove script attached, is unable to bounce");184 }185 }
EnemyAI
1 using UnityEngine; 2  3 ///  4 /// 关卡目标 5 ///  6 [RequireComponent(typeof(CapsuleCollider))] 7 public class Goal : MonoBehaviour  8 { 9     /// 10     /// 举起玩家的力11     /// 12     public float lift;            13     /// 14     /// 加载下一个关卡的等待时间15     /// 16     public float loadDelay;        17     /// 18     /// 下一个场景的索引19     /// 20     public int nextLevelIndex;                                                                21     22     /// 23     /// 计时器24     /// 25     private float counter;26     27     void Awake()28     {29         GetComponent
().isTrigger = true;30 }31 32 33 void OnTriggerStay(Collider other)34 {35 Rigidbody rigid = other.GetComponent
();36 if(rigid)37 rigid.AddForce(Vector3.up * lift, ForceMode.Force);38 39 if (other.tag == "Player")40 {41 counter += Time.deltaTime;42 if(counter > loadDelay)43 Application.LoadLevel (nextLevelIndex);44 }45 }46 47 void OnTriggerExit(Collider other)48 {49 if (other.tag == "Player")50 counter = 0f;51 }52 }
Goal
1 using UnityEngine; 2 using System.Collections; 3  4 ///  5 /// GUI 6 ///  7 public class GUIManager : MonoBehaviour  8 {     9     /// 10     /// GUISkin11     /// 12     public GUISkin guiSkin;13     /// 14     /// 已收集的金币15     /// 16     [HideInInspector]17     public int coinsCollected;18     /// 19     /// 场景中的金币数量20     /// 21     private int coinsInLevel;22     /// 23     /// 生命24     /// 25     private Health health;26     27     void Start()28     {29         coinsInLevel = GameObject.FindGameObjectsWithTag("Coin").Length;        30         health = GameObject.FindGameObjectWithTag("Player").GetComponent
();31 }32 33 void OnGUI()34 {35 GUI.skin = guiSkin;36 GUILayout.Space(5f);37 38 if(health)39 GUILayout.Label ("Health: " + health.currentHealth);40 if(coinsInLevel > 0)41 GUILayout.Label ("Cubes: " + coinsCollected + " / " + coinsInLevel);42 }43 }
GUIManager
1 using UnityEngine; 2 using System.Collections; 3  4 ///  5 /// 障碍 6 ///  7 [RequireComponent(typeof(DealDamage))] 8 [RequireComponent(typeof(AudioSource))] 9 public class Hazard : MonoBehaviour 10 {11     /// 12     /// 推开受害者的力13     /// 14     public float pushForce = 25f;                            15     /// 16     /// 向上推的力17     /// 18     public float pushHeight = 6f;                           19     /// 20     /// 照成的伤害21     /// 22     public int damage = 1;                                  23     /// 24     /// 是否是触发25     /// 26     public bool triggerEnter;                               27     /// 28     /// 是否是碰撞29     /// 30     public bool collisionEnter = true;                                    31     /// 32     /// 影响的单位的标签33     /// 34     public string[] effectedTags = {
"Player"}; 35 /// 36 /// 碰撞声音37 /// 38 public AudioClip hitSound; 39 40 /// 41 /// 处理伤害42 /// 43 private DealDamage dealDamage;44 /// 45 /// AudioSource46 /// 47 private AudioSource aSource;48 49 //setup50 void Awake()51 {52 aSource = GetComponent
();53 aSource.playOnAwake = false;54 dealDamage = GetComponent
();55 }56 57 void OnCollisionEnter(Collision col)58 {59 //不是碰撞60 if(!collisionEnter)61 return;62 //遍历检查标签63 foreach(string tag in effectedTags)64 //标签相等65 if(col.transform.tag == tag)66 {67 //处理伤害68 dealDamage.Attack (col.gameObject, damage, pushHeight, pushForce);69 //播放声音70 if (hitSound)71 {72 aSource.clip = hitSound;73 aSource.Play();74 }75 }76 }77 78 void OnTriggerEnter(Collider other)79 {80 //不是触发器81 if(!triggerEnter)82 return;83 //遍历标签84 foreach(string tag in effectedTags)85 //标签相等86 if(other.transform.tag == tag)87 //处理伤害88 dealDamage.Attack (other.gameObject, damage, pushHeight, pushForce);89 }90 }
Hazard
1 using UnityEngine;  2 using System.Collections;  3   4 ///   5 /// 生命  6 ///   7 [RequireComponent(typeof(AudioSource))]  8 public class Health : MonoBehaviour   9 { 10     ///  11     /// 撞击声音 12     ///  13     public AudioClip impactSound;                     14     ///  15     /// 受到伤害时的声音 16     ///  17     public AudioClip hurtSound;                         18     ///  19     /// 死亡声音 20     ///  21     public AudioClip deadSound;                         22     ///  23     /// 当前生命 24     ///  25     public int currentHealth = 1;                     26     ///  27     /// 是否能受到撞击伤害 28     ///  29     public bool takeImpactDmg;                         30     ///  31     /// 是否只能受到刚体伤害 32     ///  33     public bool onlyRigidbodyImpact;                 34     ///  35     /// 是否可以重生 36     ///  37     public bool respawn;                             38     ///  39     /// 不会受到撞击伤害的标签 40     ///  41     public string[] impactFilterTag;                 42     ///  43     /// 受到伤害时的闪烁延迟 44     ///  45     public float hitFlashDelay = 0.1f;                 46     ///  47     /// 闪烁持续时间 48     ///  49     public float flashDuration = 0.9f;                 50     ///  51     /// 受到伤害时的闪烁颜色 52     ///  53     public Color hitFlashColor = Color.red;             54     ///  55     /// 闪烁的物体 56     ///  57     public Transform flashObject;                     58     ///  59     ///  60     ///  61     public GameObject[] spawnOnDeath;                 62      63     ///  64     /// 是否死亡,是否闪烁 65     ///  66     [HideInInspector] 67     public bool dead, flashing; 68     ///  69     /// 重生位置 70     ///  71     [HideInInspector] 72     public Vector3 respawnPos; 73      74     ///  75     /// 原始颜色 76     ///  77     private Color originalColor; 78     ///  79     ///  80     ///  81     private int defHealth, h, hitForce; 82     private bool hitColor = false; 83     ///  84     /// 下一个闪烁,停止闪烁时间 85     ///  86     private float nextFlash, stopFlashTime; 87     ///  88     /// 扔物体 89     ///  90     private Throwing throwing; 91     ///  92     /// 闪烁渲染器 93     ///  94     private Renderer flashRender; 95     ///  96     /// AudioSource 97     ///  98     private AudioSource aSource; 99     100     void Awake()101     {102         aSource = GetComponent
();103 if(currentHealth <= 0)104 Debug.LogWarning(transform.name + " has 'currentHealth' set to 0 or less in 'Health' script: it has died upon scene start");105 aSource.playOnAwake = false;106 if(flashObject == null)107 flashObject = transform;108 flashRender = flashObject.GetComponent
();109 originalColor = flashRender.material.color;110 defHealth = currentHealth;111 respawnPos = transform.position;112 }113 114 115 void Update()116 { 117 //受到伤害,闪烁118 if (currentHealth < h)119 {120 flashing = true;121 stopFlashTime = Time.time + flashDuration;122 if (hurtSound)123 AudioSource.PlayClipAtPoint(hurtSound, transform.position);124 }125 h = currentHealth;126 127 if (flashing)128 {129 Flash ();130 if (Time.time > stopFlashTime)131 {132 flashRender.material.color = originalColor;133 flashing = false;134 }135 }136 137 dead = (currentHealth <= 0) ? true : false;138 if (dead)139 Death();140 }141 142 ///
143 /// 闪烁144 /// 145 void Flash()146 {147 flashRender.material.color = (hitColor) ? hitFlashColor : originalColor;148 if(Time.time > nextFlash)149 {150 hitColor = !hitColor;151 nextFlash = Time.time + hitFlashDelay;152 }153 }154 155 ///
156 /// 死亡157 /// 158 void Death()159 {160 161 if(tag == "Player")162 throwing = GetComponent
();163 if(throwing && throwing.heldObj && throwing.heldObj.tag == "Pickup")164 throwing.ThrowPickup();165 166 if (deadSound)167 AudioSource.PlayClipAtPoint(deadSound, transform.position);168 flashing = false;169 flashObject.GetComponent
().material.color = originalColor;170 if(respawn)171 {172 Rigidbody rigid = GetComponent
();173 if(rigid)174 rigid.velocity *= 0;175 transform.position = respawnPos;176 dead = false;177 currentHealth = defHealth;178 }179 else180 Destroy (gameObject);181 182 if (spawnOnDeath.Length != 0)183 foreach(GameObject obj in spawnOnDeath)184 Instantiate(obj, transform.position, Quaternion.Euler(Vector3.zero));185 }186 187 void OnCollisionEnter(Collision col)188 {189 //播放撞击声音190 if(!aSource.isPlaying && impactSound)191 {192 aSource.clip = impactSound;193 aSource.volume = col.relativeVelocity.magnitude/30;194 aSource.Play();195 }196 197 //不会受到撞击伤害,返回198 if (!takeImpactDmg)199 return;200 //找到标签,返回201 foreach(string tag in impactFilterTag) 202 if(col.transform.tag == tag)203 return;204 //只能受到刚体撞击且没有刚体,返回205 if(onlyRigidbodyImpact && !col.rigidbody)206 return;207 208 //计算受到的伤害209 if(col.rigidbody)210 hitForce = (int)(col.rigidbody.velocity.magnitude/4 * col.rigidbody.mass);211 else212 hitForce = (int)col.relativeVelocity.magnitude/6;213 currentHealth -= hitForce;214 //print (transform.name + " took: " + hitForce + " dmg in collision with " + col.transform.name);215 }216 }
Health
1 using UnityEngine;  2 using System.Collections;  3 using System.Collections.Generic;  4   5 ///   6 /// 移动到指定的点  7 ///   8 [RequireComponent(typeof(Rigidbody))]  9 public class MoveToPoints:MonoBehaviour { 10     ///  11     /// 移动速度 12     ///  13     public float speed;                                         14     ///  15     /// 延迟 16     ///  17     public float delay;                                         18     ///  19     /// 移动类型 20     ///  21     public type movementType;                                22  23     ///  24     /// 移动类型 25     ///  26     public enum type { 27         ///  28         /// 在最后一个路标停止 29         ///  30         PlayOnce, 31         ///  32         /// 转圈 33         ///  34         Loop, 35         ///  36         /// 来回 37         ///  38         PingPong 39     } 40     ///  41     /// 当前路标索引 42     ///  43     private int currentWp; 44     ///  45     /// 到达时间 46     ///  47     private float arrivalTime; 48     ///  49     /// 是否向前,是否到达 50     ///  51     private bool forward = true, arrived = false; 52     ///  53     /// 路标列表 54     ///  55     private List
waypoints = new List
(); 56 ///
57 /// 角色移动 58 /// 59 private CharacterMotor characterMotor; 60 ///
61 /// 敌人AI 62 /// 63 private EnemyAI enemyAI; 64 ///
65 /// 刚体 66 /// 67 private Rigidbody rigid; 68 69 void Awake() { 70 //标签不是Enemy 71 if(transform.tag != "Enemy") { 72 //没有刚体,添加刚体 73 if(!GetComponent
()) 74 gameObject.AddComponent
(); 75 //动力学 76 GetComponent
().isKinematic = true; 77 //不使用重力 78 GetComponent
().useGravity = false; 79 //修改插值类型 80 GetComponent
().interpolation = RigidbodyInterpolation.Interpolate; 81 } else { 82 //角色移动 83 characterMotor = GetComponent
(); 84 //获取敌人AI 85 enemyAI = GetComponent
(); 86 } 87 //获取刚体 88 rigid = GetComponent
(); 89 //遍历子物体 90 foreach(Transform child in transform) 91 //添加路标 92 if(child.tag == "Waypoint") 93 waypoints.Add(child); 94 //分离路标 95 foreach(Transform waypoint in waypoints) 96 waypoint.parent = null; 97 98 if(waypoints.Count == 0) 99 Debug.LogError("No waypoints found for 'MoveToPoints' script. To add waypoints: add child gameObjects with the tag 'Waypoint'",transform);100 }101 102 103 void Update() {104 //路标数量大于0105 if(waypoints.Count > 0) {106 //没有到达107 if(!arrived) {108 //与下一个路标的距离小于0.3109 if(Vector3.Distance(transform.position,waypoints[currentWp].position) < 0.3f) {110 //设置到达时间111 arrivalTime = Time.time;112 //修改到达标志位113 arrived = true;114 }115 //到达116 } else {117 //当前时间大于到达时间加延迟118 if(Time.time > arrivalTime + delay) {119 //获取下一个路标120 GetNextWP();121 //修改到达标志位122 arrived = false;123 }124 }125 }126 //标签是Enemy,路标数量大于0127 if(transform.tag == "Enemy" && waypoints.Count > 0) {128 //没有到达位置129 if(!arrived) {130 //玩家移动到指定路标131 characterMotor.MoveTo(waypoints[currentWp].position,enemyAI.acceleration,0.1f,enemyAI.ignoreY);132 //播放动画133 if(enemyAI.animatorController)134 enemyAI.animatorController.SetBool("Moving",true);135 //到达位置136 } else137 //播放动画138 if(enemyAI.animatorController)139 enemyAI.animatorController.SetBool("Moving",false);140 }141 }142 143 void FixedUpdate() {144 //标签为Enemy145 if(transform.tag != "Enemy") {146 //没有到达且路标数量大于0147 if(!arrived && waypoints.Count > 0) {148 //计算和路标的距离149 Vector3 direction = waypoints[currentWp].position - transform.position;150 //刚体移动151 rigid.MovePosition(transform.position + (direction.normalized * speed * Time.fixedDeltaTime));152 }153 }154 }155 156 ///
157 /// 获取下一个路标158 /// 159 private void GetNextWP() {160 //一次161 if(movementType == type.PlayOnce) {162 currentWp++;163 if(currentWp == waypoints.Count)164 enabled = false;165 }166 //循环167 if(movementType == type.Loop)168 currentWp = (currentWp == waypoints.Count - 1) ? 0 : currentWp += 1;169 //来回170 if(movementType == type.PingPong) {171 if(currentWp == waypoints.Count - 1)172 forward = false;173 else if(currentWp == 0)174 forward = true;175 currentWp = (forward) ? currentWp += 1 : currentWp -= 1;176 }177 }178 179 180 void OnDrawGizmos() {181 Gizmos.color = Color.cyan;182 foreach(Transform child in transform) {183 if(child.tag == "Waypoint")184 Gizmos.DrawSphere(child.position,.7f);185 }186 }187 }
MoveToPoints
1 using UnityEngine;  2 using System.Collections;  3   4 ///   5 /// 玩家移动  6 ///   7 [RequireComponent(typeof(CharacterMotor))]  8 [RequireComponent(typeof(DealDamage))]  9 [RequireComponent(typeof(AudioSource))] 10 [RequireComponent(typeof(Rigidbody))] 11 public class PlayerMove:MonoBehaviour { 12     ///  13     /// 是否是卷轴模式 14     ///  15     public bool sidescroller; 16     ///  17     /// 主相机,FloorChecks游戏物体Transform 18     ///  19     public Transform mainCam, floorChecks; 20     ///  21     /// Animator 22     ///  23     public Animator animator; 24     ///  25     /// 跳跃声音 26     ///  27     public AudioClip jumpSound; 28     ///  29     /// 着陆声音 30     ///  31     public AudioClip landSound; 32  33     ///  34     /// 加速度 35     ///  36     public float accel = 70f; 37     ///                                                                                       38     /// 空中加速度 39     ///  40     public float airAccel = 18f; 41     ///  42     /// 减速度 43     ///      44     public float decel = 7.6f; 45     ///  46     /// 空中减速度 47     ///  48     public float airDecel = 1.1f; 49     ///  50     /// 旋转速度,空中旋转速度 51     ///  52     [Range(0f,5f)] 53     public float rotateSpeed = 0.7f, airRotateSpeed = 0.4f; 54     ///  55     /// 最高移动速度 56     ///  57     public float maxSpeed = 9; 58     ///  59     /// 最大坡度,最大滑坡速度 60     ///  61     public float slopeLimit = 40, slideAmount = 35; 62     ///  63     /// 移动平台的摩擦力 64     ///  65     public float movingPlatformFriction = 7.7f; 66  67     ///  68     /// 常规跳跃力 69     ///  70     public Vector3 jumpForce = new Vector3(0,13,0); 71     ///  72     /// 2连跳力 73     ///  74     public Vector3 secondJumpForce = new Vector3(0,13,0); 75     ///  76     /// 3连跳力 77     ///  78     public Vector3 thirdJumpForce = new Vector3(0,13,0); 79     ///  80     /// 两次跳跃间的延迟 81     ///  82     public float jumpDelay = 0.1f; 83     ///  84     /// 着陆前仍然可以按下跳跃的时间 85     ///  86     public float jumpLeniancy = 0.17f; 87     [HideInInspector] 88     public int onEnemyBounce; 89     ///  90     /// 跳跃类型 91     ///  92     private int onJump; 93     ///  94     /// 是否着陆 95     ///  96     private bool grounded; 97     ///  98     /// 检查是否着陆的Transform列表(玩家身体的下面9个点) 99     /// 100     private Transform[] floorCheckers;101     /// 102     /// 103     /// 104     private Quaternion screenMovementSpace;105     /// 106     /// 按下跳跃的时间,着陆后的时间,当前加速度,当前减速度,当前旋转速度,斜率107     /// 108     private float airPressTime, groundedCount, curAccel, curDecel, curRotateSpeed, slope;109     /// 110     /// 方向,移动方向,屏幕向前移动,屏幕向右移动,移动物体的速度111     /// 112     private Vector3 direction, moveDirection, screenMovementForward, screenMovementRight, movingObjSpeed;113 114     /// 115     /// 角色移动116     /// 117     private CharacterMotor characterMotor;118     /// 119     /// 敌人AI120     /// 121     private EnemyAI enemyAI;122     /// 123     /// 处理伤害124     /// 125     private DealDamage dealDamage;126     /// 127     /// Rigidbody128     /// 129     private Rigidbody rigid;130     /// 131     /// AudioSource132     /// 133     private AudioSource aSource;134 135 136     void Awake() {137         //没有检查列表138         if(!floorChecks) {139             //添加140             floorChecks = new GameObject().transform;141             floorChecks.name = "FloorChecks";142             floorChecks.parent = transform;143             floorChecks.position = transform.position;144             //添加单个子物体145             GameObject check = new GameObject();146             check.name = "Check1";147             check.transform.parent = floorChecks;148             check.transform.position = transform.position;149             Debug.LogWarning("No 'floorChecks' assigned to PlayerMove script, so a single floorcheck has been created",floorChecks);150         }151         //标签不是Player152         if(tag != "Player") {153             //标签改为Player154             tag = "Player";155             Debug.LogWarning("PlayerMove script assigned to object without the tag 'Player', tag has been assigned automatically",transform);156         }157 158         //获取主摄像机159         mainCam = GameObject.FindGameObjectWithTag("MainCamera").transform;160         //获取处理伤害161         dealDamage = GetComponent
();162 //获取角色移动163 characterMotor = GetComponent
();164 //获取刚体165 rigid = GetComponent
();166 //获取AudioSource167 aSource = GetComponent
();168 169 //设置检查列表170 floorCheckers = new Transform[floorChecks.childCount];171 for(int i = 0;i < floorCheckers.Length;i++)172 floorCheckers[i] = floorChecks.GetChild(i);173 }174 175 void Update() {176 //激活刚体177 rigid.WakeUp();178 //计算跳跃179 JumpCalculations();180 181 //根据玩家是否着地设置当前加速度182 curAccel = (grounded) ? accel : airAccel;183 //根据玩家是否着地设置当前减速度184 curDecel = (grounded) ? decel : airDecel;185 //根据玩家是否着地设置当前旋转速度186 curRotateSpeed = (grounded) ? rotateSpeed : airRotateSpeed;187 188 screenMovementSpace = Quaternion.Euler(0,mainCam.eulerAngles.y,0);189 screenMovementForward = screenMovementSpace * Vector3.forward;190 screenMovementRight = screenMovementSpace * Vector3.right;191 192 193 float h = Input.GetAxisRaw("Horizontal");194 float v = Input.GetAxisRaw("Vertical");195 196 //不是卷轴模式197 if(!sidescroller)198 direction = (screenMovementForward * v) + (screenMovementRight * h);199 //是卷轴模式200 else201 //方向等于水平轴的输入*Vector3.right202 direction = Vector3.right * h;203 //移动方向等于当前位置加方向204 moveDirection = transform.position + direction;205 }206 207 void FixedUpdate() {208 //检查是否着地209 grounded = IsGrounded();210 //角色移动211 characterMotor.MoveTo(moveDirection,curAccel,0.7f,true);212 //旋转角色213 if(rotateSpeed != 0 && direction.magnitude != 0)214 characterMotor.RotateToDirection(moveDirection,curRotateSpeed * 5,true);215 //管理角色速度216 characterMotor.ManageSpeed(curDecel,maxSpeed + movingObjSpeed.magnitude,true);217 //播放动画218 if(animator) {219 animator.SetFloat("DistanceToTarget",characterMotor.DistanceToTarget);220 animator.SetBool("Grounded",grounded);221 animator.SetFloat("YVelocity",GetComponent
().velocity.y);222 }223 }224 225 void OnCollisionStay(Collision other) {226 if(other.collider.tag != "Untagged" || grounded == false)227 return;228 //在小坡度上停止下滑229 if(direction.magnitude == 0 && slope < slopeLimit && rigid.velocity.magnitude < 2) {230 rigid.velocity = Vector3.zero;231 }232 }233 234 ///
235 /// 检查是否着陆236 /// 237 private bool IsGrounded() {238 //计算距离239 float dist = GetComponent
().bounds.extents.y;240 241 //遍历所有检查点242 foreach(Transform check in floorCheckers) {243 RaycastHit hit;244 //向下发射射线245 if(Physics.Raycast(check.position,Vector3.down,out hit,dist + 0.05f)) {246 //如果不是触发器247 if(!hit.transform.GetComponent
().isTrigger) {248 //计算斜率249 slope = Vector3.Angle(hit.normal,Vector3.up);250 //斜率大于最大斜率,不是Pushable251 if(slope > slopeLimit && hit.transform.tag != "Pushable") {252 //计算滑动方向253 Vector3 slide = new Vector3(0f,-slideAmount,0f);254 //刚体施加滑动力255 rigid.AddForce(slide,ForceMode.Force);256 }257 //碰到敌人,y轴速度小于0258 if(hit.transform.tag == "Enemy" && rigid.velocity.y < 0) {259 //获取敌人AI260 enemyAI = hit.transform.GetComponent
();261 //弹开玩家262 enemyAI.BouncedOn();263 //264 onEnemyBounce++;265 //处理伤害266 dealDamage.Attack(hit.transform.gameObject,1,0f,0f);267 } else268 //269 onEnemyBounce = 0;270 //移动平台或Pushable271 if(hit.transform.tag == "MovingPlatform" || hit.transform.tag == "Pushable") {272 //移动物体的速度为刚体的速度273 movingObjSpeed = hit.transform.GetComponent
().velocity;274 //移动物体的y轴速度为0275 movingObjSpeed.y = 0f;276 //根据移动物体的速度和摩檫力给玩家刚体添加力277 rigid.AddForce(movingObjSpeed * movingPlatformFriction * Time.fixedDeltaTime,ForceMode.VelocityChange);278 } else {279 //移动物体的速度归0280 movingObjSpeed = Vector3.zero;281 }282 return true;283 }284 }285 }286 //移动物体的速度归0287 movingObjSpeed = Vector3.zero;288 return false;289 }290 291 ///
292 /// 计算跳跃293 /// 294 private void JumpCalculations() {295 //保存着陆后的时间296 groundedCount = (grounded) ? groundedCount += Time.deltaTime : 0f;297 298 //着陆时间小于0.25并且不等于0,正在播放声音,y轴的速度小于1299 if(groundedCount < 0.25 && groundedCount != 0 && !GetComponent
().isPlaying && landSound && GetComponent
().velocity.y < 1) {300 //根据y轴的速度修改音量301 aSource.volume = Mathf.Abs(GetComponent
().velocity.y) / 40;302 //修改声音303 aSource.clip = landSound;304 //播放声音305 aSource.Play();306 }307 //按下jump且没有着陆308 if(Input.GetButtonDown("Jump") && !grounded)309 //修改按下跳跃的时间为当前时间310 airPressTime = Time.time;311 312 //着陆,斜率小于最大斜率313 if(grounded && slope < slopeLimit) {314 //按下Jump315 if(Input.GetButtonDown("Jump") || airPressTime + jumpLeniancy > Time.time) {316 //切换跳跃类型317 onJump = (groundedCount < jumpDelay) ? Mathf.Min(2,onJump + 1) : 0;318 319 if(onJump == 0)320 Jump(jumpForce);321 else if(onJump == 1)322 Jump(secondJumpForce);323 else if(onJump == 2) {324 Jump(thirdJumpForce);325 onJump--;326 }327 }328 }329 }330 331 ///
332 /// 跳跃333 /// 334 public void Jump(Vector3 jumpVelocity) {335 //播放跳跃声音336 if(jumpSound) {337 aSource.volume = 1;338 aSource.clip = jumpSound;339 aSource.Play();340 }341 //改变刚体的y轴速度342 rigid.velocity = new Vector3(rigid.velocity.x,0f,rigid.velocity.z);343 //给刚体添加力344 rigid.AddRelativeForce(jumpVelocity,ForceMode.Impulse);345 //重置按下跳跃的时间346 airPressTime = 0f;347 }348 }
PlayerMove
1 using UnityEngine;  2 using System.Collections;  3   4   5 ///   6 /// 让玩家拾取,扔,推物体  7 ///   8 [RequireComponent(typeof(AudioSource))]  9 [RequireComponent(typeof(Rigidbody))] 10 [RequireComponent(typeof(PlayerMove))] 11 public class Throwing : MonoBehaviour  12 { 13     ///  14     /// 拾取声音 15     ///  16     public AudioClip pickUpSound;                                 17     ///  18     /// 扔声音 19     ///  20     public AudioClip throwSound;                                          21     ///  22     /// 用来抓物体的子游戏物体 23     ///  24     public GameObject grabBox;                                     25     ///  26     /// 举起物体的偏移 27     ///  28     public Vector3 holdOffset;                                     29     ///  30     /// 扔的力 31     ///  32     public Vector3 throwForce = new Vector3(0, 5, 7);             33     ///  34     /// 转向物体的速度 35     ///  36     public float rotateToBlockSpeed = 3;                         37     ///  38     /// 检查玩家头部的范围 39     ///  40     public float checkRadius = 0.5f;                             41     ///  42     /// 拾取物体的重量 43     ///  44     [Range(0.1f, 1f)]                                             45     public float weightChange = 0.3f; 46     ///  47     /// 未用 48     ///                      49     [Range(10f, 1000f)] 50     public float holdingBreakForce = 45, holdingBreakTorque = 45; 51     ///  52     /// Animator 53     ///  54     public Animator animator;                                     55     ///  56     /// 手臂动画层 57     ///  58     public int armsAnimationLayer;                                 59      60     ///  61     /// 举起或抓住的物体 62     ///  63     [HideInInspector] 64     public GameObject heldObj; 65     ///  66     /// 举起物体的位置 67     ///  68     private Vector3 holdPos; 69     ///  70     /// 连接物体和角色的关节 71     ///  72     private FixedJoint joint; 73     ///  74     /// 举起物体的时间,扔物体的时间,默认旋转速度 75     ///  76     private float timeOfPickup, timeOfThrow, defRotateSpeed; 77     ///  78     /// gizmo颜色 79     ///  80     private Color gizmoColor; 81     ///  82     /// AudioSource 83     ///  84     private AudioSource aSource; 85     ///  86     /// 玩家移动 87     ///  88     private PlayerMove playerMove; 89     ///  90     /// 父物体下的子物体的触发器 91     ///  92     private TriggerParent triggerParent; 93     ///  94     /// 默认刚体插值类型 95     ///  96     private RigidbodyInterpolation objectDefInterpolation; 97      98      99 100     void Awake()101     {102         //获取AudioSource103         aSource = GetComponent
();104 //没有抓物体的子物体105 if(!grabBox)106 {107 //新建108 grabBox = new GameObject();109 //添加碰撞器110 grabBox.AddComponent
();111 //设置为触发器112 grabBox.GetComponent
().isTrigger = true;113 //设置玩家为父物体114 grabBox.transform.parent = transform;115 //修改局部坐标116 grabBox.transform.localPosition = new Vector3(0f, 0f, 0.5f);117 //修改层(Ignore Raycast)118 grabBox.layer = 2;119 Debug.LogWarning("No grabBox object assigned to 'Throwing' script, one has been created and assigned for you", grabBox);120 }121 //获取玩家移动脚本122 playerMove = GetComponent
();123 //设置默认旋转速度124 defRotateSpeed = playerMove.rotateSpeed;125 //Animator不为空126 if(animator)127 //设置手臂动画层的权重128 animator.SetLayerWeight(armsAnimationLayer, 1);129 }130 131 void Update()132 {133 //按下Grab键,有举起或抓住的物体,当前时间比举起物体的时间大0.1f134 if (Input.GetButtonDown ("Grab") && heldObj && Time.time > timeOfPickup + 0.1f)135 {136 //举起物体的标签为"Pickup"137 if(heldObj.tag == "Pickup")138 //扔掉举起的物体 139 ThrowPickup();140 }141 //有Animator142 if(animator)143 //有举起的物体且物体标签为"Pickup"144 if(heldObj && heldObj.tag == "Pickup")145 animator.SetBool ("HoldingPickup", true);146 else147 animator.SetBool ("HoldingPickup", false);148 //有抓住的物体且物体标签为"Pushable"149 if(heldObj && heldObj.tag == "Pushable")150 animator.SetBool ("HoldingPushable", true);151 else152 animator.SetBool ("HoldingPushable", false);153 154 //有抓住的物体且物体标签为"Pushable"155 if (heldObj && heldObj.tag == "Pushable")156 {157 //按下Grab158 if(Input.GetButtonUp ("Grab"))159 {160 //丢弃物体161 DropPushable();162 }163 //没有关节164 if(!joint)165 {166 //丢弃物体167 DropPushable();168 print ("'Pushable' object dropped because the 'holdingBreakForce' or 'holdingBreakTorque' was exceeded");169 }170 }171 }172 173 void OnTriggerStay(Collider other)174 {175 //按下Grab176 if(Input.GetButton("Grab"))177 {178 //标签为"Pickup",没有举起的物体,当前时间大于扔物体的时间加0.2179 if(other.tag == "Pickup" && heldObj == null && timeOfThrow + 0.2f < Time.time)180 //举起物体181 LiftPickup(other);182 //标签为"Pushable",没有抓住的物体,当前时间大于扔物体的时间加0.2183 if(other.tag == "Pushable" && heldObj == null && timeOfThrow + 0.2f < Time.time)184 //抓物体185 GrabPushable(other);186 }187 }188 189 ///
190 /// 抓住物体191 /// 192 private void GrabPushable(Collider other)193 {194 //抓住的物体为碰撞的物体195 heldObj = other.gameObject;196 //获取物体的插值类型197 objectDefInterpolation = heldObj.GetComponent
().interpolation;198 //修改物体的插值为内插值199 heldObj.GetComponent
().interpolation = RigidbodyInterpolation.Interpolate;200 //添加关节,连接玩家和物体201 AddJoint ();202 //设置破坏关节的力为无限203 joint.breakForce = Mathf.Infinity;204 //设置破坏关节的扭矩力为无限205 joint.breakTorque = Mathf.Infinity;206 //设置玩家移动的旋转速度为0207 playerMove.rotateSpeed = 0;208 }209 210 ///
211 /// 举起物体212 /// 213 private void LiftPickup(Collider other)214 {215 //获取物体的网格216 Mesh otherMesh = other.GetComponent
().mesh;217 //计算举起的位置218 holdPos = transform.position + transform.forward * holdOffset.z + transform.right * holdOffset.x + transform.up * holdOffset.y;219 //举起的位置的y值加碰撞器的范围的y值加碰撞物体网格的范围的y值220 holdPos.y += (GetComponent
().bounds.extents.y) + (otherMesh.bounds.extents.y);221 222 //检测举起位置的圆形范围223 if(!Physics.CheckSphere(holdPos,checkRadius)) {224 //修改gizmo颜色225 gizmoColor = Color.green;226 //缓存举起的物体227 heldObj = other.gameObject;228 //修改默认插值类型229 objectDefInterpolation = heldObj.GetComponent
().interpolation;230 //修改举起物体的插值类型231 heldObj.GetComponent
().interpolation = RigidbodyInterpolation.Interpolate;232 //修改举起物体的位置233 heldObj.transform.position = holdPos;234 //修改举起物体的旋转235 heldObj.transform.rotation = transform.rotation;236 //添加关节,连接物体和玩家237 AddJoint();238 //修改举起物体的质量239 heldObj.GetComponent
().mass *= weightChange;240 //修改举起物体的时间为当前时间241 timeOfPickup = Time.time;242 } else {243 //修改gizmo颜色244 gizmoColor = Color.red;245 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," +246 "the CheckSphere function, in order to make sure it isn't detecting something above the players head that is invisible");247 }248 }249 250 ///
251 /// 放下物体252 /// 253 private void DropPushable()254 {255 //修改抓住物体的插值类型256 heldObj.GetComponent
().interpolation = objectDefInterpolation;257 //销毁关节258 Destroy (joint);259 //修改玩家移动的旋转速度为默认旋转速度260 playerMove.rotateSpeed = defRotateSpeed;261 heldObj = null;262 timeOfThrow = Time.time;263 }264 265 ///
266 /// 扔掉物体267 /// 268 public void ThrowPickup()269 {270 //播放扔物体声音271 if(throwSound)272 {273 aSource.volume = 1;274 aSource.clip = throwSound;275 aSource.Play ();276 }277 //删除关节278 Destroy (joint);279 //获取举起物体的刚体280 Rigidbody r = heldObj.GetComponent
();281 //恢复物体的插值类型282 r.interpolation = objectDefInterpolation;283 //恢复物体的质量284 r.mass /= weightChange;285 //给刚体添加力286 r.AddRelativeForce (throwForce, ForceMode.VelocityChange);287 288 heldObj = null;289 timeOfThrow = Time.time;290 }291 292 ///
293 /// 添加关节,连接玩家和物体294 /// 295 private void AddJoint()296 {297 //如果有物体298 if (heldObj)299 {300 //播放拾取声音301 if(pickUpSound)302 {303 aSource.volume = 1;304 aSource.clip = pickUpSound;305 aSource.Play ();306 }307 //在物体上添加关节308 joint = heldObj.AddComponent
();309 //设置关节的连接物体为玩家的刚体310 joint.connectedBody = GetComponent
();311 }312 }313 314 void OnDrawGizmosSelected()315 {316 Gizmos.color = gizmoColor;317 Gizmos.DrawSphere (holdPos, checkRadius);318 }319 }
Throwing
1 using UnityEngine; 2 using System.Collections; 3  4 ///  5 /// 父物体下的子物体的触发器 6 ///  7 public class TriggerParent:MonoBehaviour { 8  9     /// 10     /// 要检查的标签列表11     /// 12     public string[] tagsToCheck;            13 14     /// 15     /// 是否发生了碰撞,是否在碰撞中16     /// 17     [HideInInspector]18     public bool collided, colliding;19     /// 20     /// 撞击的物体21     /// 22     [HideInInspector]23     public GameObject hitObject;24 25     void Awake() {26         //没有Collider或有Collider但不是触发器27         if(!GetComponent
() || (GetComponent
() && !GetComponent
().isTrigger))28 Debug.LogError("'TriggerParent' script attached to object which does not have a trigger collider",transform);29 }30 31 void OnTriggerEnter(Collider other) {32 //标签列表长度大于0且没有碰撞过33 if(tagsToCheck.Length > 0 && !collided) {34 //遍历标签35 foreach(string tag in tagsToCheck) {36 //找到标签37 if(other.tag == tag) {38 //已发生碰撞39 collided = true;40 //存储碰撞物体41 hitObject = other.gameObject;42 break;43 }44 45 }46 } else47 //已发生碰撞48 collided = true;49 //存储碰撞物体50 hitObject = other.gameObject;51 }52 53 void OnTriggerStay(Collider other) {54 //标签列表长度大于055 if(tagsToCheck.Length > 0) {56 //遍历标签57 foreach(string tag in tagsToCheck) {58 //找到标签59 if(other.tag == tag) {60 //正在碰撞61 colliding = true;62 //存储碰撞物体63 hitObject = other.gameObject;64 break;65 }66 }67 } else {68 //存储碰撞物体69 hitObject = other.gameObject;70 //正在碰撞71 colliding = true;72 }73 }74 75 void OnTriggerExit(Collider other) {76 //标签列表长度大于077 if(tagsToCheck.Length > 0) {78 //遍历标签79 foreach(string tag in tagsToCheck) {80 //找到标签81 if(other.tag == tag) {82 colliding = false;83 hitObject = null;84 break;85 }86 }87 } else88 return;89 }90 91 void LateUpdate() {92 //重置collided,hitObject93 if(collided) {94 collided = false;95 hitObject = null;96 }97 }98 }
TriggerParent
1 using UnityEngine;  2 using System.Collections;  3 using System.Collections.Generic;  4   5 ///   6 /// 水  7 ///   8 [RequireComponent(typeof(BoxCollider))]  9 public class Water:MonoBehaviour { 10     ///  11     /// 玩家进水的声音 12     ///  13     public AudioClip splashSound; 14     ///  15     /// 水的推力 16     ///  17     public Vector3 force = new Vector3(0,16.5f,0); 18     ///  19     /// 玩家是否会受到水的阻力影响 20     ///  21     public bool effectPlayerDrag; 22     ///  23     /// 刚体受到的水的阻力(不包含玩家) 24     ///  25     public float resistance = 0.4f;                      26     ///  27     /// 刚体受到的角阻力(不包含玩家) 28     ///  29     public float angularResistance = 0.2f;                 30  31     ///  32     /// 刚体受到的阻力字典 33     ///  34     private Dictionary
dragStore = new Dictionary
(); 35 ///
36 /// 刚体受到的角阻力字典 37 /// 38 private Dictionary
angularStore = new Dictionary
(); 39 40 void Awake() { 41 //自动修改"Water"标签 42 if(tag != "Water") { 43 tag = "Water"; 44 Debug.LogWarning("'Water' script attached to an object not tagged 'Water', it been assigned the tag 'Water'",transform); 45 } 46 //设置Trigger 47 GetComponent
().isTrigger = true; 48 } 49 50 void OnTriggerEnter(Collider other) { 51 //获取物体的刚体 52 Rigidbody r = other.GetComponent
(); 53 //刚体不为空 54 if(r) { 55 //播放入水声音 56 if(splashSound) { 57 float volume = other.GetComponent
().velocity.magnitude / 5; 58 AudioSource.PlayClipAtPoint(splashSound,other.transform.position,volume); 59 } 60 61 //是玩家且不受水的阻力影响 62 if(r.tag == "Player" && !effectPlayerDrag) 63 return; 64 65 //存储受到的阻力 66 dragStore.Add(r.gameObject,r.drag); 67 //存储受到的角阻力 68 angularStore.Add(r.gameObject,r.angularDrag); 69 70 //修改刚体受到的阻力 71 r.drag = resistance; 72 //修改刚体受到的角阻力 73 r.angularDrag = angularResistance; 74 } else if(splashSound) 75 //播放入水声音 76 AudioSource.PlayClipAtPoint(splashSound,other.transform.position); 77 } 78 79 80 81 void OnTriggerStay(Collider other) { 82 //计算表面高度 83 float surface = transform.position.y + GetComponent
().bounds.extents.y; 84 Rigidbody rigid = other.GetComponent
(); 85 if(rigid) { 86 //计算物体相对于表面高度的深度 87 float depth = surface - other.transform.position.y; 88 //深度大于0.4 89 if(depth > 0.4f) 90 //用一个较小的力往上推刚体 91 rigid.AddForce(force,ForceMode.Force); 92 //深度小于等于0.4 93 else 94 //用一个较大的力往上推刚体 95 rigid.AddForce(force * (depth * 2),ForceMode.Force); 96 } 97 } 98 99 void OnTriggerExit(Collider other) {100 //获取物体的刚体101 Rigidbody r = other.GetComponent
();102 //有刚体103 if(r) {104 //是玩家且不受阻力水的阻力影响105 if(r.tag == "Player" && !effectPlayerDrag)106 return;107 108 //阻力和角阻力字典包含刚体的游戏物体109 if(dragStore.ContainsKey(r.gameObject) && angularStore.ContainsKey(r.gameObject)) {110 //恢复阻力111 r.drag = dragStore[r.gameObject];112 //恢复角阻力113 r.angularDrag = angularStore[r.gameObject];114 //移除阻力115 dragStore.Remove(r.gameObject);116 //移除角阻力117 angularStore.Remove(r.gameObject);118 } else {119 //重置阻力120 r.drag = 0f;121 //重置角阻力122 r.angularDrag = 0.05f;123 print("Object left water: couldn't get drag values, restored to defaults");124 }125 }126 }127 }
Water

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

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

转载于:https://www.cnblogs.com/revoid/p/6592344.html

你可能感兴趣的文章
Floyd算法
查看>>
CentOS 6.4下安装Oracle 11gR2
查看>>
linux建立用户 详细
查看>>
jquery获取radio的值
查看>>
创建索引
查看>>
jQuery基础-创建HTML
查看>>
spring boot 热部署
查看>>
NYOJ-214 单调递增子序列(二) AC 分类: NYOJ ...
查看>>
[HDU 4417]Super Mario
查看>>
clip-path的妙用
查看>>
在FMOD中使用customRollOff实现更自然的声音衰减
查看>>
java日常-map转成json
查看>>
动画view
查看>>
自己写个多任务多线程断点下载框架
查看>>
Css 按钮
查看>>
Silverlight显示WCF详细异常信息
查看>>
BZOJ5299:[CQOI2018]解锁屏幕(状压DP)
查看>>
BZOJ1042:[HAOI2008]硬币购物(DP,容斥)
查看>>
[项目管理]关于项目的工期控制
查看>>
hdu3976(Electric resistance) 高斯消元
查看>>