十四创建音效
游戏所有的音效播放都是通过SoundManager来控制的。
14.1创建SoundManager
切换Hierarchy窗口创建Empty Object修改名称为SoundManager。给SoundManager添加2个Audio Source组件。AudioSource1来播放音效,AudioSource2来播放背景音乐。
14.2创建脚本
创建C#脚本修改名称为SoundManager.cs来控制声音的播放。代码如下:
using UnityEngine;
using System.Collections;
public class SoundManager : MonoBehaviour {
//音效
public AudioSource efxSource;
//背景音乐
public AudioSource musicSource;
public static SoundManager instance = null;
//音量上下线
public float lowPitchRange = 0.95f;
public float highPitchRange = 1.05f;
// Use this for initialization
void Awake ()
{
if(instance == null)
instance = this;
else if(instance != this)
Destroy(gameObject);
DontDestroyOnLoad(gameObject);
}
public void PlaySingle(AudioClip clip)
{
efxSource.clip = clip;
efxSource.Play();
}
public void RandomizeSfx(params AudioClip[] clips)
{
int randomIndex = Random.Range(0,clips.Length);
float randomPitch = Random.Range(lowPitchRange,highPitchRange);
efxSource.pitch = randomPitch;
efxSource.clip = clips[randomIndex];
efxSource.Play();
}
}
编写完成后,把SoundManager.cs附加给SoundManager对象。
修改属性:
Sound Manager(Script)/Efx Source = AudioSource1
Sound Manager(Script)/Music Source = AudioSource1
设置组件属性:
AudioSource2/Audio Clips = Project/Asserts/Sounds/scavengers_music
Play On Awak = true
Loop = true
点击运行查看效果,切换关卡的时候背景音乐并没有重新开始,这是因为DontDestroyOnLoad(gameObject)的作用。
14.3修改Player
修改Player.cs脚本程序,对主角动作增加音效。代码如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Player : MovingObject
{
//对内墙的破坏力
public int wallDamage = 1;
//食物增加生命
public int pointsPerFood = 10;
//苏打增加生命
public int pointsPerSoda = 20;
//重启延迟时间
public float restartLevelDelay = 1f;
//Player动画
private Animator animator;
//当前生命值
private int food ;
public Text foodText;
public AudioClip moveSound1;
public AudioClip moveSound2;
public AudioClip eatSound1;
public AudioClip eatSound2;
public AudioClip drinkSound1;
public AudioClip drinkSound2;
public AudioClip gameOverSound;
protected override void Start ()
{
animator = GetComponent<Animator>();
food = GameManager.instance.playerFoodPoints;
foodText.text = "Food: "+food;
base.Start();
}
void Update ()
{
if(!GameManager.instance.playersTurn)
return ;
//键盘输入,控制角色移动。
int horizontal = 0;
int vertical = 0 ;
horizontal = (int)Input.GetAxisRaw("Horizontal");
vertical = (int)Input.GetAxisRaw("Vertical");
if(horizontal!=0)
vertical = 0;
if(horizontal!=0 || vertical!=0)
AttemptMove<Wall>(horizontal,vertical);
}
//内置函数
private void OnDisable()
{
GameManager.instance.playerFoodPoints = food;
}
protected override void AttemptMove<T>(int xDir,int yDir)
{
//没移动一次食物减少1
food--;
foodText.text = "Food: "+food;
RaycastHit2D hit;
if(Move (xDir,yDir,out hit))
{
SoundManager.instance.RandomizeSfx(moveSound1,moveSound2);
}
base.AttemptMove<T>(xDir,yDir);
GameManager.instance.playersTurn =false;
}
//检查是否游戏结束
private void CheckIfGameOver()
{
//当前生命低于0游戏结束
if(food <= 0 )
{
SoundManager.instance.PlaySingle(gameOverSound);
SoundManager.instance.musicSource.Stop();
GameManager.instance.GameOver();
}
}
//碰撞内墙
protected override void OnCantMove<T>(T component)
{
Wall hitWall = component as Wall;
//破坏内墙
hitWall.DamageWall(wallDamage);
//出发PlayerChop触发器
animator.SetTrigger("PlayerChop");
}
//主角移动套exit的时候,加载下一关
private void Restart()
{
Application.LoadLevel(Application.loadedLevel);
}
//主角被敌人攻击的时候损失生命值
public void LoseFood(int loss)
{
//出发PlayerHit触发器
animator.SetTrigger("PlayerHit");
food -= loss;
foodText.text = "-" + loss + "Food: "+food;
CheckIfGameOver();
}
//检查碰撞,exit,food,soda
private void OnTriggerEnter2D(Collider2D other)
{
//主角移动到出口
if(other.tag == "Exit")
{
Invoke("Restart",restartLevelDelay);
enabled = false;
}
//吃掉食物
else if(other.tag == "Food")
{
food += pointsPerFood;
foodText.text = "+" + pointsPerFood + " Food: "+food;
SoundManager.instance.RandomizeSfx(eatSound1,eatSound2);
other.gameObject.SetActive(false);
}
//喝掉苏打汽水
else if(other.tag == "Soda")
{
food += pointsPerSoda;
foodText.text = "+" + pointsPerSoda + "Food: "+food;
SoundManager.instance.RandomizeSfx(drinkSound1,drinkSound2);
other.gameObject.SetActive(false);
}
}
}
设置Player预制体/PlayerScript音效属性。
moveSound1 = Project/Asserts/Audio/ scavengers_footstep1
moveSound2 = Project/Asserts/Audio/ scavengers_footstep2
eatSound1 = Project/Asserts/Audio/ scavengers_fruit1
eatSound2 = Project/Asserts/Audio/ scavengers_fruit2
drinkSound1 = Project/Asserts/Audio/ scavengers_soda1
drinkSound2 = Project/Asserts/Audio/ scavengers_soda2
gameOverSound = Project/Asserts/Audio/scavengers_die
14.4修改Enemy
修改Enemy.cs脚本代码如下:
using UnityEngine;
using System.Collections;
public class Enemy : MovingObject {
public int playerDemage;
public AudioClip enemyAttack1;
public AudioClip enemyAttack2;
private Animator animator;
private Transform target;
private bool skipMove;
// Use this for initialization
protected override void Start () {
GameManager.instance.AddEnemyToList(this);
animator = GetComponent<Animator>();
target = GameObject.FindGameObjectWithTag("Player").transform;
base.Start();
}
protected override void AttemptMove<T>(int xDir,int yDir)
{
if(skipMove)
{
skipMove = false;
return ;
}
base.AttemptMove<T>(xDir,yDir);
skipMove = true;
}
public void EnemyMove()
{
int xDir = 0 ;
int yDir = 0 ;
if(Mathf.Abs(target.transform.position.x - transform.position.x) < float.Epsilon)
yDir = target.transform.position.y > transform.position.y ? 1:-1;
else
xDir = target.transform.position.x > transform.position.x ? 1:-1;
AttemptMove<Player>(xDir,yDir);
}
protected override void OnCantMove<T>(T component)
{
Player hitPlayer = component as Player;
hitPlayer.LoseFood(playerDemage);
animator.SetTrigger("EnemyAttack");
SoundManager.instance.RandomizeSfx(enemyAttack1,enemyAttack2);
}
}
给预制体Enemy1和Enemy2的Enemy.cs脚本组件赋值。
修改属性:
Attack Sound1 = Project/Asserts/Audio/ scavengers_enemy1
Attack Sound2 = Project/Asserts/Audio/ scavengers_enemy2
14.5修改Wall
修改脚本Wall.cs代码如下:
using UnityEngine;
using System.Collections;
public class Wall : MonoBehaviour
{
public AudioClip chopSound1;
public AudioClip chopSound2;
public Sprite dmgSprite;
public int hp = 4;
private SpriteRenderer spriteRenderer;
// Use this for initialization
void Awake () {
spriteRenderer = GetComponent<SpriteRenderer>();
}
public void DamageWall(int less)
{
SoundManager.instance.RandomizeSfx(chopSound1,chopSound2);
spriteRenderer.sprite = dmgSprite;
hp -= less;
if(hp <= 0)
gameObject.SetActive(false);
}
}
给预制体Wall1到Wall2的Wall.cs脚本组件赋值。
修改属性:
ChopSound1 = Project/Asserts/Audio/scavengers_chop1
Chop Sound2 = Project/Asserts/Audio/scavengers_chop2