筆記21 坦克大戰:小地圖
創建地面,添加跟隨攝像機
代碼:跟隨攝像機FlowTarget
public class FlowTarget : MonoBehaviour {
//跟隨的目標
public Transform target;
//跟隨的高度
public float height;
//跟隨的距離
public float distance;
//兩個更新的方法:Update和LateUpdate。 把Update改爲LateUpdate
//物體移動是在Update裏面做的,攝像機是跟隨物體移動,所以在LateUpdate裏面。
void LateUpdate () {
//法二:平滑跟隨。我的前方和目標的前方逐漸一致,利用插值。
//此方法,Y軸是不需要跟隨的,將其置爲零
Vector3 forward = transform.forward;
forward.y = 0;
//1可以寫成public變量,在外面調整平滑。爲了讓各個設備一樣,所以* Time.deltaTime
Vector3 newForward = Vector3.Lerp(forward, target.forward, 1 * Time.deltaTime);
//此處減去newForward * distance
transform.position = target.position - newForward * distance + Vector3.up * height;
//看向目標點(否則攝像機不會旋轉)
transform.LookAt(target);
}
}
添加音頻管理器
代碼:音頻管理器AudioManager
public class AudioManager : MonoBehaviour {
//音頻播放器有了,首先寫成單例類。
public static AudioManager Instance;
//寫出兩個播放器(背景音、音效)。然後到unity裏關聯(背景音,循環打鉤)。
public AudioSource bgmPlayer;
public AudioSource sePlayer;
void Awake () {
//單例類一定要在Awake裏面賦值。因爲這個方法調用的時機比Start靠前。
//這樣可以保證在第一時間把這個單例做成。
Instance = this;
}
// 下面給三個方法
//一個播放bgm。傳進來一個name,就是你播放的文件名稱
public void PlayMusic(string name)
{
//如果當前沒有播放,再去播放
if(bgmPlayer.isPlaying == false)
{
/*加載音頻資源。類型AudioClip。
從哪個位置加載?直接把name(外界傳進來的)放那就可以了。*/
AudioClip clip = Resources.Load<AudioClip>(name);
//更換當前播放的聲音片段
bgmPlayer.clip = clip;
//播放Play
bgmPlayer.Play();
}
}
//停止播放
public void StopMusic()
{
bgmPlayer.Stop();
}
//播放音效
public void PlaySound(string name)
{
/*加載音頻資源。類型AudioClip。
從哪個位置加載?直接把name(外界傳進來的)放那就可以了。*/
AudioClip clip = Resources.Load<AudioClip>(name);
//播放音效
sePlayer.PlayOneShot(clip);
}
}
製作坦克預設體
代碼:坦克預設體TankBass
public class TankBass : MonoBehaviour {
//輪胎,即車輪碰撞器
public WheelCollider[] wheel;
//血量。public使我們可以在unity裏修改血量。
public int Hp = 100;
//炮臺
public Transform Turret;
//子彈。每個坦克都會實例化子彈
public GameObject BulletPre;
//爆炸效果
public GameObject BombPre;
//開火點
public Transform FirePoint;
//protected 受保護的(該類和子類可以訪問)。
//子類一定會在自己的Start、Update裏寫東西,所以,寫成虛方法virtual
protected virtual void Start () {
}
protected virtual void Update () {
//如果血量小於等於0,就不能對坦克進行操作了
if (Hp <= 0)
{
return;
}
}
//受到攻擊。把子彈寫成一個觸發
private void OnTriggerEnter(Collider other)
{
//受到子彈攻擊。觸發的Tag值等於子彈Bullet,血量大於100。
if (other.tag == "Bullet" && Hp > 0)
{
//減血
Hp -= 30;
//播放被打中時的音效
AudioManager.Instance.PlaySound("hitWall");
//判斷血量
if(Hp <= 0)
{
//播放爆炸時的聲音
AudioManager.Instance.PlaySound("boom");
//實例化爆炸效果。在當前位置爆炸
Instantiate(BombPre, transform.position, Quaternion.identity);
//炸飛炮臺
//由於之前沒有給炮臺添加剛體,此處通過代碼添加
/*先拿到炮臺這個物體gameObject.添加一個組件AddComponent<>,
把組件的類型寫到<>裏。此時就添加了剛體。*/
Turret.gameObject.AddComponent<Rigidbody>();
/*給這個剛體,一個向上的力AddForce(Vector3.up * 300f)。
首先得到這個剛體Turret.GetComponent<Rigidbody>()*/
Turret.GetComponent<Rigidbody>().AddForce(Vector3.up * 300f);
//銷燬炮臺。5之後應該是落地了。
Destroy(Turret.gameObject, 5f);
}
}
}
//開火。
//protected 受保護的(該類和子類可以訪問)。但是還不確定子類是否要重寫方法,所以不要寫成虛方法。
protected void Fire()
{
//播放開火的聲音
AudioManager.Instance.PlaySound("bullet");
//實例化子彈。位置和開火點一樣,旋轉和開火點一樣。
Instantiate(BulletPre, FirePoint.position, FirePoint.rotation);
}
}
製作炮彈,利用坦克預設體制作玩家坦克、敵人坦克
代碼:炮彈BulletControl
public class BulletControl : MonoBehaviour {
void Start () {
//給子彈一個向前方的力。因爲這個裏只給一次,所以在Start裏面寫就好了。
GetComponent<Rigidbody>().AddForce(transform.forward * 3000f);
}
//子彈銷燬。無論碰到什麼,銷燬自己。
private void OnTriggerEnter(Collider other)
{
Destroy(gameObject);
}
}
代碼:玩家坦克PlayerControl
public class PlayerControl : TankBass {
//修改繼承、繼承於TankBass。
//希望炮管可以上下移動,先找到炮管。
public Transform Guntrans;
//計時器
private float timer;
protected override void Start()
{
base.Start();
//“base.Start();”表示,會調用父類裏的Start方法。
//鼠標隱藏。鼠標的模式改成鎖定的。
Cursor.lockState = CursorLockMode.Locked;
}
protected override void Update()
{
base.Update();
// Update控制移動
//首先得到輸入軸
float vertical = Input.GetAxis("Vertical");
float horizontal = Input.GetAxis("Horizontal");
//如果水平軸不爲零
if(horizontal != 0)
{
//轉向
wheel[0].steerAngle = horizontal * 50;
wheel[1].steerAngle = horizontal * 50;
//播放移動的聲音
AudioManager.Instance.PlayMusic("move");
}
else
{
AudioManager.Instance.StopMusic();
}
//如果垂直軸不等於0
if(vertical != 0)
{
//前進。給垂直方向上的力
wheel[2].motorTorque = vertical * 2000;
wheel[3].motorTorque = vertical * 2000;
}
//左右旋轉炮臺。監聽鼠標的左右滑動。
float mouseX = Input.GetAxis("Mouse X");
//如果這個值不爲0
if(mouseX != 0)
{
//旋轉歐拉角。垂直軸(Y軸)*鼠標左右移動(有正負)*20度*換算單位(變成每秒)
Turret.localEulerAngles += Vector3.up * mouseX * 20 * Time.deltaTime;
}
//上下旋轉炮管。監聽鼠標的上下滑動。
float mouseY = Input.GetAxis("Mouse Y");
//如果這個值不爲0
if (mouseY != 0)
{
//旋轉歐拉角。垂直軸(Y軸)*鼠標左右移動(有正負)*20度*換算單位(變成每秒)
Guntrans.localEulerAngles += Vector3.left * mouseY * 5 * Time.deltaTime;
//限制角度。當前的角度Vector3.Angle(炮管的正前方,炮臺的正前方)
float angle = Vector3.Angle(Guntrans.forward, Turret.forward);
//如果上下都大於5度
if(angle > 5)
{
//就把要加的度數減回來
Guntrans.localEulerAngles -= Vector3.left * mouseY * 5 * Time.deltaTime;
}
}
//開火。最好給一個計時器,不能讓它一直開火。
//計時器在這裏一直計時
timer += Time.deltaTime;
//此處,規定1秒可以開一發,並且按了左鍵
if(timer > 1f && Input.GetMouseButtonDown(0))
{
//把timer置爲0
timer = 0;
//調用開火方法
Fire();
}
}
}
代碼:敵人坦克EnemyControl
雖然敵人坦克的腳本代碼很少,但它繼承了父類坦克允許他繼承的方法。
敵人是否有其他功能,需完善。
public class EnemyControl : TankBass{
//修改繼承、繼承於TankBass。
}