2D Platformer 学习
using UnityEngine; using System.Collections; /// <summary> /// 玩家控制 /// </summary> public class PlayerControl : MonoBehaviour { /// <summary> /// 是否面向右边 /// </summary> [HideInInspector] public bool facingRight = true; /// <summary> /// 是否在跳跃状态 /// </summary> [HideInInspector] public bool jump = false; /// <summary> /// 玩家左右移动的力 /// </summary> public float moveForce = 365f; /// <summary> /// 玩家在x轴的最大移动速度 /// </summary> public float maxSpeed = 5f; /// <summary> /// 跳跃声音 /// </summary> public AudioClip[] jumpClips; /// <summary> /// 跳跃力 /// </summary> public float jumpForce = 1000f; /// <summary> /// 嘲讽声音 /// </summary> public AudioClip[] taunts; /// <summary> /// 嘲讽阈值 /// </summary> public float tauntProbability = 50f; /// <summary> /// 嘲讽延迟 /// </summary> public float tauntDelay = 1f; /// <summary> /// 上一次的嘲讽索引 /// </summary> private int tauntIndex; /// <summary> /// 检查玩家是否在地上的go /// </summary> private Transform groundCheck; /// <summary> /// 玩家是否在地上 /// </summary> private bool grounded = false; /// <summary> /// Animator /// </summary> private Animator anim; void Awake() { groundCheck = transform.Find("groundCheck"); anim = GetComponent<Animator>(); } void Update() { //发射射线检测玩家是否在地面 grounded = Physics2D.Linecast(transform.position, groundCheck.position, 1 << LayerMask.NameToLayer("Ground")); //如果按下跳跃键且玩家在地上,玩家跳 if(Input.GetButtonDown("Jump") && grounded) jump = true; } void FixedUpdate () { //获取水平的输入 float h = Input.GetAxis("Horizontal"); //设置水平方向的移动速度 anim.SetFloat("Speed", Mathf.Abs(h)); //如果玩家速度没有到达最大速度,让玩家到达最大速度 if(h * GetComponent<Rigidbody2D>().velocity.x < maxSpeed) GetComponent<Rigidbody2D>().AddForce(Vector2.right * h * moveForce); //如果x轴的速度大于最大速度,限制玩家速度为最大速度 if(Mathf.Abs(GetComponent<Rigidbody2D>().velocity.x) > maxSpeed) GetComponent<Rigidbody2D>().velocity = new Vector2(Mathf.Sign(GetComponent<Rigidbody2D>().velocity.x) * maxSpeed, GetComponent<Rigidbody2D>().velocity.y); //设置玩家的朝向 if(h > 0 && !facingRight) Flip(); else if(h < 0 && facingRight) Flip(); //如果玩家跳 if(jump) { //播放跳动画 anim.SetTrigger("Jump"); //随机播放跳跃声音 int i = Random.Range(0, jumpClips.Length); AudioSource.PlayClipAtPoint(jumpClips[i], transform.position); //添加跳跃力 GetComponent<Rigidbody2D>().AddForce(new Vector2(0f, jumpForce)); //设置跳跃标志位为false jump = false; } } /// <summary> /// 转向 /// </summary> void Flip () { facingRight = !facingRight; Vector3 theScale = transform.localScale; theScale.x *= -1; transform.localScale = theScale; } /// <summary> /// 嘲讽协程 /// </summary> /// <returns></returns> public IEnumerator Taunt() { //计算嘲讽几率 float tauntChance = Random.Range(0f, 100f); //如果嘲讽几率大于阈值 if(tauntChance > tauntProbability) { yield return new WaitForSeconds(tauntDelay); if(!GetComponent<AudioSource>().isPlaying) { tauntIndex = TauntRandom(); GetComponent<AudioSource>().clip = taunts[tauntIndex]; GetComponent<AudioSource>().Play(); } } } /// <summary> /// 随机播放嘲讽 /// </summary> /// <returns></returns> int TauntRandom() { int i = Random.Range(0, taunts.Length); //如果和上次的嘲讽索引一样,再随机一次 if(i == tauntIndex) return TauntRandom(); else return i; } }
using UnityEngine; using System.Collections; /// <summary> /// 玩家生命 /// </summary> public class PlayerHealth : MonoBehaviour { /// <summary> /// 玩家生命 /// </summary> public float health = 100f; /// <summary> /// 玩家能被伤害的时间间隔 /// </summary> public float repeatDamagePeriod = 2f; /// <summary> /// 玩家受到伤害的声音数组 /// </summary> public AudioClip[] ouchClips; /// <summary> /// 玩家受到伤害时受到的力 /// </summary> public float hurtForce = 10f; /// <summary> /// 敌人碰到玩家后,玩家受到的伤害 /// </summary> public float damageAmount = 10f; /// <summary> /// 玩家血条 /// </summary> private SpriteRenderer healthBar; /// <summary> /// 上一次受到的伤害 /// </summary> private float lastHitTime; /// <summary> /// 血条缩放 /// </summary> private Vector3 healthScale; /// <summary> /// 玩家控制 /// </summary> private PlayerControl playerControl; /// <summary> /// Animator /// </summary> private Animator anim; void Awake () { playerControl = GetComponent<PlayerControl>(); healthBar = GameObject.Find("HealthBar").GetComponent<SpriteRenderer>(); anim = GetComponent<Animator>(); healthScale = healthBar.transform.localScale; } void OnCollisionEnter2D (Collision2D col) { //如果碰到敌人 if(col.gameObject.tag == "Enemy") { //如果时间大于 上次受到伤害的时间 + 玩家能被伤害的时间间隔 if (Time.time > lastHitTime + repeatDamagePeriod) { //如果玩家生命>0 if(health > 0f) { TakeDamage(col.transform); //设置上次受到伤害的时间 lastHitTime = Time.time; } //如果玩家生命<=,让玩家掉下河 else { //将玩家的碰撞器修改为触发器 Collider2D[] cols = GetComponents<Collider2D>(); foreach(Collider2D c in cols) { c.isTrigger = true; } //修改玩家及其子物体的 SorintLayer SpriteRenderer[] spr = GetComponentsInChildren<SpriteRenderer>(); foreach(SpriteRenderer s in spr) { s.sortingLayerName = "UI"; } //关闭玩家控制脚本 GetComponent<PlayerControl>().enabled = false; //关闭 gun脚本 GetComponentInChildren<Gun>().enabled = false; //播放死亡动画 anim.SetTrigger("Die"); } } } } /// <summary> /// 受到伤害 /// </summary> /// <param name="enemy"></param> void TakeDamage (Transform enemy) { //让玩家不能跳 playerControl.jump = false; //设置受伤的方向 Vector3 hurtVector = transform.position - enemy.position + Vector3.up * 5f; //给刚体施加力 GetComponent<Rigidbody2D>().AddForce(hurtVector * hurtForce); //减血 health -= damageAmount; //更新血条 UpdateHealthBar(); //随机播放受到伤害的声音 int i = Random.Range (0, ouchClips.Length); AudioSource.PlayClipAtPoint(ouchClips[i], transform.position); } /// <summary> /// 更新血条 /// </summary> public void UpdateHealthBar () { //设置血条颜色 healthBar.material.color = Color.Lerp(Color.green, Color.red, 1 - health * 0.01f); //设置血条缩放 healthBar.transform.localScale = new Vector3(healthScale.x * health * 0.01f, 1, 1); } }
using UnityEngine; using System.Collections; /// <summary> /// 玩家放置炸弹 /// </summary> public class LayBombs : MonoBehaviour { /// <summary> /// 炸弹是否已放置 /// </summary> [HideInInspector] public bool bombLaid = false; /// <summary> /// 玩家拥有的炸弹数量 /// </summary> public int bombCount = 0; /// <summary> /// 放置炸弹的声音 /// </summary> public AudioClip bombsAway; /// <summary> /// 炸弹预设 /// </summary> public GameObject bomb; /// <summary> /// 炸弹HUD /// </summary> private GUITexture bombHUD; void Awake () { bombHUD = GameObject.Find("ui_bombHUD").GetComponent<GUITexture>(); } void Update () { //放置炸弹 if(Input.GetButtonDown("Fire2") && !bombLaid && bombCount > 0) { bombCount--; bombLaid = true; AudioSource.PlayClipAtPoint(bombsAway,transform.position); Instantiate(bomb, transform.position, transform.rotation); } bombHUD.enabled = bombCount > 0; } }
using UnityEngine; using System.Collections; /// <summary> /// 玩家的枪 /// </summary> public class Gun : MonoBehaviour { /// <summary> /// 火箭预设 /// </summary> public Rigidbody2D rocket; /// <summary> /// 火箭速度 /// </summary> public float speed = 20f; /// <summary> /// 玩家控制 /// </summary> private PlayerControl playerCtrl; /// <summary> /// Animator /// </summary> private Animator anim; void Awake() { anim = transform.root.gameObject.GetComponent<Animator>(); playerCtrl = transform.root.GetComponent<PlayerControl>(); } void Update () { //按下发射键 if(Input.GetButtonDown("Fire1")) { //播放动画 anim.SetTrigger("Shoot"); //播放声音 GetComponent<AudioSource>().Play(); //玩家朝右 if(playerCtrl.facingRight) { //实例化向右的子弹 Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0,0,0))) as Rigidbody2D; bulletInstance.velocity = new Vector2(speed, 0); } //玩家朝左 else { //实例化向左的子弹 Rigidbody2D bulletInstance = Instantiate(rocket, transform.position, Quaternion.Euler(new Vector3(0,0,180f))) as Rigidbody2D; bulletInstance.velocity = new Vector2(-speed, 0); } } } }
using UnityEngine; using System.Collections; /// <summary> /// 火箭 /// </summary> public class Rocket : MonoBehaviour { /// <summary> /// 爆炸预设 /// </summary> public GameObject explosion; void Start () { //炸弹没有碰到任何东西,默认2秒内销毁 Destroy(gameObject, 2); } /// <summary> /// 爆炸 /// </summary> void OnExplode() { //实例化爆炸效果,让爆炸效果在z轴随机旋转 Quaternion randomRotation = Quaternion.Euler(0f, 0f, Random.Range(0f, 360f)); Instantiate(explosion, transform.position, randomRotation); } void OnTriggerEnter2D (Collider2D col) { //撞到敌人 if(col.tag == "Enemy") { //敌人受伤 col.gameObject.GetComponent<Enemy>().Hurt(); OnExplode(); Destroy (gameObject); } //撞到炸弹收集物 else if(col.tag == "BombPickup") { //炸弹爆炸 col.gameObject.GetComponent<Bomb>().Explode(); Destroy (col.transform.root.gameObject); Destroy (gameObject); } //其余情况 else if(col.gameObject.tag != "Player") { OnExplode(); Destroy (gameObject); } } }
using UnityEngine; using System.Collections; /// <summary> /// 自动销毁 /// </summary> public class Destroyer : MonoBehaviour { /// <summary> /// 是否在开始时间就进入自动销毁 /// </summary> public bool destroyOnAwake; /// <summary> /// 自动销毁的延迟 /// </summary> public float awakeDestroyDelay; /// <summary> /// 是否查找子物体 /// </summary> public bool findChild = false; /// <summary> /// 子物体的名称 /// </summary> public string namedChild; void Awake () { if(destroyOnAwake) { if(findChild) { Destroy (transform.Find(namedChild).gameObject); } else { Destroy(gameObject, awakeDestroyDelay); } } } /// <summary> /// 销毁子物体 /// </summary> void DestroyChildGameObject () { if(transform.Find(namedChild).gameObject != null) Destroy (transform.Find(namedChild).gameObject); } /// <summary> /// 禁用子物体 /// </summary> void DisableChildGameObject () { if(transform.Find(namedChild).gameObject.activeSelf == true) transform.Find(namedChild).gameObject.SetActive(false); } /// <summary> /// 销毁物体 /// </summary> void DestroyGameObject () { Destroy (gameObject); } }
using UnityEngine; using System.Collections; /// <summary> /// 血条跟随玩家 /// </summary> public class FollowPlayer : MonoBehaviour { /// <summary> /// 相对于玩家的偏移 /// </summary> public Vector3 offset; /// <summary> /// 玩家 /// </summary> private Transform player; void Awake () { player = GameObject.FindGameObjectWithTag("Player").transform; } void Update () { transform.position = player.position + offset; } }
using UnityEngine; using System.Collections; /// <summary> /// 收集物的孵化器 /// </summary> public class PickupSpawner : MonoBehaviour { /// <summary> /// 收集物预设 /// </summary> public GameObject[] pickups; /// <summary> /// 收集物在空中的时间 /// </summary> public float pickupDeliveryTime = 5f; /// <summary> /// 掉落范围左 /// </summary> public float dropRangeLeft; /// <summary> /// 掉落范围右 /// </summary> public float dropRangeRight; /// <summary> /// 高于这个阈值,投递炸弹 /// </summary> public float highHealthThreshold = 75f; /// <summary> /// 低于这个阈值,投递血药 /// </summary> public float lowHealthThreshold = 25f; /// <summary> /// 玩家血量 /// </summary> private PlayerHealth playerHealth; void Awake () { playerHealth = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerHealth>(); } void Start () { StartCoroutine(DeliverPickup()); } /// <summary> /// 派送收集物协程 /// </summary> /// <returns></returns> public IEnumerator DeliverPickup() { yield return new WaitForSeconds(pickupDeliveryTime); //随机获得掉落在x轴的位置 float dropPosX = Random.Range(dropRangeLeft, dropRangeRight); //计算掉落位置 Vector3 dropPos = new Vector3(dropPosX, 15f, 1f); //高于阈值,实例化炸弹 if(playerHealth.health >= highHealthThreshold) Instantiate(pickups[0], dropPos, Quaternion.identity); //低于阈值,实例化药 else if(playerHealth.health <= lowHealthThreshold) Instantiate(pickups[1], dropPos, Quaternion.identity); //随机实例化 else { int pickupIndex = Random.Range(0, pickups.Length); Instantiate(pickups[pickupIndex], dropPos, Quaternion.identity); } } }
using UnityEngine; using System.Collections; /// <summary> /// 炸弹收集物 /// </summary> public class BombPickup : MonoBehaviour { /// <summary> /// 收集声音 /// </summary> public AudioClip pickupClip; /// <summary> /// Animator /// </summary> private Animator anim; /// <summary> /// 是否着陆 /// </summary> private bool landed = false; void Awake() { anim = transform.root.GetComponent<Animator>(); } void OnTriggerEnter2D (Collider2D other) { //碰到玩家 if(other.tag == "Player") { AudioSource.PlayClipAtPoint(pickupClip, transform.position); other.GetComponent<LayBombs>().bombCount++; Destroy(transform.root.gameObject); } //碰到地面 else if(other.tag == "ground" && !landed) { anim.SetTrigger("Land"); transform.parent = null; gameObject.AddComponent<Rigidbody2D>(); landed = true; } } }
using UnityEngine; using System.Collections; /// <summary> /// 生命收集物 /// </summary> public class HealthPickup : MonoBehaviour { /// <summary> /// 提供的生命值 /// </summary> public float healthBonus; /// <summary> /// 被收集后的声音 /// </summary> public AudioClip collect; /// <summary> /// 收集物孵化器 /// </summary> private PickupSpawner pickupSpawner; /// <summary> /// Animator /// </summary> private Animator anim; /// <summary> /// 是否着陆 /// </summary> private bool landed; void Awake () { pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>(); anim = transform.root.GetComponent<Animator>(); } void OnTriggerEnter2D (Collider2D other) { //如果碰到玩家 if(other.tag == "Player") { PlayerHealth playerHealth = other.GetComponent<PlayerHealth>(); //给玩家加血 playerHealth.health += healthBonus; //限制玩家的最大生命 playerHealth.health = Mathf.Clamp(playerHealth.health, 0f, 100f); //更新血条 playerHealth.UpdateHealthBar(); pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup()); AudioSource.PlayClipAtPoint(collect,transform.position); Destroy(transform.root.gameObject); } //如果碰到地面 else if(other.tag == "ground" && !landed) { anim.SetTrigger("Land"); transform.parent = null; gameObject.AddComponent<Rigidbody2D>(); landed = true; } } }
using UnityEngine; using System.Collections; /// <summary> /// 炸弹 /// </summary> public class Bomb : MonoBehaviour { /// <summary> /// 爆炸影响的半径 /// </summary> public float bombRadius = 10f; /// <summary> /// 爆炸力 /// </summary> public float bombForce = 100f; /// <summary> /// 爆炸声音 /// </summary> public AudioClip boom; /// <summary> /// 炸弹引爆的声音 /// </summary> public AudioClip fuse; /// <summary> /// 引爆持续时间 /// </summary> public float fuseTime = 1.5f; /// <summary> /// 爆炸特效 /// </summary> public GameObject explosion; /// <summary> /// 玩家放置炸弹 /// </summary> private LayBombs layBombs; /// <summary> /// 收集物孵化器 /// </summary> private PickupSpawner pickupSpawner; /// <summary> /// 爆炸粒子系统 /// </summary> private ParticleSystem explosionFX; void Awake () { explosionFX = GameObject.FindGameObjectWithTag("ExplosionFX").GetComponent<ParticleSystem>(); pickupSpawner = GameObject.Find("pickupManager").GetComponent<PickupSpawner>(); if(GameObject.FindGameObjectWithTag("Player")) layBombs = GameObject.FindGameObjectWithTag("Player").GetComponent<LayBombs>(); } void Start () { //如果炸弹没有父物体,说明炸弹已被放置,开始引爆 if(transform.root == transform) StartCoroutine(BombDetonation()); } /// <summary> /// 炸弹引爆协程 /// </summary> /// <returns></returns> IEnumerator BombDetonation() { AudioSource.PlayClipAtPoint(fuse, transform.position); yield return new WaitForSeconds(fuseTime); Explode(); } /// <summary> /// 爆炸 /// </summary> public void Explode() { //玩家可以放置炸弹 layBombs.bombLaid = false; //开始新的投递 pickupSpawner.StartCoroutine(pickupSpawner.DeliverPickup()); //获取范围内的敌人 Collider2D[] enemies = Physics2D.OverlapCircleAll(transform.position, bombRadius, 1 << LayerMask.NameToLayer("Enemies")); foreach(Collider2D en in enemies) { Rigidbody2D rb = en.GetComponent<Rigidbody2D>(); if(rb != null && rb.tag == "Enemy") { //秒杀敌人 rb.gameObject.GetComponent<Enemy>().HP = 0; //将敌人推出一段距离 Vector3 deltaPos = rb.transform.position - transform.position; Vector3 force = deltaPos.normalized * bombForce; rb.AddForce(force); } } //播放爆炸效果 explosionFX.transform.position = transform.position; explosionFX.Play(); Instantiate(explosion,transform.position, Quaternion.identity); AudioSource.PlayClipAtPoint(boom, transform.position); Destroy (gameObject); } }
using UnityEngine; using System.Collections; /// <summary> /// 敌人 /// </summary> public class Enemy : MonoBehaviour { /// <summary> /// 移动速度 /// </summary> public float moveSpeed = 2f; /// <summary> /// 玩家被击杀需要的次数 /// </summary> public int HP = 2; /// <summary> /// 死亡的动画 /// </summary> public Sprite deadEnemy; /// <summary> /// 受到伤害的动画 /// </summary> public Sprite damagedEnemy; /// <summary> /// 死亡声音 /// </summary> public AudioClip[] deathClips; /// <summary> /// 敌人死亡后生成的 得分物体 /// </summary> public GameObject hundredPointsUI; /// <summary> /// /// </summary> public float deathSpinMin = -100f; /// <summary> /// /// </summary> public float deathSpinMax = 100f; /// <summary> /// 精灵渲染器 /// </summary> private SpriteRenderer ren; /// <summary> /// 检查前方的go /// </summary> private Transform frontCheck; /// <summary> /// 是否死亡 /// </summary> private bool dead = false; /// <summary> /// 玩家得分脚本 /// </summary> private Score score; void Awake() { ren = transform.Find("body").GetComponent<SpriteRenderer>(); frontCheck = transform.Find("frontCheck").transform; score = GameObject.Find("Score").GetComponent<Score>(); } void FixedUpdate () { //检测碰撞 Collider2D[] frontHits = Physics2D.OverlapPointAll(frontCheck.position, 1); foreach(Collider2D c in frontHits) { //如果碰到障碍物 if(c.tag == "Obstacle") { //转向 Flip (); break; } } GetComponent<Rigidbody2D>().velocity = new Vector2(transform.localScale.x * moveSpeed, GetComponent<Rigidbody2D>().velocity.y); if(HP == 1 && damagedEnemy != null) ren.sprite = damagedEnemy; if(HP <= 0 && !dead) Death (); } /// <summary> /// 受到伤害 /// </summary> public void Hurt() { HP--; } void Death() { //关闭所有的精灵渲染器 SpriteRenderer[] otherRenderers = GetComponentsInChildren<SpriteRenderer>(); foreach(SpriteRenderer s in otherRenderers) { s.enabled = false; } //打开自身的渲染器,设置为死亡精灵 ren.enabled = true; ren.sprite = deadEnemy; //玩家得分+100 score.score += 100; //死亡标志位设为true dead = true; GetComponent<Rigidbody2D>().fixedAngle = false; GetComponent<Rigidbody2D>().AddTorque(Random.Range(deathSpinMin,deathSpinMax)); //修改碰撞器为触发器 Collider2D[] cols = GetComponents<Collider2D>(); foreach(Collider2D c in cols) { c.isTrigger = true; } //播放随机的死亡声音 int i = Random.Range(0, deathClips.Length); AudioSource.PlayClipAtPoint(deathClips[i], transform.position); //实例化得分效果 Vector3 scorePos; scorePos = transform.position; scorePos.y += 1.5f; Instantiate(hundredPointsUI, scorePos, Quaternion.identity); } /// <summary> /// 转向 /// </summary> public void Flip() { Vector3 enemyScale = transform.localScale; enemyScale.x *= -1; transform.localScale = enemyScale; } }
using UnityEngine; using System.Collections; /// <summary> /// 移除器 /// </summary> public class Remover : MonoBehaviour { /// <summary> /// 水的飞溅效果 /// </summary> public GameObject splash; void OnTriggerEnter2D(Collider2D col) { //如果碰到玩家 if(col.gameObject.tag == "Player") { //禁用摄像机跟随玩家的脚本 GameObject.FindGameObjectWithTag("MainCamera").GetComponent<CameraFollow>().enabled = false; //禁用玩家血条 if(GameObject.FindGameObjectWithTag("HealthBar").activeSelf) { GameObject.FindGameObjectWithTag("HealthBar").SetActive(false); } Instantiate(splash, col.transform.position, transform.rotation); Destroy (col.gameObject); StartCoroutine("ReloadGame"); } else { Instantiate(splash, col.transform.position, transform.rotation); Destroy (col.gameObject); } } /// <summary> /// 重新加载游戏协程 /// </summary> /// <returns></returns> IEnumerator ReloadGame() { yield return new WaitForSeconds(2); Application.LoadLevel(Application.loadedLevel); } }
using UnityEngine; using System.Collections; /// <summary> /// 玩家得分 /// </summary> public class Score : MonoBehaviour { /// <summary> /// 玩家得分 /// </summary> public int score = 0; /// <summary> /// 玩家控制脚本 /// </summary> private PlayerControl playerControl; /// <summary> /// 上一帧的得分 /// </summary> private int previousScore = 0; void Awake () { playerControl = GameObject.FindGameObjectWithTag("Player").GetComponent<PlayerControl>(); } void Update () { //设置得分文本 GetComponent<GUIText>().text = "Score: " + score; //如果上一帧的得分不等与现在的得分 if(previousScore != score) //播放嘲讽 playerControl.StartCoroutine(playerControl.Taunt()); //设置上一帧的额得分为 现在的得分 previousScore = score; } }
using UnityEngine; using System.Collections; /// <summary> /// 分数阴影 /// </summary> public class ScoreShadow : MonoBehaviour { /// <summary> /// Score Go /// </summary> public GameObject guiCopy; void Awake() { //设置阴影的位置 Vector3 behindPos = transform.position; behindPos = new Vector3(guiCopy.transform.position.x, guiCopy.transform.position.y-0.005f, guiCopy.transform.position.z-1); transform.position = behindPos; } void Update () { GetComponent<GUIText>().text = guiCopy.GetComponent<GUIText>().text; } }
using UnityEngine; using System.Collections; /// <summary> /// 暂停器 /// </summary> public class Pauser : MonoBehaviour { /// <summary> /// 是否已暂停 /// </summary> private bool paused = false; void Update () { if(Input.GetKeyUp(KeyCode.P)) { paused = !paused; } if(paused) Time.timeScale = 0; else Time.timeScale = 1; } }
using UnityEngine; using System.Collections; /// <summary> /// 并行背景 /// </summary> public class BackgroundParallax : MonoBehaviour { /// <summary> /// 并行背景数组 /// </summary> public Transform[] backgrounds; /// <summary> /// /// </summary> public float parallaxScale; /// <summary> /// /// </summary> public float parallaxReductionFactor; /// <summary> /// /// </summary> public float smoothing; /// <summary> /// 摄像机 /// </summary> private Transform cam; /// <summary> /// 上一帧的相机位置 /// </summary> private Vector3 previousCamPos; void Awake () { cam = Camera.main.transform; } void Start () { previousCamPos = cam.position; } void Update () { float parallax = (previousCamPos.x - cam.position.x) * parallaxScale; for(int i = 0; i < backgrounds.Length; i++) { float backgroundTargetPosX = backgrounds[i].position.x + parallax * (i * parallaxReductionFactor + 1); Vector3 backgroundTargetPos = new Vector3(backgroundTargetPosX, backgrounds[i].position.y, backgrounds[i].position.z); backgrounds[i].position = Vector3.Lerp(backgrounds[i].position, backgroundTargetPos, smoothing * Time.deltaTime); } previousCamPos = cam.position; } }
using UnityEngine; using System.Collections; /// <summary> /// 背景道具孵化器 /// </summary> public class BackgroundPropSpawner : MonoBehaviour { /// <summary> /// 背景道具的刚体 /// </summary> public Rigidbody2D backgroundProp; /// <summary> /// 左侧的x轴孵化点 /// </summary> public float leftSpawnPosX; /// <summary> /// 右侧的x轴孵化点 /// </summary> public float rightSpawnPosX; /// <summary> /// /// </summary> public float minSpawnPosY; public float maxSpawnPosY; /// <summary> /// 最短的孵化时间间隔 /// </summary> public float minTimeBetweenSpawns; /// <summary> /// 最长的孵化时间间隔 /// </summary> public float maxTimeBetweenSpawns; /// <summary> /// 道具的最小速度 /// </summary> public float minSpeed; /// <summary> /// 道具的最大速度 /// </summary> public float maxSpeed; void Start () { //随机种子 Random.seed = System.DateTime.Today.Millisecond; StartCoroutine("Spawn"); } /// <summary> /// 孵化协程 /// </summary> /// <returns></returns> IEnumerator Spawn () { //随机等待时间 float waitTime = Random.Range(minTimeBetweenSpawns, maxTimeBetweenSpawns); yield return new WaitForSeconds(waitTime); //随机方向 bool facingLeft = Random.Range(0,2) == 0; float posX = facingLeft ? rightSpawnPosX : leftSpawnPosX; //随机y轴位置 float posY = Random.Range(minSpawnPosY, maxSpawnPosY); Vector3 spawnPos = new Vector3(posX, posY, transform.position.z); Rigidbody2D propInstance = Instantiate(backgroundProp, spawnPos, Quaternion.identity) as Rigidbody2D; if(!facingLeft) { Vector3 scale = propInstance.transform.localScale; scale.x *= -1; propInstance.transform.localScale = scale; } //随机速度 float speed = Random.Range(minSpeed, maxSpeed); speed *= facingLeft ? -1f : 1f; propInstance.velocity = new Vector2(speed, 0); //重新孵化 StartCoroutine(Spawn()); while(propInstance != null) { if(facingLeft) { if(propInstance.transform.position.x < leftSpawnPosX - 0.5f) Destroy(propInstance.gameObject); } else { if(propInstance.transform.position.x > rightSpawnPosX + 0.5f) Destroy(propInstance.gameObject); } yield return null; } } }
using UnityEngine; using System.Collections; /// <summary> /// 摄像机跟随玩家 /// </summary> public class CameraFollow : MonoBehaviour { public float xMargin = 1f; public float yMargin = 1f; public float xSmooth = 8f; public float ySmooth = 8f; public Vector2 maxXAndY; public Vector2 minXAndY; private Transform player; void Awake () { player = GameObject.FindGameObjectWithTag("Player").transform; } bool CheckXMargin() { return Mathf.Abs(transform.position.x - player.position.x) > xMargin; } bool CheckYMargin() { return Mathf.Abs(transform.position.y - player.position.y) > yMargin; } void FixedUpdate () { TrackPlayer(); } void TrackPlayer () { float targetX = transform.position.x; float targetY = transform.position.y; if(CheckXMargin()) targetX = Mathf.Lerp(transform.position.x, player.position.x, xSmooth * Time.deltaTime); if(CheckYMargin()) targetY = Mathf.Lerp(transform.position.y, player.position.y, ySmooth * Time.deltaTime); targetX = Mathf.Clamp(targetX, minXAndY.x, maxXAndY.x); targetY = Mathf.Clamp(targetY, minXAndY.y, maxXAndY.y); transform.position = new Vector3(targetX, targetY, transform.position.z); } }
using UnityEngine; using System.Collections; /// <summary> /// 设置粒子系统的SortingLayer /// </summary> public class SetParticleSortingLayer : MonoBehaviour { /// <summary> /// SortingLayer名 /// </summary> public string sortingLayerName; void Start () { //设置粒子系统的sortingLayer名 GetComponent<ParticleSystem>().GetComponent<Renderer>().sortingLayerName = sortingLayerName; } }
视频:https://pan.baidu.com/s/1skBrKnF
项目:https://pan.baidu.com/s/1qXDvBWg