Complete Physics Platformer Kit 学习
- using UnityEngine;
- /// <summary>
- /// 摄像机跟随玩家
- /// </summary>
- public class CameraFollow : MonoBehaviour
- {
- /// <summary>
- /// 目标
- /// </summary>
- public Transform target;
- /// <summary>
- /// 和目标之间的偏移
- /// </summary>
- );
- /// <summary>
- /// 是否锁定旋转
- /// </summary>
- public bool lockRotation;
- /// <summary>
- /// 跟随速度
- /// </summary>
- ;
- /// <summary>
- /// 围绕目标旋转的速度
- /// </summary>
- ;
- /// <summary>
- /// 是否可以由鼠标控制旋转(只有在相机没有被固定的情况下)
- /// </summary>
- public bool mouseFreelook;
- /// <summary>
- /// 旋转阻尼
- /// </summary>
- ;
- /// <summary>
- /// 摄像机在水中时的过滤物体
- /// </summary>
- public GameObject waterFilter;
- /// <summary>
- ///
- /// </summary>
- public string[] avoidClippingTags;
- /// <summary>
- /// Camera Target
- /// </summary>
- private Transform followTarget;
- /// <summary>
- /// 暂未用到
- /// </summary>
- private bool camColliding;
- //setup objects
- void Awake()
- {
- //创建跟随物体(Camera Target)
- followTarget = new GameObject().transform;
- followTarget.name = "Camera Target";
- if(waterFilter)
- waterFilter.GetComponent<Renderer>().enabled = false;
- if(!target)
- Debug.LogError("'CameraFollow script' has no target assigned to it", transform);
- //如果用鼠标控制旋转,旋转阻尼为0
- if(mouseFreelook)
- rotateDamping = 0f;
- }
- void Update()
- {
- //没有目标不处理
- if (!target)
- return;
- //平滑跟随
- SmoothFollow ();
- //平滑朝向玩家
- )
- SmoothLookAt();
- //直接朝向玩家
- else
- transform.LookAt(target.position);
- }
- void OnTriggerEnter(Collider other)
- {
- //打开水遮罩
- if (other.tag == "Water" && waterFilter)
- waterFilter.GetComponent<Renderer>().enabled = true;
- }
- void OnTriggerExit(Collider other)
- {
- //关闭水遮罩
- if (other.tag == "Water" && waterFilter)
- waterFilter.GetComponent<Renderer>().enabled = false;
- }
- /// <summary>
- /// 平滑朝向目标
- /// </summary>
- void SmoothLookAt()
- {
- Quaternion rotation = Quaternion.LookRotation (target.position - transform.position);
- transform.rotation = Quaternion.Slerp (transform.rotation, rotation, rotateDamping * Time.deltaTime);
- }
- /// <summary>
- /// 平滑跟随目标
- /// </summary>
- void SmoothFollow()
- {
- followTarget.position = target.position;
- followTarget.Translate(targetOffset, Space.Self);
- if (lockRotation)
- followTarget.rotation = target.rotation;
- //鼠标控制围绕目标旋转
- if(mouseFreelook)
- {
- float axisX = Input.GetAxis ("Mouse X") * inputRotationSpeed * Time.deltaTime;
- followTarget.RotateAround (target.position,Vector3.up, axisX);
- float axisY = Input.GetAxis ("Mouse Y") * inputRotationSpeed * Time.deltaTime;
- followTarget.RotateAround (target.position, transform.right, -axisY);
- }
- //键盘控制围绕目标旋转
- else
- {
- float axis = Input.GetAxis ("CamHorizontal") * inputRotationSpeed * Time.deltaTime;
- followTarget.RotateAround (target.position, Vector3.up, axis);
- }
- //计算相机的下一帧位置
- Vector3 nextFramePosition = Vector3.Lerp(transform.position, followTarget.position, followSpeed * Time.deltaTime);
- Vector3 direction = nextFramePosition - target.position;
- //射线检测这个位置
- RaycastHit hit;
- if(Physics.Raycast (target.position, direction, out hit, direction.magnitude + 0.3f))
- {
- transform.position = nextFramePosition;
- foreach(string tag in avoidClippingTags)
- //如果这个位置有物体,修改相机位置
- if(hit.transform.tag == tag)
- transform.position = hit.point - direction.normalized * 0.3f;
- }
- else
- {
- //直接修改相机位置
- transform.position = nextFramePosition;
- }
- }
- }
CameraFollow
- using UnityEngine;
- /// <summary>
- /// 角色移动
- /// </summary>
- [RequireComponent(typeof(Rigidbody))]
- public class CharacterMotor:MonoBehaviour {
- /// <summary>
- /// 是否冻结z轴的移动
- /// </summary>
- public bool sidescroller;
- /// <summary>
- /// 当前速度
- /// </summary>
- [HideInInspector]
- public Vector3 currentSpeed;
- /// <summary>
- /// 到目标的距离
- /// </summary>
- [HideInInspector]
- public float DistanceToTarget;
- /// <summary>
- /// 刚体
- /// </summary>
- private Rigidbody rigid;
- void Awake() {
- //设置rigidbody
- rigid = GetComponent<Rigidbody>();
- rigid.interpolation = RigidbodyInterpolation.Interpolate;
- if(sidescroller)
- rigid.constraints = RigidbodyConstraints.FreezeRotation | RigidbodyConstraints.FreezePositionZ;
- else
- rigid.constraints = RigidbodyConstraints.FreezeRotation;
- //添加光滑的物理材质
- if(GetComponent<Collider>().material.name == "Default (Instance)") {
- PhysicMaterial pMat = new PhysicMaterial();
- pMat.name = "Frictionless";
- pMat.frictionCombine = PhysicMaterialCombine.Multiply;
- pMat.bounceCombine = PhysicMaterialCombine.Multiply;
- pMat.dynamicFriction = 0f;
- pMat.staticFriction = 0f;
- GetComponent<Collider>().material = pMat;
- Debug.LogWarning("No physics material found for CharacterMotor, a frictionless one has been created and assigned",transform);
- }
- }
- /// <summary>
- /// 移动刚体到指定位置
- /// </summary>
- public bool MoveTo(Vector3 destination,float acceleration,float stopDistance,bool ignoreY) {
- Vector3 relativePos = (destination - transform.position);
- //忽略y轴?
- if(ignoreY)
- relativePos.y = ;
- DistanceToTarget = relativePos.magnitude;
- if(DistanceToTarget <= stopDistance)
- return true;
- else
- rigid.AddForce(relativePos.normalized * acceleration * Time.deltaTime,ForceMode.VelocityChange);
- return false;
- }
- /// <summary>
- /// 旋转刚体朝向当前速度
- /// </summary>
- public void RotateToVelocity(float turnSpeed,bool ignoreY) {
- Vector3 dir;
- if(ignoreY)
- dir = new Vector3(rigid.velocity.x,0f,rigid.velocity.z);
- else
- dir = rigid.velocity;
- if(dir.magnitude > 0.1) {
- Quaternion dirQ = Quaternion.LookRotation(dir);
- Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,dir.magnitude * turnSpeed * Time.deltaTime);
- rigid.MoveRotation(slerp);
- }
- }
- /// <summary>
- /// 旋转刚体朝向指定方向
- /// </summary>
- public void RotateToDirection(Vector3 lookDir,float turnSpeed,bool ignoreY) {
- Vector3 characterPos = transform.position;
- //忽略y轴?
- if(ignoreY) {
- characterPos.y = ;
- lookDir.y = ;
- }
- Vector3 newDir = lookDir - characterPos;
- Quaternion dirQ = Quaternion.LookRotation(newDir);
- Quaternion slerp = Quaternion.Slerp(transform.rotation,dirQ,turnSpeed * Time.deltaTime);
- rigid.MoveRotation(slerp);
- }
- /// <summary>
- /// 管理速度
- /// </summary>
- public void ManageSpeed(float deceleration,float maxSpeed,bool ignoreY) {
- currentSpeed = rigid.velocity;
- //忽略y轴
- if(ignoreY)
- currentSpeed.y = ;
- ) {
- rigid.AddForce((currentSpeed * -) * deceleration * Time.deltaTime,ForceMode.VelocityChange);
- if(rigid.velocity.magnitude > maxSpeed)
- rigid.AddForce((currentSpeed * -) * deceleration * Time.deltaTime,ForceMode.VelocityChange);
- }
- }
- }
CharacterMotor
- using UnityEngine;
- /// <summary>
- /// 检查点
- /// </summary>
- [RequireComponent(typeof(CapsuleCollider))]
- [RequireComponent(typeof(AudioSource))]
- public class Checkpoint : MonoBehaviour
- {
- /// <summary>
- /// 激活颜色
- /// </summary>
- public Color activeColor = Color.green;
- /// <summary>
- /// 激活时的不透明度
- /// </summary>
- public float activeColorOpacity = 0.4f;
- /// <summary>
- /// 生命
- /// </summary>
- private Health health;
- /// <summary>
- /// 默认颜色
- /// </summary>
- private Color defColor;
- /// <summary>
- /// 检查点列表
- /// </summary>
- private GameObject[] checkpoints;
- /// <summary>
- /// 渲染器
- /// </summary>
- private Renderer render;
- /// <summary>
- /// AudioSource
- /// </summary>
- private AudioSource aSource;
- void Awake()
- {
- render = GetComponent<Renderer>();
- aSource = GetComponent<AudioSource>();
- //标签不是Respawn,自动修改标签
- if(tag != "Respawn")
- {
- tag = "Respawn";
- Debug.LogWarning ("'Checkpoint' script attached to object without the 'Respawn' tag, tag has been assigned automatically", transform);
- }
- GetComponent<Collider>().isTrigger = true;
- //设置默认颜色和不透明度
- if(render)
- defColor = render.material.color;
- activeColor.a = activeColorOpacity;
- }
- void Start()
- {
- checkpoints = GameObject.FindGameObjectsWithTag("Respawn");
- health = GameObject.FindGameObjectWithTag("Player").GetComponent<Health>();
- if(!health)
- Debug.LogError("For Checkpoint to work, the Player needs 'Health' script attached", transform);
- }
- void OnTriggerEnter(Collider other)
- {
- //如果碰到玩家
- if(other.transform.tag == "Player" && health)
- {
- health.respawnPos = transform.position;
- if(render.material.color != activeColor)
- {
- foreach (GameObject checkpoint in checkpoints)
- checkpoint.GetComponent<Renderer>().material.color = defColor;
- aSource.Play();
- render.material.color = activeColor;
- }
- }
- }
- }
Checkpoint
- using UnityEngine;
- /// <summary>
- /// 金币
- /// </summary>
- [RequireComponent(typeof(SphereCollider))]
- public class Coin : MonoBehaviour
- {
- /// <summary>
- /// 被收集时的声音
- /// </summary>
- public AudioClip collectSound;
- /// <summary>
- /// 旋转
- /// </summary>
- , , );
- /// <summary>
- /// 玩家靠近时,增加的旋转
- /// </summary>
- , , );
- /// <summary>
- /// 金币向玩家移动的速度
- /// </summary>
- public float startSpeed = 3f;
- /// <summary>
- /// 金币向玩家移动的加速度
- /// </summary>
- public float speedGain = 0.2f;
- /// <summary>
- /// 是否被搜集
- /// </summary>
- private bool collected;
- /// <summary>
- /// 玩家
- /// </summary>
- private Transform player;
- /// <summary>
- /// 子物体的触发器
- /// </summary>
- private TriggerParent triggerParent;
- /// <summary>
- /// GUI
- /// </summary>
- private GUIManager gui;
- void Awake()
- {
- gui = FindObjectOfType(typeof(GUIManager)) as GUIManager ;
- if(tag != "Coin")
- {
- tag = "Coin";
- Debug.LogWarning ("'Coin' script attached to object not tagged 'Coin', tag added automatically", transform);
- }
- GetComponent<Collider>().isTrigger = true;
- triggerParent = GetComponentInChildren<TriggerParent>();
- //添加bounds子物体
- if(!triggerParent)
- {
- GameObject bounds = new GameObject();
- bounds.name = "Bounds";
- bounds.AddComponent<SphereCollider>();
- bounds.GetComponent<SphereCollider>().radius = 7f;
- bounds.GetComponent<SphereCollider>().isTrigger = true;
- bounds.transform.parent = transform;
- bounds.transform.position = transform.position;
- bounds.AddComponent<TriggerParent>();
- triggerParent = GetComponentInChildren<TriggerParent>();
- triggerParent.tagsToCheck = ];
- triggerParent.tagsToCheck[] = "Player";
- Debug.LogWarning ("No pickup radius 'bounds' trigger attached to coin: " + transform.name + ", one has been added automatically", bounds);
- }
- }
- void Start()
- {
- player = GameObject.FindGameObjectWithTag("Player").transform;
- }
- void Update()
- {
- transform.Rotate (rotation * Time.deltaTime, Space.World);
- if(triggerParent.collided)
- collected = true;
- //增加金币的旋转速度和移动速度,将金币移向玩家
- if (collected)
- {
- startSpeed += speedGain;
- rotation += rotationGain;
- transform.position = Vector3.Lerp (transform.position, player.position, startSpeed * Time.deltaTime);
- }
- }
- void OnTriggerEnter(Collider other)
- {
- if (other.tag == "Player")
- CoinGet();
- }
- /// <summary>
- /// 获取金币
- /// </summary>
- void CoinGet()
- {
- if(collectSound)
- AudioSource.PlayClipAtPoint(collectSound, transform.position);
- if (gui)
- gui.coinsCollected ++;
- Destroy(gameObject);
- }
- }
Coin
- using UnityEngine;
- /// <summary>
- /// 处理伤害
- /// </summary>
- public class DealDamage : MonoBehaviour
- {
- /// <summary>
- /// 受害人的生命
- /// </summary>
- private Health health;
- /// <summary>
- /// 攻击
- /// </summary>
- public void Attack(GameObject victim, int dmg, float pushHeight, float pushForce)
- {
- health = victim.GetComponent<Health>();
- //推物体
- Vector3 pushDir = (victim.transform.position - transform.position);
- pushDir.y = 0f;
- pushDir.y = pushHeight * 0.1f;
- if (victim.GetComponent<Rigidbody>() && !victim.GetComponent<Rigidbody>().isKinematic)
- {
- victim.GetComponent<Rigidbody>().velocity = , , );
- victim.GetComponent<Rigidbody>().AddForce (pushDir.normalized * pushForce, ForceMode.VelocityChange);
- victim.GetComponent<Rigidbody>().AddForce (Vector3.up * pushHeight, ForceMode.VelocityChange);
- }
- //应用伤害
- if(health && !health.flashing)
- health.currentHealth -= dmg;
- }
- }
DealDamage
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 摧毁物体
- /// </summary>
- public class DestroyObject : MonoBehaviour
- {
- /// <summary>
- /// 摧毁声音
- /// </summary>
- public AudioClip destroySound;
- /// <summary>
- /// 延迟
- /// </summary>
- public float delay;
- /// <summary>
- /// 是否分离子物体并且不摧毁子物体
- /// </summary>
- public bool destroyChildren;
- /// <summary>
- /// 从父物体中心推开子物体的数量
- /// </summary>
- public float pushChildAmount;
- void Start()
- {
- //获取子物体列表
- Transform[] children = new Transform[transform.childCount];
- ; i < transform.childCount; i++)
- children[i] = transform.GetChild(i);
- //分离子物体
- if (!destroyChildren)
- transform.DetachChildren();
- //给子物体添加一个推力和旋转
- foreach (Transform child in children)
- {
- Rigidbody rigid = child.GetComponent<Rigidbody>();
- )
- {
- Vector3 pushDir = child.position - transform.position;
- rigid.AddForce(pushDir * pushChildAmount, ForceMode.Force);
- rigid.AddTorque(Random.insideUnitSphere, ForceMode.Force);
- }
- }
- //删除父物体
- if(destroySound)
- AudioSource.PlayClipAtPoint(destroySound, transform.position);
- Destroy (gameObject, delay);
- }
- }
DestroyObject
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 敌人AI
- /// </summary>
- [RequireComponent(typeof(CharacterMotor))]
- [RequireComponent(typeof(DealDamage))]
- public class EnemyAI : MonoBehaviour
- {
- /// <summary>
- /// 移动加速度
- /// </summary>
- public float acceleration = 35f;
- /// <summary>
- /// 移动减速度
- /// </summary>
- public float deceleration = 8f;
- /// <summary>
- /// 旋转速度
- /// </summary>
- public float rotateSpeed = 0.7f;
- /// <summary>
- /// 速度极限
- /// </summary>
- public float speedLimit = 10f;
- /// <summary>
- /// 玩家跳到敌人头上时应用到玩家身上的力
- /// </summary>
- , , );
- /// <summary>
- /// 玩家跳到敌人头上时的声音
- /// </summary>
- public AudioClip bounceSound;
- /// <summary>
- /// 玩家碰到敌人时受到的推力
- /// </summary>
- public float pushForce = 10f;
- /// <summary>
- /// 玩家碰到敌人时玩家的高度
- /// </summary>
- public float pushHeight = 7f;
- /// <summary>
- /// 敌人对玩家的伤害
- /// </summary>
- ;
- /// <summary>
- /// 是否追逐视野内的目标
- /// </summary>
- public bool chase = true;
- /// <summary>
- /// 追逐时是否忽略y轴
- /// </summary>
- public bool ignoreY = true;
- /// <summary>
- /// 追逐停止的距离
- /// </summary>
- public float chaseStopDistance = 0.7f;
- /// <summary>
- /// 视野范围
- /// </summary>
- public GameObject sightBounds;
- /// <summary>
- /// 攻击范围
- /// </summary>
- public GameObject attackBounds;
- /// <summary>
- /// Animator
- /// </summary>
- public Animator animatorController;
- /// <summary>
- /// 移动到路标点
- /// </summary>
- public MoveToPoints moveToPointsScript;
- /// <summary>
- /// 视野触发器
- /// </summary>
- private TriggerParent sightTrigger;
- /// <summary>
- /// 攻击触发器
- /// </summary>
- private TriggerParent attackTrigger;
- /// <summary>
- /// 玩家移动
- /// </summary>
- private PlayerMove playerMove;
- /// <summary>
- /// 角色移动
- /// </summary>
- private CharacterMotor characterMotor;
- /// <summary>
- /// 处理伤害
- /// </summary>
- private DealDamage dealDamage;
- void Awake()
- {
- characterMotor = GetComponent<CharacterMotor>();
- dealDamage = GetComponent<DealDamage>();
- if(tag != "Enemy")
- {
- tag = "Enemy";
- Debug.LogWarning("'EnemyAI' script attached to object without 'Enemy' tag, it has been assign automatically", transform);
- }
- if(sightBounds)
- {
- sightTrigger = sightBounds.GetComponent<TriggerParent>();
- if(!sightTrigger)
- Debug.LogError("'TriggerParent' script needs attaching to enemy 'SightBounds'", sightBounds);
- }
- if(!sightBounds)
- Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'SightBounds' or enemy will not be able to see", transform);
- if(attackBounds)
- {
- attackTrigger = attackBounds.GetComponent<TriggerParent>();
- if(!attackTrigger)
- Debug.LogError("'TriggerParent' script needs attaching to enemy 'attackBounds'", attackBounds);
- }
- else
- Debug.LogWarning("Assign a trigger with 'TriggerParent' script attached, to 'AttackBounds' or enemy will not be able to attack", transform);
- }
- void Update()
- {
- //追逐
- if (sightTrigger && sightTrigger.colliding && chase && sightTrigger.hitObject != null && sightTrigger.hitObject.activeInHierarchy)
- {
- characterMotor.MoveTo (sightTrigger.hitObject.transform.position, acceleration, chaseStopDistance, ignoreY);
- if(animatorController)
- animatorController.SetBool("Moving", true);
- if(moveToPointsScript)
- moveToPointsScript.enabled = false;
- }
- else
- {
- if(animatorController)
- animatorController.SetBool("Moving", false);
- if(moveToPointsScript)
- moveToPointsScript.enabled = true;
- }
- //攻击
- if (attackTrigger && attackTrigger.collided)
- {
- dealDamage.Attack(attackTrigger.hitObject, attackDmg, pushHeight, pushForce);
- if(animatorController)
- animatorController.SetBool("Attacking", true);
- }
- else if(animatorController)
- animatorController.SetBool("Attacking", false);
- }
- void FixedUpdate()
- {
- characterMotor.ManageSpeed(deceleration, speedLimit, ignoreY);
- characterMotor.RotateToVelocity (rotateSpeed, ignoreY);
- }
- /// <summary>
- /// 弹开玩家
- /// </summary>
- public void BouncedOn()
- {
- if(!playerMove)
- playerMove = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerMove>();
- if (bounceSound)
- AudioSource.PlayClipAtPoint(bounceSound, transform.position);
- if(playerMove)
- {
- Vector3 bounceMultiplier = new Vector3(0f, 1.5f, 0f) * playerMove.onEnemyBounce;
- playerMove.Jump (bounceForce + bounceMultiplier);
- }
- else
- Debug.LogWarning("'Player' tagged object landed on enemy, but without playerMove script attached, is unable to bounce");
- }
- }
EnemyAI
- using UnityEngine;
- /// <summary>
- /// 关卡目标
- /// </summary>
- [RequireComponent(typeof(CapsuleCollider))]
- public class Goal : MonoBehaviour
- {
- /// <summary>
- /// 举起玩家的力
- /// </summary>
- public float lift;
- /// <summary>
- /// 加载下一个关卡的等待时间
- /// </summary>
- public float loadDelay;
- /// <summary>
- /// 下一个场景的索引
- /// </summary>
- public int nextLevelIndex;
- /// <summary>
- /// 计时器
- /// </summary>
- private float counter;
- void Awake()
- {
- GetComponent<Collider>().isTrigger = true;
- }
- void OnTriggerStay(Collider other)
- {
- Rigidbody rigid = other.GetComponent<Rigidbody>();
- if(rigid)
- rigid.AddForce(Vector3.up * lift, ForceMode.Force);
- if (other.tag == "Player")
- {
- counter += Time.deltaTime;
- if(counter > loadDelay)
- Application.LoadLevel (nextLevelIndex);
- }
- }
- void OnTriggerExit(Collider other)
- {
- if (other.tag == "Player")
- counter = 0f;
- }
- }
Goal
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// GUI
- /// </summary>
- public class GUIManager : MonoBehaviour
- {
- /// <summary>
- /// GUISkin
- /// </summary>
- public GUISkin guiSkin;
- /// <summary>
- /// 已收集的金币
- /// </summary>
- [HideInInspector]
- public int coinsCollected;
- /// <summary>
- /// 场景中的金币数量
- /// </summary>
- private int coinsInLevel;
- /// <summary>
- /// 生命
- /// </summary>
- private Health health;
- void Start()
- {
- coinsInLevel = GameObject.FindGameObjectsWithTag("Coin").Length;
- health = GameObject.FindGameObjectWithTag("Player").GetComponent<Health>();
- }
- void OnGUI()
- {
- GUI.skin = guiSkin;
- GUILayout.Space(5f);
- if(health)
- GUILayout.Label ("Health: " + health.currentHealth);
- )
- GUILayout.Label ("Cubes: " + coinsCollected + " / " + coinsInLevel);
- }
- }
GUIManager
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 障碍
- /// </summary>
- [RequireComponent(typeof(DealDamage))]
- [RequireComponent(typeof(AudioSource))]
- public class Hazard : MonoBehaviour
- {
- /// <summary>
- /// 推开受害者的力
- /// </summary>
- public float pushForce = 25f;
- /// <summary>
- /// 向上推的力
- /// </summary>
- public float pushHeight = 6f;
- /// <summary>
- /// 照成的伤害
- /// </summary>
- ;
- /// <summary>
- /// 是否是触发
- /// </summary>
- public bool triggerEnter;
- /// <summary>
- /// 是否是碰撞
- /// </summary>
- public bool collisionEnter = true;
- /// <summary>
- /// 影响的单位的标签
- /// </summary>
- public string[] effectedTags = {"Player"};
- /// <summary>
- /// 碰撞声音
- /// </summary>
- public AudioClip hitSound;
- /// <summary>
- /// 处理伤害
- /// </summary>
- private DealDamage dealDamage;
- /// <summary>
- /// AudioSource
- /// </summary>
- private AudioSource aSource;
- //setup
- void Awake()
- {
- aSource = GetComponent<AudioSource>();
- aSource.playOnAwake = false;
- dealDamage = GetComponent<DealDamage>();
- }
- void OnCollisionEnter(Collision col)
- {
- //不是碰撞
- if(!collisionEnter)
- return;
- //遍历检查标签
- foreach(string tag in effectedTags)
- //标签相等
- if(col.transform.tag == tag)
- {
- //处理伤害
- dealDamage.Attack (col.gameObject, damage, pushHeight, pushForce);
- //播放声音
- if (hitSound)
- {
- aSource.clip = hitSound;
- aSource.Play();
- }
- }
- }
- void OnTriggerEnter(Collider other)
- {
- //不是触发器
- if(!triggerEnter)
- return;
- //遍历标签
- foreach(string tag in effectedTags)
- //标签相等
- if(other.transform.tag == tag)
- //处理伤害
- dealDamage.Attack (other.gameObject, damage, pushHeight, pushForce);
- }
- }
Hazard
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 生命
- /// </summary>
- [RequireComponent(typeof(AudioSource))]
- public class Health : MonoBehaviour
- {
- /// <summary>
- /// 撞击声音
- /// </summary>
- public AudioClip impactSound;
- /// <summary>
- /// 受到伤害时的声音
- /// </summary>
- public AudioClip hurtSound;
- /// <summary>
- /// 死亡声音
- /// </summary>
- public AudioClip deadSound;
- /// <summary>
- /// 当前生命
- /// </summary>
- ;
- /// <summary>
- /// 是否能受到撞击伤害
- /// </summary>
- public bool takeImpactDmg;
- /// <summary>
- /// 是否只能受到刚体伤害
- /// </summary>
- public bool onlyRigidbodyImpact;
- /// <summary>
- /// 是否可以重生
- /// </summary>
- public bool respawn;
- /// <summary>
- /// 不会受到撞击伤害的标签
- /// </summary>
- public string[] impactFilterTag;
- /// <summary>
- /// 受到伤害时的闪烁延迟
- /// </summary>
- public float hitFlashDelay = 0.1f;
- /// <summary>
- /// 闪烁持续时间
- /// </summary>
- public float flashDuration = 0.9f;
- /// <summary>
- /// 受到伤害时的闪烁颜色
- /// </summary>
- public Color hitFlashColor = Color.red;
- /// <summary>
- /// 闪烁的物体
- /// </summary>
- public Transform flashObject;
- /// <summary>
- ///
- /// </summary>
- public GameObject[] spawnOnDeath;
- /// <summary>
- /// 是否死亡,是否闪烁
- /// </summary>
- [HideInInspector]
- public bool dead, flashing;
- /// <summary>
- /// 重生位置
- /// </summary>
- [HideInInspector]
- public Vector3 respawnPos;
- /// <summary>
- /// 原始颜色
- /// </summary>
- private Color originalColor;
- /// <summary>
- ///
- /// </summary>
- private int defHealth, h, hitForce;
- private bool hitColor = false;
- /// <summary>
- /// 下一个闪烁,停止闪烁时间
- /// </summary>
- private float nextFlash, stopFlashTime;
- /// <summary>
- /// 扔物体
- /// </summary>
- private Throwing throwing;
- /// <summary>
- /// 闪烁渲染器
- /// </summary>
- private Renderer flashRender;
- /// <summary>
- /// AudioSource
- /// </summary>
- private AudioSource aSource;
- void Awake()
- {
- aSource = GetComponent<AudioSource>();
- )
- Debug.LogWarning(transform.name + " has 'currentHealth' set to 0 or less in 'Health' script: it has died upon scene start");
- aSource.playOnAwake = false;
- if(flashObject == null)
- flashObject = transform;
- flashRender = flashObject.GetComponent<Renderer>();
- originalColor = flashRender.material.color;
- defHealth = currentHealth;
- respawnPos = transform.position;
- }
- void Update()
- {
- //受到伤害,闪烁
- if (currentHealth < h)
- {
- flashing = true;
- stopFlashTime = Time.time + flashDuration;
- if (hurtSound)
- AudioSource.PlayClipAtPoint(hurtSound, transform.position);
- }
- h = currentHealth;
- if (flashing)
- {
- Flash ();
- if (Time.time > stopFlashTime)
- {
- flashRender.material.color = originalColor;
- flashing = false;
- }
- }
- dead = (currentHealth <= ) ? true : false;
- if (dead)
- Death();
- }
- /// <summary>
- /// 闪烁
- /// </summary>
- void Flash()
- {
- flashRender.material.color = (hitColor) ? hitFlashColor : originalColor;
- if(Time.time > nextFlash)
- {
- hitColor = !hitColor;
- nextFlash = Time.time + hitFlashDelay;
- }
- }
- /// <summary>
- /// 死亡
- /// </summary>
- void Death()
- {
- if(tag == "Player")
- throwing = GetComponent<Throwing>();
- if(throwing && throwing.heldObj && throwing.heldObj.tag == "Pickup")
- throwing.ThrowPickup();
- if (deadSound)
- AudioSource.PlayClipAtPoint(deadSound, transform.position);
- flashing = false;
- flashObject.GetComponent<Renderer>().material.color = originalColor;
- if(respawn)
- {
- Rigidbody rigid = GetComponent<Rigidbody>();
- if(rigid)
- rigid.velocity *= ;
- transform.position = respawnPos;
- dead = false;
- currentHealth = defHealth;
- }
- else
- Destroy (gameObject);
- )
- foreach(GameObject obj in spawnOnDeath)
- Instantiate(obj, transform.position, Quaternion.Euler(Vector3.zero));
- }
- void OnCollisionEnter(Collision col)
- {
- //播放撞击声音
- if(!aSource.isPlaying && impactSound)
- {
- aSource.clip = impactSound;
- aSource.volume = col.relativeVelocity.magnitude/;
- aSource.Play();
- }
- //不会受到撞击伤害,返回
- if (!takeImpactDmg)
- return;
- //找到标签,返回
- foreach(string tag in impactFilterTag)
- if(col.transform.tag == tag)
- return;
- //只能受到刚体撞击且没有刚体,返回
- if(onlyRigidbodyImpact && !col.rigidbody)
- return;
- //计算受到的伤害
- if(col.rigidbody)
- hitForce = ( * col.rigidbody.mass);
- else
- hitForce = (;
- currentHealth -= hitForce;
- //print (transform.name + " took: " + hitForce + " dmg in collision with " + col.transform.name);
- }
- }
Health
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- /// <summary>
- /// 移动到指定的点
- /// </summary>
- [RequireComponent(typeof(Rigidbody))]
- public class MoveToPoints:MonoBehaviour {
- /// <summary>
- /// 移动速度
- /// </summary>
- public float speed;
- /// <summary>
- /// 延迟
- /// </summary>
- public float delay;
- /// <summary>
- /// 移动类型
- /// </summary>
- public type movementType;
- /// <summary>
- /// 移动类型
- /// </summary>
- public enum type {
- /// <summary>
- /// 在最后一个路标停止
- /// </summary>
- PlayOnce,
- /// <summary>
- /// 转圈
- /// </summary>
- Loop,
- /// <summary>
- /// 来回
- /// </summary>
- PingPong
- }
- /// <summary>
- /// 当前路标索引
- /// </summary>
- private int currentWp;
- /// <summary>
- /// 到达时间
- /// </summary>
- private float arrivalTime;
- /// <summary>
- /// 是否向前,是否到达
- /// </summary>
- private bool forward = true, arrived = false;
- /// <summary>
- /// 路标列表
- /// </summary>
- private List<Transform> waypoints = new List<Transform>();
- /// <summary>
- /// 角色移动
- /// </summary>
- private CharacterMotor characterMotor;
- /// <summary>
- /// 敌人AI
- /// </summary>
- private EnemyAI enemyAI;
- /// <summary>
- /// 刚体
- /// </summary>
- private Rigidbody rigid;
- void Awake() {
- //标签不是Enemy
- if(transform.tag != "Enemy") {
- //没有刚体,添加刚体
- if(!GetComponent<Rigidbody>())
- gameObject.AddComponent<Rigidbody>();
- //动力学
- GetComponent<Rigidbody>().isKinematic = true;
- //不使用重力
- GetComponent<Rigidbody>().useGravity = false;
- //修改插值类型
- GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
- } else {
- //角色移动
- characterMotor = GetComponent<CharacterMotor>();
- //获取敌人AI
- enemyAI = GetComponent<EnemyAI>();
- }
- //获取刚体
- rigid = GetComponent<Rigidbody>();
- //遍历子物体
- foreach(Transform child in transform)
- //添加路标
- if(child.tag == "Waypoint")
- waypoints.Add(child);
- //分离路标
- foreach(Transform waypoint in waypoints)
- waypoint.parent = null;
- )
- Debug.LogError("No waypoints found for 'MoveToPoints' script. To add waypoints: add child gameObjects with the tag 'Waypoint'",transform);
- }
- void Update() {
- //路标数量大于0
- ) {
- //没有到达
- if(!arrived) {
- //与下一个路标的距离小于0.3
- if(Vector3.Distance(transform.position,waypoints[currentWp].position) < 0.3f) {
- //设置到达时间
- arrivalTime = Time.time;
- //修改到达标志位
- arrived = true;
- }
- //到达
- } else {
- //当前时间大于到达时间加延迟
- if(Time.time > arrivalTime + delay) {
- //获取下一个路标
- GetNextWP();
- //修改到达标志位
- arrived = false;
- }
- }
- }
- //标签是Enemy,路标数量大于0
- ) {
- //没有到达位置
- if(!arrived) {
- //玩家移动到指定路标
- characterMotor.MoveTo(waypoints[currentWp].position,enemyAI.acceleration,0.1f,enemyAI.ignoreY);
- //播放动画
- if(enemyAI.animatorController)
- enemyAI.animatorController.SetBool("Moving",true);
- //到达位置
- } else
- //播放动画
- if(enemyAI.animatorController)
- enemyAI.animatorController.SetBool("Moving",false);
- }
- }
- void FixedUpdate() {
- //标签为Enemy
- if(transform.tag != "Enemy") {
- //没有到达且路标数量大于0
- ) {
- //计算和路标的距离
- Vector3 direction = waypoints[currentWp].position - transform.position;
- //刚体移动
- rigid.MovePosition(transform.position + (direction.normalized * speed * Time.fixedDeltaTime));
- }
- }
- }
- /// <summary>
- /// 获取下一个路标
- /// </summary>
- private void GetNextWP() {
- //一次
- if(movementType == type.PlayOnce) {
- currentWp++;
- if(currentWp == waypoints.Count)
- enabled = false;
- }
- //循环
- if(movementType == type.Loop)
- currentWp = (currentWp == waypoints.Count - ) ? : currentWp += ;
- //来回
- if(movementType == type.PingPong) {
- )
- forward = false;
- )
- forward = true;
- currentWp = (forward) ? currentWp += : currentWp -= ;
- }
- }
- void OnDrawGizmos() {
- Gizmos.color = Color.cyan;
- foreach(Transform child in transform) {
- if(child.tag == "Waypoint")
- Gizmos.DrawSphere(child.position,.7f);
- }
- }
- }
MoveToPoints
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 玩家移动
- /// </summary>
- [RequireComponent(typeof(CharacterMotor))]
- [RequireComponent(typeof(DealDamage))]
- [RequireComponent(typeof(AudioSource))]
- [RequireComponent(typeof(Rigidbody))]
- public class PlayerMove:MonoBehaviour {
- /// <summary>
- /// 是否是卷轴模式
- /// </summary>
- public bool sidescroller;
- /// <summary>
- /// 主相机,FloorChecks游戏物体Transform
- /// </summary>
- public Transform mainCam, floorChecks;
- /// <summary>
- /// Animator
- /// </summary>
- public Animator animator;
- /// <summary>
- /// 跳跃声音
- /// </summary>
- public AudioClip jumpSound;
- /// <summary>
- /// 着陆声音
- /// </summary>
- public AudioClip landSound;
- /// <summary>
- /// 加速度
- /// </summary>
- public float accel = 70f;
- /// <summary>
- /// 空中加速度
- /// </summary>
- public float airAccel = 18f;
- /// <summary>
- /// 减速度
- /// </summary>
- public float decel = 7.6f;
- /// <summary>
- /// 空中减速度
- /// </summary>
- public float airDecel = 1.1f;
- /// <summary>
- /// 旋转速度,空中旋转速度
- /// </summary>
- [Range(0f,5f)]
- public float rotateSpeed = 0.7f, airRotateSpeed = 0.4f;
- /// <summary>
- /// 最高移动速度
- /// </summary>
- ;
- /// <summary>
- /// 最大坡度,最大滑坡速度
- /// </summary>
- , slideAmount = ;
- /// <summary>
- /// 移动平台的摩擦力
- /// </summary>
- public float movingPlatformFriction = 7.7f;
- /// <summary>
- /// 常规跳跃力
- /// </summary>
- ,,);
- /// <summary>
- /// 2连跳力
- /// </summary>
- ,,);
- /// <summary>
- /// 3连跳力
- /// </summary>
- ,,);
- /// <summary>
- /// 两次跳跃间的延迟
- /// </summary>
- public float jumpDelay = 0.1f;
- /// <summary>
- /// 着陆前仍然可以按下跳跃的时间
- /// </summary>
- public float jumpLeniancy = 0.17f;
- [HideInInspector]
- public int onEnemyBounce;
- /// <summary>
- /// 跳跃类型
- /// </summary>
- private int onJump;
- /// <summary>
- /// 是否着陆
- /// </summary>
- private bool grounded;
- /// <summary>
- /// 检查是否着陆的Transform列表(玩家身体的下面9个点)
- /// </summary>
- private Transform[] floorCheckers;
- /// <summary>
- ///
- /// </summary>
- private Quaternion screenMovementSpace;
- /// <summary>
- /// 按下跳跃的时间,着陆后的时间,当前加速度,当前减速度,当前旋转速度,斜率
- /// </summary>
- private float airPressTime, groundedCount, curAccel, curDecel, curRotateSpeed, slope;
- /// <summary>
- /// 方向,移动方向,屏幕向前移动,屏幕向右移动,移动物体的速度
- /// </summary>
- private Vector3 direction, moveDirection, screenMovementForward, screenMovementRight, movingObjSpeed;
- /// <summary>
- /// 角色移动
- /// </summary>
- private CharacterMotor characterMotor;
- /// <summary>
- /// 敌人AI
- /// </summary>
- private EnemyAI enemyAI;
- /// <summary>
- /// 处理伤害
- /// </summary>
- private DealDamage dealDamage;
- /// <summary>
- /// Rigidbody
- /// </summary>
- private Rigidbody rigid;
- /// <summary>
- /// AudioSource
- /// </summary>
- private AudioSource aSource;
- void Awake() {
- //没有检查列表
- if(!floorChecks) {
- //添加
- floorChecks = new GameObject().transform;
- floorChecks.name = "FloorChecks";
- floorChecks.parent = transform;
- floorChecks.position = transform.position;
- //添加单个子物体
- GameObject check = new GameObject();
- check.name = "Check1";
- check.transform.parent = floorChecks;
- check.transform.position = transform.position;
- Debug.LogWarning("No 'floorChecks' assigned to PlayerMove script, so a single floorcheck has been created",floorChecks);
- }
- //标签不是Player
- if(tag != "Player") {
- //标签改为Player
- tag = "Player";
- Debug.LogWarning("PlayerMove script assigned to object without the tag 'Player', tag has been assigned automatically",transform);
- }
- //获取主摄像机
- mainCam = GameObject.FindGameObjectWithTag("MainCamera").transform;
- //获取处理伤害
- dealDamage = GetComponent<DealDamage>();
- //获取角色移动
- characterMotor = GetComponent<CharacterMotor>();
- //获取刚体
- rigid = GetComponent<Rigidbody>();
- //获取AudioSource
- aSource = GetComponent<AudioSource>();
- //设置检查列表
- floorCheckers = new Transform[floorChecks.childCount];
- ;i < floorCheckers.Length;i++)
- floorCheckers[i] = floorChecks.GetChild(i);
- }
- void Update() {
- //激活刚体
- rigid.WakeUp();
- //计算跳跃
- JumpCalculations();
- //根据玩家是否着地设置当前加速度
- curAccel = (grounded) ? accel : airAccel;
- //根据玩家是否着地设置当前减速度
- curDecel = (grounded) ? decel : airDecel;
- //根据玩家是否着地设置当前旋转速度
- curRotateSpeed = (grounded) ? rotateSpeed : airRotateSpeed;
- screenMovementSpace = Quaternion.Euler(,mainCam.eulerAngles.y,);
- screenMovementForward = screenMovementSpace * Vector3.forward;
- screenMovementRight = screenMovementSpace * Vector3.right;
- float h = Input.GetAxisRaw("Horizontal");
- float v = Input.GetAxisRaw("Vertical");
- //不是卷轴模式
- if(!sidescroller)
- direction = (screenMovementForward * v) + (screenMovementRight * h);
- //是卷轴模式
- else
- //方向等于水平轴的输入*Vector3.right
- direction = Vector3.right * h;
- //移动方向等于当前位置加方向
- moveDirection = transform.position + direction;
- }
- void FixedUpdate() {
- //检查是否着地
- grounded = IsGrounded();
- //角色移动
- characterMotor.MoveTo(moveDirection,curAccel,0.7f,true);
- //旋转角色
- && direction.magnitude != )
- characterMotor.RotateToDirection(moveDirection,curRotateSpeed * ,true);
- //管理角色速度
- characterMotor.ManageSpeed(curDecel,maxSpeed + movingObjSpeed.magnitude,true);
- //播放动画
- if(animator) {
- animator.SetFloat("DistanceToTarget",characterMotor.DistanceToTarget);
- animator.SetBool("Grounded",grounded);
- animator.SetFloat("YVelocity",GetComponent<Rigidbody>().velocity.y);
- }
- }
- void OnCollisionStay(Collision other) {
- if(other.collider.tag != "Untagged" || grounded == false)
- return;
- //在小坡度上停止下滑
- && slope < slopeLimit && rigid.velocity.magnitude < ) {
- rigid.velocity = Vector3.zero;
- }
- }
- /// <summary>
- /// 检查是否着陆
- /// </summary>
- private bool IsGrounded() {
- //计算距离
- float dist = GetComponent<Collider>().bounds.extents.y;
- //遍历所有检查点
- foreach(Transform check in floorCheckers) {
- RaycastHit hit;
- //向下发射射线
- if(Physics.Raycast(check.position,Vector3.down,out hit,dist + 0.05f)) {
- //如果不是触发器
- if(!hit.transform.GetComponent<Collider>().isTrigger) {
- //计算斜率
- slope = Vector3.Angle(hit.normal,Vector3.up);
- //斜率大于最大斜率,不是Pushable
- if(slope > slopeLimit && hit.transform.tag != "Pushable") {
- //计算滑动方向
- Vector3 slide = new Vector3(0f,-slideAmount,0f);
- //刚体施加滑动力
- rigid.AddForce(slide,ForceMode.Force);
- }
- //碰到敌人,y轴速度小于0
- ) {
- //获取敌人AI
- enemyAI = hit.transform.GetComponent<EnemyAI>();
- //弹开玩家
- enemyAI.BouncedOn();
- //
- onEnemyBounce++;
- //处理伤害
- dealDamage.Attack(hit.transform.gameObject,,0f,0f);
- } else
- //
- onEnemyBounce = ;
- //移动平台或Pushable
- if(hit.transform.tag == "MovingPlatform" || hit.transform.tag == "Pushable") {
- //移动物体的速度为刚体的速度
- movingObjSpeed = hit.transform.GetComponent<Rigidbody>().velocity;
- //移动物体的y轴速度为0
- movingObjSpeed.y = 0f;
- //根据移动物体的速度和摩檫力给玩家刚体添加力
- rigid.AddForce(movingObjSpeed * movingPlatformFriction * Time.fixedDeltaTime,ForceMode.VelocityChange);
- } else {
- //移动物体的速度归0
- movingObjSpeed = Vector3.zero;
- }
- return true;
- }
- }
- }
- //移动物体的速度归0
- movingObjSpeed = Vector3.zero;
- return false;
- }
- /// <summary>
- /// 计算跳跃
- /// </summary>
- private void JumpCalculations() {
- //保存着陆后的时间
- groundedCount = (grounded) ? groundedCount += Time.deltaTime : 0f;
- //着陆时间小于0.25并且不等于0,正在播放声音,y轴的速度小于1
- && !GetComponent<AudioSource>().isPlaying && landSound && GetComponent<Rigidbody>().velocity.y < ) {
- //根据y轴的速度修改音量
- aSource.volume = Mathf.Abs(GetComponent<Rigidbody>().velocity.y) / ;
- //修改声音
- aSource.clip = landSound;
- //播放声音
- aSource.Play();
- }
- //按下jump且没有着陆
- if(Input.GetButtonDown("Jump") && !grounded)
- //修改按下跳跃的时间为当前时间
- airPressTime = Time.time;
- //着陆,斜率小于最大斜率
- if(grounded && slope < slopeLimit) {
- //按下Jump
- if(Input.GetButtonDown("Jump") || airPressTime + jumpLeniancy > Time.time) {
- //切换跳跃类型
- onJump = (groundedCount < jumpDelay) ? Mathf.Min(,onJump + ) : ;
- )
- Jump(jumpForce);
- )
- Jump(secondJumpForce);
- ) {
- Jump(thirdJumpForce);
- onJump--;
- }
- }
- }
- }
- /// <summary>
- /// 跳跃
- /// </summary>
- public void Jump(Vector3 jumpVelocity) {
- //播放跳跃声音
- if(jumpSound) {
- aSource.volume = ;
- aSource.clip = jumpSound;
- aSource.Play();
- }
- //改变刚体的y轴速度
- rigid.velocity = new Vector3(rigid.velocity.x,0f,rigid.velocity.z);
- //给刚体添加力
- rigid.AddRelativeForce(jumpVelocity,ForceMode.Impulse);
- //重置按下跳跃的时间
- airPressTime = 0f;
- }
- }
PlayerMove
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 让玩家拾取,扔,推物体
- /// </summary>
- [RequireComponent(typeof(AudioSource))]
- [RequireComponent(typeof(Rigidbody))]
- [RequireComponent(typeof(PlayerMove))]
- public class Throwing : MonoBehaviour
- {
- /// <summary>
- /// 拾取声音
- /// </summary>
- public AudioClip pickUpSound;
- /// <summary>
- /// 扔声音
- /// </summary>
- public AudioClip throwSound;
- /// <summary>
- /// 用来抓物体的子游戏物体
- /// </summary>
- public GameObject grabBox;
- /// <summary>
- /// 举起物体的偏移
- /// </summary>
- public Vector3 holdOffset;
- /// <summary>
- /// 扔的力
- /// </summary>
- , , );
- /// <summary>
- /// 转向物体的速度
- /// </summary>
- ;
- /// <summary>
- /// 检查玩家头部的范围
- /// </summary>
- public float checkRadius = 0.5f;
- /// <summary>
- /// 拾取物体的重量
- /// </summary>
- [Range(0.1f, 1f)]
- public float weightChange = 0.3f;
- /// <summary>
- /// 未用
- /// </summary>
- [Range(10f, 1000f)]
- , holdingBreakTorque = ;
- /// <summary>
- /// Animator
- /// </summary>
- public Animator animator;
- /// <summary>
- /// 手臂动画层
- /// </summary>
- public int armsAnimationLayer;
- /// <summary>
- /// 举起或抓住的物体
- /// </summary>
- [HideInInspector]
- public GameObject heldObj;
- /// <summary>
- /// 举起物体的位置
- /// </summary>
- private Vector3 holdPos;
- /// <summary>
- /// 连接物体和角色的关节
- /// </summary>
- private FixedJoint joint;
- /// <summary>
- /// 举起物体的时间,扔物体的时间,默认旋转速度
- /// </summary>
- private float timeOfPickup, timeOfThrow, defRotateSpeed;
- /// <summary>
- /// gizmo颜色
- /// </summary>
- private Color gizmoColor;
- /// <summary>
- /// AudioSource
- /// </summary>
- private AudioSource aSource;
- /// <summary>
- /// 玩家移动
- /// </summary>
- private PlayerMove playerMove;
- /// <summary>
- /// 父物体下的子物体的触发器
- /// </summary>
- private TriggerParent triggerParent;
- /// <summary>
- /// 默认刚体插值类型
- /// </summary>
- private RigidbodyInterpolation objectDefInterpolation;
- void Awake()
- {
- //获取AudioSource
- aSource = GetComponent<AudioSource>();
- //没有抓物体的子物体
- if(!grabBox)
- {
- //新建
- grabBox = new GameObject();
- //添加碰撞器
- grabBox.AddComponent<BoxCollider>();
- //设置为触发器
- grabBox.GetComponent<Collider>().isTrigger = true;
- //设置玩家为父物体
- grabBox.transform.parent = transform;
- //修改局部坐标
- grabBox.transform.localPosition = new Vector3(0f, 0f, 0.5f);
- //修改层(Ignore Raycast)
- grabBox.layer = ;
- Debug.LogWarning("No grabBox object assigned to 'Throwing' script, one has been created and assigned for you", grabBox);
- }
- //获取玩家移动脚本
- playerMove = GetComponent<PlayerMove>();
- //设置默认旋转速度
- defRotateSpeed = playerMove.rotateSpeed;
- //Animator不为空
- if(animator)
- //设置手臂动画层的权重
- animator.SetLayerWeight(armsAnimationLayer, );
- }
- void Update()
- {
- //按下Grab键,有举起或抓住的物体,当前时间比举起物体的时间大0.1f
- if (Input.GetButtonDown ("Grab") && heldObj && Time.time > timeOfPickup + 0.1f)
- {
- //举起物体的标签为"Pickup"
- if(heldObj.tag == "Pickup")
- //扔掉举起的物体
- ThrowPickup();
- }
- //有Animator
- if(animator)
- //有举起的物体且物体标签为"Pickup"
- if(heldObj && heldObj.tag == "Pickup")
- animator.SetBool ("HoldingPickup", true);
- else
- animator.SetBool ("HoldingPickup", false);
- //有抓住的物体且物体标签为"Pushable"
- if(heldObj && heldObj.tag == "Pushable")
- animator.SetBool ("HoldingPushable", true);
- else
- animator.SetBool ("HoldingPushable", false);
- //有抓住的物体且物体标签为"Pushable"
- if (heldObj && heldObj.tag == "Pushable")
- {
- //按下Grab
- if(Input.GetButtonUp ("Grab"))
- {
- //丢弃物体
- DropPushable();
- }
- //没有关节
- if(!joint)
- {
- //丢弃物体
- DropPushable();
- print ("'Pushable' object dropped because the 'holdingBreakForce' or 'holdingBreakTorque' was exceeded");
- }
- }
- }
- void OnTriggerStay(Collider other)
- {
- //按下Grab
- if(Input.GetButton("Grab"))
- {
- //标签为"Pickup",没有举起的物体,当前时间大于扔物体的时间加0.2
- if(other.tag == "Pickup" && heldObj == null && timeOfThrow + 0.2f < Time.time)
- //举起物体
- LiftPickup(other);
- //标签为"Pushable",没有抓住的物体,当前时间大于扔物体的时间加0.2
- if(other.tag == "Pushable" && heldObj == null && timeOfThrow + 0.2f < Time.time)
- //抓物体
- GrabPushable(other);
- }
- }
- /// <summary>
- /// 抓住物体
- /// </summary>
- private void GrabPushable(Collider other)
- {
- //抓住的物体为碰撞的物体
- heldObj = other.gameObject;
- //获取物体的插值类型
- objectDefInterpolation = heldObj.GetComponent<Rigidbody>().interpolation;
- //修改物体的插值为内插值
- heldObj.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
- //添加关节,连接玩家和物体
- AddJoint ();
- //设置破坏关节的力为无限
- joint.breakForce = Mathf.Infinity;
- //设置破坏关节的扭矩力为无限
- joint.breakTorque = Mathf.Infinity;
- //设置玩家移动的旋转速度为0
- playerMove.rotateSpeed = ;
- }
- /// <summary>
- /// 举起物体
- /// </summary>
- private void LiftPickup(Collider other)
- {
- //获取物体的网格
- Mesh otherMesh = other.GetComponent<MeshFilter>().mesh;
- //计算举起的位置
- holdPos = transform.position + transform.forward * holdOffset.z + transform.right * holdOffset.x + transform.up * holdOffset.y;
- //举起的位置的y值加碰撞器的范围的y值加碰撞物体网格的范围的y值
- holdPos.y += (GetComponent<Collider>().bounds.extents.y) + (otherMesh.bounds.extents.y);
- //检测举起位置的圆形范围
- if(!Physics.CheckSphere(holdPos,checkRadius)) {
- //修改gizmo颜色
- gizmoColor = Color.green;
- //缓存举起的物体
- heldObj = other.gameObject;
- //修改默认插值类型
- objectDefInterpolation = heldObj.GetComponent<Rigidbody>().interpolation;
- //修改举起物体的插值类型
- heldObj.GetComponent<Rigidbody>().interpolation = RigidbodyInterpolation.Interpolate;
- //修改举起物体的位置
- heldObj.transform.position = holdPos;
- //修改举起物体的旋转
- heldObj.transform.rotation = transform.rotation;
- //添加关节,连接物体和玩家
- AddJoint();
- //修改举起物体的质量
- heldObj.GetComponent<Rigidbody>().mass *= weightChange;
- //修改举起物体的时间为当前时间
- timeOfPickup = Time.time;
- } else {
- //修改gizmo颜色
- gizmoColor = Color.red;
- print("Can't lift object here. If nothing is above the player, perhaps you need to add a layerMask parameter to line 136 of the code in this script," +
- "the CheckSphere function, in order to make sure it isn't detecting something above the players head that is invisible");
- }
- }
- /// <summary>
- /// 放下物体
- /// </summary>
- private void DropPushable()
- {
- //修改抓住物体的插值类型
- heldObj.GetComponent<Rigidbody>().interpolation = objectDefInterpolation;
- //销毁关节
- Destroy (joint);
- //修改玩家移动的旋转速度为默认旋转速度
- playerMove.rotateSpeed = defRotateSpeed;
- heldObj = null;
- timeOfThrow = Time.time;
- }
- /// <summary>
- /// 扔掉物体
- /// </summary>
- public void ThrowPickup()
- {
- //播放扔物体声音
- if(throwSound)
- {
- aSource.volume = ;
- aSource.clip = throwSound;
- aSource.Play ();
- }
- //删除关节
- Destroy (joint);
- //获取举起物体的刚体
- Rigidbody r = heldObj.GetComponent<Rigidbody>();
- //恢复物体的插值类型
- r.interpolation = objectDefInterpolation;
- //恢复物体的质量
- r.mass /= weightChange;
- //给刚体添加力
- r.AddRelativeForce (throwForce, ForceMode.VelocityChange);
- heldObj = null;
- timeOfThrow = Time.time;
- }
- /// <summary>
- /// 添加关节,连接玩家和物体
- /// </summary>
- private void AddJoint()
- {
- //如果有物体
- if (heldObj)
- {
- //播放拾取声音
- if(pickUpSound)
- {
- aSource.volume = ;
- aSource.clip = pickUpSound;
- aSource.Play ();
- }
- //在物体上添加关节
- joint = heldObj.AddComponent<FixedJoint>();
- //设置关节的连接物体为玩家的刚体
- joint.connectedBody = GetComponent<Rigidbody>();
- }
- }
- void OnDrawGizmosSelected()
- {
- Gizmos.color = gizmoColor;
- Gizmos.DrawSphere (holdPos, checkRadius);
- }
- }
Throwing
- using UnityEngine;
- using System.Collections;
- /// <summary>
- /// 父物体下的子物体的触发器
- /// </summary>
- public class TriggerParent:MonoBehaviour {
- /// <summary>
- /// 要检查的标签列表
- /// </summary>
- public string[] tagsToCheck;
- /// <summary>
- /// 是否发生了碰撞,是否在碰撞中
- /// </summary>
- [HideInInspector]
- public bool collided, colliding;
- /// <summary>
- /// 撞击的物体
- /// </summary>
- [HideInInspector]
- public GameObject hitObject;
- void Awake() {
- //没有Collider或有Collider但不是触发器
- if(!GetComponent<Collider>() || (GetComponent<Collider>() && !GetComponent<Collider>().isTrigger))
- Debug.LogError("'TriggerParent' script attached to object which does not have a trigger collider",transform);
- }
- void OnTriggerEnter(Collider other) {
- //标签列表长度大于0且没有碰撞过
- && !collided) {
- //遍历标签
- foreach(string tag in tagsToCheck) {
- //找到标签
- if(other.tag == tag) {
- //已发生碰撞
- collided = true;
- //存储碰撞物体
- hitObject = other.gameObject;
- break;
- }
- }
- } else
- //已发生碰撞
- collided = true;
- //存储碰撞物体
- hitObject = other.gameObject;
- }
- void OnTriggerStay(Collider other) {
- //标签列表长度大于0
- ) {
- //遍历标签
- foreach(string tag in tagsToCheck) {
- //找到标签
- if(other.tag == tag) {
- //正在碰撞
- colliding = true;
- //存储碰撞物体
- hitObject = other.gameObject;
- break;
- }
- }
- } else {
- //存储碰撞物体
- hitObject = other.gameObject;
- //正在碰撞
- colliding = true;
- }
- }
- void OnTriggerExit(Collider other) {
- //标签列表长度大于0
- ) {
- //遍历标签
- foreach(string tag in tagsToCheck) {
- //找到标签
- if(other.tag == tag) {
- colliding = false;
- hitObject = null;
- break;
- }
- }
- } else
- return;
- }
- void LateUpdate() {
- //重置collided,hitObject
- if(collided) {
- collided = false;
- hitObject = null;
- }
- }
- }
TriggerParent
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- /// <summary>
- /// 水
- /// </summary>
- [RequireComponent(typeof(BoxCollider))]
- public class Water:MonoBehaviour {
- /// <summary>
- /// 玩家进水的声音
- /// </summary>
- public AudioClip splashSound;
- /// <summary>
- /// 水的推力
- /// </summary>
- ,);
- /// <summary>
- /// 玩家是否会受到水的阻力影响
- /// </summary>
- public bool effectPlayerDrag;
- /// <summary>
- /// 刚体受到的水的阻力(不包含玩家)
- /// </summary>
- public float resistance = 0.4f;
- /// <summary>
- /// 刚体受到的角阻力(不包含玩家)
- /// </summary>
- public float angularResistance = 0.2f;
- /// <summary>
- /// 刚体受到的阻力字典
- /// </summary>
- private Dictionary<GameObject,float> dragStore = new Dictionary<GameObject,float>();
- /// <summary>
- /// 刚体受到的角阻力字典
- /// </summary>
- private Dictionary<GameObject,float> angularStore = new Dictionary<GameObject,float>();
- void Awake() {
- //自动修改"Water"标签
- if(tag != "Water") {
- tag = "Water";
- Debug.LogWarning("'Water' script attached to an object not tagged 'Water', it been assigned the tag 'Water'",transform);
- }
- //设置Trigger
- GetComponent<Collider>().isTrigger = true;
- }
- void OnTriggerEnter(Collider other) {
- //获取物体的刚体
- Rigidbody r = other.GetComponent<Rigidbody>();
- //刚体不为空
- if(r) {
- //播放入水声音
- if(splashSound) {
- ;
- AudioSource.PlayClipAtPoint(splashSound,other.transform.position,volume);
- }
- //是玩家且不受水的阻力影响
- if(r.tag == "Player" && !effectPlayerDrag)
- return;
- //存储受到的阻力
- dragStore.Add(r.gameObject,r.drag);
- //存储受到的角阻力
- angularStore.Add(r.gameObject,r.angularDrag);
- //修改刚体受到的阻力
- r.drag = resistance;
- //修改刚体受到的角阻力
- r.angularDrag = angularResistance;
- } else if(splashSound)
- //播放入水声音
- AudioSource.PlayClipAtPoint(splashSound,other.transform.position);
- }
- void OnTriggerStay(Collider other) {
- //计算表面高度
- float surface = transform.position.y + GetComponent<Collider>().bounds.extents.y;
- Rigidbody rigid = other.GetComponent<Rigidbody>();
- if(rigid) {
- //计算物体相对于表面高度的深度
- float depth = surface - other.transform.position.y;
- //深度大于0.4
- if(depth > 0.4f)
- //用一个较小的力往上推刚体
- rigid.AddForce(force,ForceMode.Force);
- //深度小于等于0.4
- else
- //用一个较大的力往上推刚体
- rigid.AddForce(force * (depth * ),ForceMode.Force);
- }
- }
- void OnTriggerExit(Collider other) {
- //获取物体的刚体
- Rigidbody r = other.GetComponent<Rigidbody>();
- //有刚体
- if(r) {
- //是玩家且不受阻力水的阻力影响
- if(r.tag == "Player" && !effectPlayerDrag)
- return;
- //阻力和角阻力字典包含刚体的游戏物体
- if(dragStore.ContainsKey(r.gameObject) && angularStore.ContainsKey(r.gameObject)) {
- //恢复阻力
- r.drag = dragStore[r.gameObject];
- //恢复角阻力
- r.angularDrag = angularStore[r.gameObject];
- //移除阻力
- dragStore.Remove(r.gameObject);
- //移除角阻力
- angularStore.Remove(r.gameObject);
- } else {
- //重置阻力
- r.drag = 0f;
- //重置角阻力
- r.angularDrag = 0.05f;
- print("Object left water: couldn't get drag values, restored to defaults");
- }
- }
- }
- }
Water
视频:https://pan.baidu.com/s/1mhF7hmo
项目:https://pan.baidu.com/s/1pL6nMTP
Complete Physics Platformer Kit 学习的更多相关文章
- iOS7 Sprite Kit 学习
iOS7 Sprite Kit 学习 iOS 7有一个新功能 Sprite Kit 这个有点类似cocos2d 感觉用法都差不多.下面简单来介绍下Sprite Kit About Sprite Kit ...
- S老师 Top-Down RPG Starter Kit 学习
character creation using UnityEngine; using System.Collections; public class CharacterCreation : Mon ...
- Sprite Kit编程指南(1)-深入Sprite Kit
深入Sprite Kit 学习Sprite Kit最好的方法是在实践中观察它.此示例创建一对场景和各自的动画内容.通过这个例子,你将学习使用Sprite Kit内容的一些基础技术,包括: · ...
- [Unity3D]Unity资料大全免费分享
都是网上找的连七八糟的资料了,整理好分享的,有学习资料,视频,源码,插件……等等 东西比较多,不是所有的都是你需要的,可以按 ctrl+F 来搜索你要的东西,如果有广告,不用理会,关掉就可以了,如 ...
- 【转】iOS 开发怎么入门?
原文网址:http://www.zhihu.com/question/20264108 iOS 开发怎么入门? 请问有设计模式.内存管理方面的资料吗?最好有除了官方文档之外的其它内容,10 条评论 分 ...
- DirectX SDK版本与Visual Studio版本
对于刚刚接触 DirectShow 的人来说,安装配置是一个令人头疼的问题,经常出现的情况是最基本的 baseclass 就无法编译.一开始我也为此费了很大的功夫,比如说修改代码.修改编译选项使其编译 ...
- How to Write Doc Comments for the Javadoc Tool
http://www.oracle.com/technetwork/java/javase/documentation/index-137868.html This document describe ...
- DirectX
DirectX 9.0 Complete Software Development Kit (SDK) :(2002-12-19) 点击下载 DirectX 9.0 SDK Update - (Sum ...
- 转 springboot 教程
转 Spring Boot 揭秘与实战 系列 拓展阅读: https://zhuanlan.zhihu.com/dreawer?topic=Java 发表于 2016-12-21 | Spring框架 ...
随机推荐
- 开发框架DevExtreme全新发布v18.2.6|附下载
DevExtreme Complete Subscription是性能最优的 HTML5,CSS 和 JavaScript 移动.Web开发框架,可以直接在Visual Studio集成开发环境,构建 ...
- 实现html转png
公司要求将一些重要数据全部以图片的形式放在官网上,防止网络爬虫. 之前都是UI作图,人工上传,为了解放生产力,于是我们程序处理. 步骤: 1.html得到与原图一致的图片(交给前端处理) 2.html ...
- kettle在linux下执行任务
1.下载 最新版下载 7.1 https://community.hitachivantara.com/docs/DOC-1009855 准备 上传任务文件 .kjb,.ktr 上传mysql 驱动 ...
- L230 RF可靠性测试-RF指标
最近调试Zigbee 和2.4G产品时需要做一些认证,查找到常用的RF指标. ----------http://www.52rd.com/S_TXT/2016_5/TXT83303.htm------ ...
- <context:annotation-config/>和<mvc:annotation-driven/>及解决No mapping found for HTTP request with URI [/role/getRole] in DispatcherServlet with name 'springmvc-config'
1:什么时候使用<context:annotation-config> 当你使用@Autowired,@Required,@Resource,@PostConstruct,@PreDest ...
- array_multisort
项目中用到这个函数了 ,起初对这个函数一直是懵逼状态,文档都看的朦朦胧胧的 网上无意间看到这篇文章 ,写的超级详细,收藏了 . 当然要先放原地址:https://www.cnblogs.com/WuN ...
- 解析XML技术
转载:http://developer.51cto.com/art/200903/117512.htm XML现在已经成为一种通用的数据交换格式,它的平台无关性,语言无关性,系统无关性,给数据集成与交 ...
- JavaScript条件语句4--分支语句--if
JavaScript条件语句--分支语句 学习目标 1.掌握条件语句if 2.掌握prompt()的应用 3.掌握alert的应用 If语句 语法一: If(condition){ statement ...
- Android内核栈溢出与ROP(CVE-2013-2597)
一.准备 由于内核栈不可执行(NX),栈溢出利用需用到ROP.简单回顾一下ARM ROP. 漏洞演示代码如下,网上随便找了个. char *str="/system/bin/sh" ...
- tmux不自动加载配置文件.tmux.conf
/********************************************************************** * tmux不自动加载配置文件.tmux.conf * ...