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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 }
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 Listwaypoints = 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 }
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 }
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 }
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 }
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 DictionarydragStore = new Dictionary (); 35 /// 36 /// 刚体受到的角阻力字典 37 /// 38 private DictionaryangularStore = 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 }
视频:https://pan.baidu.com/s/1mhF7hmo
项目:https://pan.baidu.com/s/1pL6nMTP