[初学Untiy]Survival Shooter Tutorial

来源:互联网 发布:淘宝客代运营 编辑:程序博客网 时间:2024/05/21 07:55

https://unity3d.com/learn/tutorials/projects/survival-shooter-tutorial

01.Enviroment Setup

This is part 1 of 10 of the Survival shooter tutorial, in which you will setup a pre-designed environment with lighting and background music.

Add a Quad GameObject and rename it Floor.
调整transform
将Floor 作为之后Ray的终结平面。设置其 Layer 为 Floor.去除其 Mesh Renderer Component使其不可见。

02.Player Character

Animation Clip

drag the player to the scene. notice it has an animator component.

  • Animation Clip
  • Animation State Machines

Add an animator controller.
Drag the three animation clip on to the Window Animator.
And set the Idle to be default state.

Now, set the logic among those animations!
Add Parameter bool called IsWalking.
Add Parameter trigger called Die.
Set up transitions.

Animator Window

Set Transitioin
注意这里的 Conditioins
意思是当 IsWalking 被设置为 true 的时候,Player 的动作由 Idle 变为 Move。

-Animator Controller

Add Component Rigidbody to GameObject Player.
Set the Drag and Angular Drag to Infinity.
Set Freeze Position and Freeze Rotation.

Set Rigidbody

Add Component Capsule Collider.

Write Script.

camRay

using UnityEngine;public class PlayerMovement : MonoBehaviour{    public float speed = 6f;    Vector3 movement;    Animator anim;    Rigidbody playerRigidbody;    int floorMask;    float camRayLength = 100f;    void Awake()    {        floorMask = LayerMask.GetMask("Floor");        anim = GetComponent<Animator>();        playerRigidbody = GetComponent<Rigidbody>();    }    void FixedUpdate()    {        float h = Input.GetAxisRaw("Horizontal");       // Since input is not smoothed, keyboard input will always be either -1, 0 or 1.        float v = Input.GetAxisRaw("Vertical");        Move(h, v);        Turning();        Animating(h, v);    }    void Move(float h, float v)    {        movement.Set(h, 0f, v);        movement = movement.normalized * speed * Time.deltaTime;     // make sure that the player moves at the same speed regardless of which key combination you use.        playerRigidbody.MovePosition(transform.position + movement);    }    void Turning()      // the direction the character is facing based on the mouse input    {        Ray camRay = Camera.main.ScreenPointToRay(Input.mousePosition);        RaycastHit floorHit;        if (Physics.Raycast(camRay, out floorHit, camRayLength, floorMask))        {            Vector3 playerToMouse = floorHit.point - transform.position;            playerToMouse.y = 0f;           // we don't want our player to sort of leaning back, so we need to make sure that the Y component of this vector is definitely 0.            Quaternion newRotation = Quaternion.LookRotation(playerToMouse);        // we can't use vector3 to do rotation, so we need to create newRotation.            playerRigidbody.MoveRotation(newRotation);                              // rotate the rigidbody to the newRotation        }    }    void Animating(float h, float v)        // we need the h && v parameters because whether or not the player is walking or idle is dependent on the input.    {        bool walking = (h != 0f || v != 0f);        // if h or v is not 0, then the player is walking.        anim.SetBool("IsWalking", walking);    }}

now I can move the player with arrow keys or W,A,S and D.

oho

03.Camera setup

We want to make an isometric view, so we’re going to use orthographic cameras.

Set main camera.
Write a script within the GameObject Main Camera.

using UnityEngine;using System.Collections;public class CameraFollow : MonoBehaviour{    public Transform target;        // a target for this camera to follow.    public float smoothing = 5f;    // our camera gonna follow the player around, but we don't want it to be super sharp.                                    // we're going to give it a little bit of lag, a little bit just to make it smoother for the player to see.    private Vector3 offset;         // the distance between camera and the player.    void Start()    {        offset = transform.position - target.position;    }    void FixedUpdate()              // use FixedUpdate to move the camera because we're following a physics object.    {                               // if we used Update then it would be moving in different time to the player because the player is moving in FixedUpdate        Vector3 targetCamPos = target.position + offset;        transform.position = Vector3.Lerp(transform.position, targetCamPos, smoothing * Time.deltaTime);       // A Lerp just smoothly moves betweent two positions.    }}

Save the Player as a Prefab.

Note: If you turn the GameObject Player in to a Prefab, it’s an asset, a hard dry file you can save it, export it, reuse it.

04.Adding Enemy one

This is part 4 of 10 of the Survival Shooter tutorial, in which you will create the enemy behaviour, including animation, state machines, nav-mesh and code.

Drag Model Zombunny on to the Scene. Add Prefab HitParticles as the child component to Zombunny.

Now we want to detect whether this enemy is something that we can shoot at, so we set this Zombunny’s layer to be “shootable”. Remenber change the children.
Add a rigidbody component to Zombunny. Then we add a Capsule Collider.

We want Zombunny to detect our Player, so we’re going to use one more collider to do that. We’re goning to use a trigger collider for this purpose. Add a Spehere Collider. And click the Is Trigger to make this Collider a Trigger Collider.

2 colliders

The Sphere Collider is slightly further out than the Capsule Collider is, the reason being that we want to detect the player within the Zombunny’s reach, so we want it to bump into stuff but we it’s reach to be able to harm the player, so we make that sphere collider slightly bigger and we make it tirgger so it’s not going to bump into anything.

Add Audio Source to the Zombunny GameObject.

Next, we need to make the guy actually follow the player.

Open Navigation Window.

Add Nav Mesh Agent Component to Zombunny.

Set Radius to 0.3, Speed to 3, Stopping Distance to 1.3, Height to 1.1.

Bake the Nav Mesh.

Create Animator Controller in the Project panel Animation Foler.
Drag This EnemyAC to Zombunny. Edit EnemyAC in the Animator Window by double click it.
Add a Trigger Parameter called PlayerDead. This enemy characters are going to walk, they’re going to have their move animation until the player dies and they are going to into their idle animation.

state machine

These state machines don’t work by themselves, the connection betweent the state machine and animator and the actual functionality is the scripting needs to tell those parameters what their value is.

So, add EnemyMovement script to Zombunny, and Edit it.

using UnityEngine;using System.Collections;public class EnemyMovement : MonoBehaviour{    Transform player;    NavMeshAgent nav;    void Awake()    {        player = GameObject.FindWithTag("Player").transform;        // our enemies are not going to be in the game when the game starts.                                                                     // Our enemies are going to be instantiated later or spawned later,                                                                     // so we use GameObject.FindWithTag to get the player's transform.        nav = GetComponent<NavMeshAgent>();    }    void Update()                           // NavMeshAgent is not keeping in time with physics, so we just use Update()    {        nav.SetDestination(player.position);                        // move towards the player    }}

the Enemy is walking towards you, wow

补充学习:Navigation System

05. Health Hud

This is part 5 of 10 of the Survival Shooter tutorial, in which you will create a Heads Up Display for Health using the new UI tools in Unity 4.6.

1.Add Canvas GameObject, and rename it HUDCanvas.

2.Add Canvas Group Component, and uncheck Interactable, Blocks Raycasts.(这样,其子对象将不能被交互,也不会阻挡射线,即使在子对象中设置了其他选项。)

3.Add HealthUI GameObject as HUDCanvas’s child.

4.choose anchor preset, hold alt and shift and click the left bottom, just like that:

choose anchor preset

5.add UI/Image to HealthUI rename it Heart, set Width and Height, and then Set Source Image “Heart”.

6.add Slider GameObject to HealthUI, and set PosX and Width to move it right to the “Heart” in the canvas. and delete it’s childobject “Handle Slider Area”, cause we are not gonna use it.
Set Transition in the Slider Component to “None”.
Set the Max Value to “100”.
Change Value to 100.

7.add UI/Image to HUDCanvas and rename it DamageImage, I want to make it be the flash effect when the Player get hurt. Use Anchor Preset to resize it full screen. And set the alpha “0”.

补充学习:UICanvas

06.Player Health

This is part 6 of 10 of the Survival Shooter tutorial, in which you will program the player’s health, which is used in reference by other elements of the game.

Add PlayerHealth.cs to Player and then edit it.

using UnityEngine;using UnityEngine.UI;using System.Collections;public class PlayerHealth : MonoBehaviour{    public int startingHealth = 100;    public int currentHealth;    public Slider healthSlider;    public Image damageImage;    public AudioClip deathClip;     // The audio clip to play when the player dies    public float flashSpeed = 5f;    public Color flashColor = new Color(1f, 0f, 0f, 0.1f);    Animator anim;    AudioSource playerAudio;    PlayerMovement playerMovement;    bool isDead;    bool damaged;    void Awake()    {        anim = GetComponent<Animator>();        playerAudio = GetComponent<AudioSource>();        playerMovement = GetComponent<PlayerMovement>();        currentHealth = startingHealth;    }    void Update()    {        if(damaged)        {            damageImage.color = flashColor;        }        else        {            // transition the color back to clear. Use Color.Lerp            damageImage.color = Color.Lerp(damageImage.color, Color.clear, flashSpeed * Time.deltaTime);        }        damaged = false;    }    public void TakeDamage(int amount)    {        // Set the damaged flag so the screen will flash.        damaged = true;        currentHealth -= amount;        healthSlider.value = currentHealth;        playerAudio.Play();     // Play the hurt sound effect.        //If the player has lost all it's health and the death flag hasn't been set yet...        if(currentHealth <= 0 && !isDead)           {            Death();        }    }    void Death()    {        // Set the death flag so this function won't be called again.        isDead = true;        // Tell the animator that the player is dead.        anim.SetTrigger("Die");        // Set the audiosource to play the death clip and play it (this will stop the hurt sound from playing).        playerAudio.clip = deathClip;        playerAudio.Play();        playerMovement.enabled = false;    }}

Now, I want give the Enemy the ability to attack the Player. Write EnemyAttack.cs and add to be the Component of Zombunny.

using UnityEngine;using System.Collections;public class EnemyAttack : MonoBehaviour{    public float timeBetweentAttacks = 0.5f;    public int attackDamage = 10;    Animator anim;    GameObject player;    PlayerHealth playerHealth;    bool playerInRange;             // whether the player is within the trigger collider and can be attacked.    float timer;                    // time for counting up to the next attack.    void Awake()    {        anim = GetComponent<Animator>();        player = GameObject.FindWithTag("Player");        playerHealth = player.GetComponent<PlayerHealth>();    }    void OnTriggerEnter(Collider other)    {        // if the entering collider is player        if(other.gameObject == player)        {            // the player is in range            playerInRange = true;        }    }    void OnTriggerExit(Collider other)    {        // if the exiting collider is the player        if(other.gameObject == player)        {            // the player is no longer in range            playerInRange = false;        }    }    void Update()    {        timer += Time.deltaTime;        if(timer >= timeBetweentAttacks && playerInRange)        {            Attack();        }        if(playerHealth.currentHealth <= 0)        {            anim.SetTrigger("PlayerDead");      // tell the animator the player is dead.        }    }    void Attack()    {        timer = 0f;        if(playerHealth.currentHealth > 0)        {            playerHealth.TakeDamage(attackDamage);        }    }}

07.Harming Enemies

This is part 7 of 10 of the Survival Shooter tutorial, in which you will give create the player shooting mechanic using Raycasting, Line Renderers and more.

1.首先给 Enmey 添加 EnemyHealth.cs,其中有一个 public void StartSinking()函数,用以在 Animationi Clip Death 中设置 Animation Event,这样当 Zombunny 在 进行 Death 动作的时候,就开始执行 StartSinking,慢慢下沉。

Aniamtioin Event

using UnityEngine;public class EnemyHealth : MonoBehaviour{    public int startingHealth = 100;    public int currentHealth;    public AudioClip deathClip;    public float sinkSpeed = 2.5f;    public int socreValue = 10;    Animator anim;    AudioSource enemyAudio;    ParticleSystem hitParticles;    CapsuleCollider capsuleCollider;    //EnemyMovement enemyMovement;    bool isDead;    bool isSinking;    void Awake()    {        anim = GetComponent<Animator>();        enemyAudio = GetComponent<AudioSource>();        //enemyMovement = GetComponent<EnemyMovement>();        hitParticles = GetComponentInChildren<ParticleSystem>();        capsuleCollider = GetComponent<CapsuleCollider>();        currentHealth = startingHealth;    }    void Update()    {        if(isSinking)        {            transform.Translate(-Vector3.up * sinkSpeed * Time.deltaTime);        }    }    public void TakeDamage(int amount, Vector3 hitPoint)    {        if(isDead)        {            return;        }        currentHealth -= amount;        enemyAudio.Play();        hitParticles.transform.position = hitPoint;        hitParticles.Play();        if(currentHealth <= 0 && !isDead)        {            Death();        }    }    void Death()    {        isDead = true;        capsuleCollider.isTrigger = true;           // turn the collider into a trigger so shots can pass through it.        anim.SetTrigger("Dead");                    // tell the animator the enemy is dead        enemyAudio.clip = deathClip;        enemyAudio.Play();        //enemyMovement.enabled = false;    }    public void StartSinking()    {        // Find and disable the Nav Mesh Agent.        GetComponent<NavMeshAgent>().enabled = false;        // Find the rigidbody component and make it kinematic (since we use Translate to sink the enemy)        GetComponent<Rigidbody>().isKinematic = true;        isSinking = true;           // the enemy should now sink                            Destroy(gameObject, 2f);                    // after 2 seconds destroy the enemy.    }}
  1. pair the Eenmy Attack.cs to EnemyHealth.cs, so the Enemy does not attack once they’re already dead.
using UnityEngine;using System.Collections;public class EnemyAttack : MonoBehaviour{    public int attackDamage = 10;    public float attackInterval = 0.8f;    GameObject player;    PlayerHealth playerHealth;    Animator anim;    EnemyHealth enemyHealth;                // we need to access the currentHealth variable in the EnemyHealth.cs    bool playerInRange;    float timer;    void Awake()    {        player = GameObject.FindWithTag("Player");        playerHealth = player.GetComponent<PlayerHealth>();        anim = GetComponent<Animator>();        enemyHealth = GetComponent<EnemyHealth>();    }    void OnTriggerEnter(Collider other)    {        if (other.gameObject == player)        {            playerInRange = true;        }    }    void OnTriggerExit(Collider other)    {        if (other.gameObject == player)        {            playerInRange = false;        }    }    void Update()    {        timer += Time.deltaTime;        if(timer >= attackInterval && playerInRange && enemyHealth.currentHealth > 0)        {            Attack();        }    }    void Attack()    {        if(playerHealth.currentHealth > 0)        {            playerHealth.TakeDamage(attackDamage);            timer = 0f;        }        else        {            anim.SetTrigger("PlayerDead");        }    }}

3.Get the Player to rock and roll.
3.1add a particle component which is going to enable the gun to spit fire.
copy the Particle System Component in the Prefabs/GunParticles and paste the component to Player/GunBarrelEnd as new.
add a Line Renderer, the Line Renderer is going to be the visual component of shooting.edit the Materials and Parameters, and then turn it off.
Line Renderer set

3.2add a light component, set the color, and turn it off.
3.3add audio source, and set the audio clip to Player GunShot, uncheck the Play On Awake and Loop.

补充学习:Using Animation Events

4.Now we add the scripts, to allow the Player shoot to the enemy. place the PlayerShooting.cs to GunBarrelEnd gameobject.

using UnityEngine;using System.Collections;public class PlayerShooting : MonoBehaviour{    public int damagePerShot = 20;    public float timeBetweenBullets = 0.15f;    public float range = 100f;    float timer;    Ray shootRay;    RaycastHit shootHit;    int shootableMask;    ParticleSystem gunParticles;    LineRenderer gunLine;    AudioSource gunAudio;    Light gunLight;    float effectsDisplayTime = 0.2f;    void Awake()    {        shootableMask = LayerMask.GetMask("Shootable");        gunParticles = GetComponent<ParticleSystem>();        gunLine = GetComponent<LineRenderer>();        gunAudio = GetComponent<AudioSource>();        gunLight = GetComponent<Light>();    }    void Update()    {        timer += Time.deltaTime;        if(Input.GetButton("Fire1") && timer >= timeBetweenBullets)           {            Shoot();        }        if(timer >= timeBetweenBullets * effectsDisplayTime)        {            DisableEffects();        }    }    public void DisableEffects()    {        gunLight.enabled = false;        gunLine.enabled = false;    }    void Shoot()    {        timer = 0f;        gunAudio.Play();        gunLight.enabled = true;        gunParticles.Stop();        gunParticles.Play();        gunLine.enabled = true;        gunLine.SetPosition(0, transform.position);        shootRay.origin = transform.position;        shootRay.direction = transform.forward;        if(Physics.Raycast(shootRay, out shootHit, range, shootableMask))       // 如果射线投射到一个 Collider 上        {            EnemyHealth enemyHealth = shootHit.collider.GetComponent<EnemyHealth>();            if(enemyHealth != null)     // 如果被射击到的对象 有 EnemyHealth component            {                enemyHealth.TakeDamage(damagePerShot, shootHit.point);            }            gunLine.SetPosition(1, shootHit.point);                             // set the Line Renderer end point        }        else                            {            gunLine.SetPosition(1, shootRay.origin + shootRay.direction * range);   // 如果没有投射到一个 Collider 上,则画一个 range 长度的 射线,沿着 direcion 方向,否则就看不到射线了。                                                                                    // just spraying bullets around even though we don't hit anything.        }    }}

5.click the apply button, 这样这些后来添加,编辑的东西就会被应用到Prefabs/Player中。

apply

6.There is an error.

“SetDestination” can only be called on an active agent that has been placed on a NavMesh.
UnityEngine.NavMeshAgent:SetDestination(Vector3)
EnemyMovement:Update() (at Assets/Scripts/Enemy/EnemyMovement.cs:19)

double click the error in the console, and jump to the EnemyMovement.cs line 19

we need to make it right.注意,当Player 或者 Enemy 生命值小于等于0的时候,就不需要再继续 SetDestination 了。所以,在这里,我们访问这两个值,然后做判断。

using UnityEngine;using System.Collections;public class EnemyMovement : MonoBehaviour{    Transform player;    NavMeshAgent nav;    PlayerHealth playerHealth;    EnemyHealth enemyHealth;    void Awake()    {        player = GameObject.FindWithTag("Player").transform;        // our enemies are not going to be in the game when the game starts.                                                                     // Our enemies are going to be instantiated later or spawned later,                                                                     // so we use GameObject.FindWithTag to get the player's transform.        nav = GetComponent<NavMeshAgent>();        playerHealth = player.GetComponent<PlayerHealth>();        enemyHealth = GetComponent<EnemyHealth>();    }    void Update()                           // NavMeshAgent is not keeping in time with physics, so we just use Update()    {        if(playerHealth.currentHealth > 0 && enemyHealth.currentHealth > 0)        {            nav.SetDestination(player.position);                        // move towards the player        }        else        {            nav.enabled = false;            // switch NavMeshAgen Component        }    }}

还有一个 Bug 就是当 Player dead 之后,还是可以 fire。。。修改

using UnityEngine;using UnityEngine.UI;using System.Collections;public class PlayerHealth : MonoBehaviour{    public int startingHealth = 100;    public int currentHealth;    public Slider healthSlider;    public Image damageImage;    public AudioClip deathClip;     // The audio clip to play when the player dies    public float flashSpeed = 5f;    public Color flashColor = new Color(1f, 0f, 0f, 0.1f);    Animator anim;    AudioSource playerAudio;    PlayerMovement playerMovement;    PlayerShooting playerShooting;    bool isDead;    bool damaged;    void Awake()    {        anim = GetComponent<Animator>();        playerAudio = GetComponent<AudioSource>();        playerMovement = GetComponent<PlayerMovement>();        playerShooting = GetComponentInChildren<PlayerShooting>();        currentHealth = startingHealth;    }    void Update()    {        if(damaged)        {            damageImage.color = flashColor;        }        else        {            // transition the color back to clear. Use Color.Lerp            damageImage.color = Color.Lerp(damageImage.color, Color.clear, flashSpeed * Time.deltaTime);        }        damaged = false;    }    public void TakeDamage(int amount)    {        if(isDead)        {            return;        }        // Set the damaged flag so the screen will flash.        damaged = true;        currentHealth -= amount;        healthSlider.value = currentHealth;        playerAudio.Play();     // Play the hurt sound effect.        //If the player has lost all it's health and the death flag hasn't been set yet...        if(currentHealth <= 0 && !isDead)           {            Death();        }    }    void Death()    {        // Set the death flag so this function won't be called again.        isDead = true;        playerShooting.DisableEffects();        // Tell the animator that the player is dead.        anim.SetTrigger("Die");        // Set the audiosource to play the death clip and play it (this will stop the hurt sound from playing).        playerAudio.clip = deathClip;        playerAudio.Play();        playerMovement.enabled = false;        playerShooting.enabled = false;     // while the player is dead, he can not shoot any longer.    }}

08.Scoring Points

This is part 8 of 10 of the Survival Shooter tutorial, in which you will program the player’s score, updating it with each kill.

Add a UI/Text called ScoreText, and move the anchor(only move the anchor, not the pivot and the position) to the top middle. Then we change the Pos Y value to -55. Then set the Width 300 and Height 50. Then set the color White. Then change the font to LuckiestGuy.Then set Font Size 50, Alignment middle and middle. For convenience, set the Text “Score: 0”.
Then we add a Shadow Component to this ScoreText GameObject. And make sure the Use Graphic Alpha is checked, otherwise when you change the alpha of the text the shadow won’t also change.

https://docs.unity3d.com/Manual/script-Shadow.html
The Shadow component adds a simple outline effect to graphic components such as Text or Image. It must be on the same GameObject as the graphic component.

Score Text

Now we need something to set the score, updating the text component’s text value with Score 10, Score 20… So we need to add a manage script called ScoreManager.cs

Drag and drop on the ScoreText Gameobject. And Edit it.

using UnityEngine;using UnityEngine.UI;using System.Collections;public class ScoreManager : MonoBehaviour{    public static int score;            // this variable belongs to the class ScoreManager, we can use it by ScoreManager.score. We don't need to access to it's instance.    Text scoreText;    void Awake()    {        scoreText = GetComponent<Text>();        score = 0;                      // reset the score, cause if we die we need the game to reset.    }    void Update()    {        scoreText.text = "Score: " + score;    }}

And we should let the Zombunny to add the score, so we edit the EnemyHealth.cs to

    public void StartSinking()    {        // Find and disable the Nav Mesh Agent.        GetComponent<NavMeshAgent>().enabled = false;        // Find the rigidbody component and make it kinematic (since we use Translate to sink the enemy)        GetComponent<Rigidbody>().isKinematic = true;        isSinking = true;                           // the enemy should now sink                            ScoreManager.score += scoreValue;           // add score in the class ScoreManager. cause the score is a static value, so we can access it through class name.        Destroy(gameObject, 2f);                    // after 2 seconds destroy the enemy.    }

Now, we drag the Zombunny in the Hierarchy to the Assets/Prefabs and make it a prefab for later use.

09.Spawing Enemies

This is part 9 of 10, in which you will add two other enemy types to the game, as well as a spawner manager to create them during the game.

1.Edit the Prefabs/ZomBear, add EnemyMovement.cs EnemyAttack.cs EnemyHealth.cs and Choose the AnimatorController “EnemyAC” which has been edit before for the Zombunny.

2.Edit the Prefabs/Hellephant, add EnemyMovement.cs EnemyAttack.cs EnemyHealth.cs, and Create Animator Override Controller called “HellephantAOC”, then select the Controller EnemyAC which has been made before,(因为这里有着同样的动作,所以可以复用) and Select AnimationClips from Model/Characters/Hellephant. Then we Set the Controller in the Hellephant/Animator “HellephantAOC”.

AnimatorOverrideController

3.Create an empty gameobject rename it EnemyManager. Edit it.

using UnityEngine;using System.Collections;public class EnemyManager : MonoBehaviour{    public PlayerHealth playerHealth;    public GameObject[] enemys;    public Transform[] spawnPoints;    public float spawnTime = 3f;    void Start()    {        InvokeRepeating("Spawn", spawnTime, spawnTime);    }    void Spawn()    {        if(playerHealth.currentHealth <= 0f)        {            return;        }        int spawnPointIndex = Random.Range(0, spawnPoints.Length);        int enemyIndex = Random.Range(0, enemys.Length);        Instantiate(enemys[enemyIndex], spawnPoints[spawnPointIndex].position, spawnPoints[spawnPointIndex].rotation);    }}

Then set up some spawnpoints in the Scene view by create some GameObjects and have different transform.position, and then fill the blanks in the EnemyManager/EnemyManager Component.

three spawnpoints, three kinds of enemies

surrounded, danger

10.Game Over

This is part 10 of 10 of the Survival Shooter tutorial, in which you will create the Game Over screen with UI, animation and code.

add UI/Image rename it ScreenFader, and stretch it to fill the screen by alt+anchor preset.

add UI/Text rename it GameOverText, and edit it.

now we need to reorder how these UI GameObjects are arranged.

The UI system needs to use the hierarchy to order it’s render order. We need to adjust the order to make it like below.

UI render Order

Draw order of elements
UI elements in the Canvas are drawn in the same order they appear in the Hierarchy. The first child is drawn first, the second child next, and so on. If two UI elements overlap, the later one will appear on top of the earlier one.
To change which element appear on top of other elements, simply reorder the elements in the Hierarchy by dragging them. The order can also be controlled from scripting by using these methods on the Transform component: SetAsFirstSibling, SetAsLastSibling, and SetSiblingIndex.

Then we set the ScreenFader and ScoreText ‘s alpha “0”. And now we are going to use animation in just a second to animate those in, make them look cool, and we are going to create a state machine for when the game ends.

Because we previously used pre-animated FBX files, they came with an animator component already attached to them, we just needed to create the controller, the state machine(Window Animator), to apply to it.
But you can use the animator with anything. You can animate anything you want to, it’s just a state machine you can apply animation clips to. So we are going to do exactly that with our UI right now.
Even the term animation is a bit misleading because it makes you think that some form of motion is involved and in fact animation in this case can literally be the changing of anything. So you can animate any public property of any component on any game object in unity.

Now we are going to do that with the UI, because when we stat adding animation Unity is going to automatically assign the animator, I.E. the holder for state machine. We need to select the right object, so we’re going to choose the HUDCanvas as the one we are going to start adding animation to. **That way when we add one clip, we’ll be able to address any property of any of the child objects.**With HUDCanvas selected, go to Window/Animation (not the animator) and edit it.(VERY NICE)

Animation

Finally!

Upgrading audio to Unity 5

01. Mixers and Effects

In this assignment we’re going to go step by step through the process of upgrading the Nightmares Survival Shooter project’s audio to take advantage of the new audio features in Unity 5. This assignment is in two parts: in the first part we’ll route our audio sources to Audio Mixer Groups, apply a Low Pass Filter to our music track and also a Duck Volume Effect to our music so that it gets quieter when our sound effects play.

  1. Singnal flow with the audio mixer.
  2. Using audio effects in your mix.

    • Create two mixers named MasterMixer and SoundEffects.
    • Edit the Groups of MasterMixer first. Add two groups, Music and SoundEffects. Music will get BackgroundMusic, and SoundEffects will get bunch of AudioSources.
    • Drag SoundEffects Mixers on to MasterMixer to make it the child, and select gourp SoundEffects of MasterMixer.
    • Edit the Groups of SoundEffects by add three groups which are GunShots, Player, Enemies.
    • Set these AudioSources Output to the AudioMixer’s gourps. Such as set Prefabs/ZomBear/AudioSource/Output to Enemies(SoundEffects), set BackgroundMusic/AudioSource/Output to Music(MasterMixer).

Enemies(SoundEffects)

Music(MasterMixer)

AudioMixer

With our audio sources now routed into our new audio mixers, we are going to add some effects processing.

  • MasterMixer/Music/Add Effects/Lowpass Simple.

The Audio Low Pass Simple Effect passes low frequencies of an AudioMixer group while removing frequencies higher than the Cutoff Frequency.

  • Add a littler bit of dynamic volume control using the duck volume audio effect. Add Duck Volume Effects to the Music Group. Now we need to route some signal from the group that we want to cause our music to duck in volume. We are going to use the SoundEffects Group, so that when the sound effects play, the music will automatically get quieter.
  • add effect send on the SoundEffects Gourp. and make the Receive “Music\Duck Volume”, edit the SendLevel 0.00dB.
  • Then Play with the duck volume Threshold in the Music Group, make it lower so when the volume come from SoundEffects bigger than the threshold, the Music will automatically get quieter.

  • Create two Snapshots. named Paused and Unpaused, in the Paused Snapshot, lower the Lowpass Simple / Cutoff freq to 800Hz. The two SnapShots are going to control the state of the mixer and allow us to recall different mixer states, including levels and effects settings.

Audio Mixer

02.Snapshots and Exposed parameters

Controlling the Mixer via scripting.

step 1

Before moving on to scripting we want to do one more thing in our mixer, we want to expose the volume of the music group and the sound effects group to script control so that we can set them directly without using the snapshot system. We also expose the volume of the soundeffects group to the script.

expose the volume to script

Now in the exposed parameters list, we are going to name this two parameters. “musicVol” and “sfxVol”.

exposed parameters list

step 2

Now we are going to add some scripting control. Let’s start by editing the PauseManager.cs.

using UnityEngine;using System.Collections;using UnityEngine.UI;using UnityEngine.Audio;#if UNITY_EDITOR        // we check if we currently running in the Unity Editor, and if so we're adding the namespace declaration using UnityEditor;#endifpublic class PauseManager_2 : MonoBehaviour {    public AudioMixerSnapshot paused;    public AudioMixerSnapshot unpaused;    Canvas canvas;    void Start()    {        canvas = GetComponent<Canvas>();    }    void Update()    {        if(Input.GetKeyDown(KeyCode.Escape))        {            canvas.enabled = !canvas.enabled;            Pause();        }    }    public void Pause()    {        Time.timeScale = Time.timeScale == 0 ? 1 : 0;       // by setting Time.timeScale to 0, we can freeze the motion of all of the objects in our game.        Lowpass();          // 调整游戏背景音量    }    public void Quit()    {#if UNITY_EDITOR                                    // we check if we are using the Unity Editor,         EditorApplication.isPlaying = false;        // stop playeing the scene#else                                               // else, we're going to call Application.Quit() meaning if this was the build of our application it would actually quit out to the desktop.        Application.Quit();#endif    }    void Lowpass()                      {        if(Time.timeScale == 0)                 // 通过判断当前是在暂停状态还是游戏状态来 Performs an interpolated transition towards this snapshot over the time interval specified.        {            paused.TransitionTo(.01f);        }        else        {            unpaused.TransitionTo(.01f);        }    }}

step 3

We have the volume control for the music and for the sound effects, we are going to use those to control our audio mixer using script.

using UnityEngine;using System.Collections;using UnityEngine.Audio;public class MixLevels_2 : MonoBehaviour{    public AudioMixer masterMixer;    public void SetSfxLvl(float sfxLvl)    {        masterMixer.SetFloat("sfxVol", sfxLvl);     // Sets the value of the exposed parameter specified.                                                     // When a parameter is exposed, it is not controlled by mixer snapshots and can therefore only be changed via this function.    }    public void SetMusicLvl(float musicLvl)    {        masterMixer.SetFloat("musicVol", musicLvl);    }}

EffectsSlider

Then set the Min Value and Max Value in the EffectsSlider and MusicSlider to proper value.

step 4

some other stuff,

  1. AudioToggle,通过设置 MainCamera 的 Component AudioListener 来设置声音的关闭和开启。

AudioToggle

  1. ResumeButton,通过设置 MenuCanvas 的 Component Canvas 来设置该GUI的显示与隐藏。

ResumeButton

And OK!

0 0
原创粉丝点击