筆記23 Unity項目:超級瑪麗
拖放地圖,裁剪精靈,形成跑步動畫,精靈渲染器
攝像機跟隨+代碼CameraControl
//跟隨的物體
public Transform target;
//最小邊界(能到的最左邊)
public float minX;
//最大邊界(能到的最右邊)
public float maxX;
void Update () {
//獲取當前位置
Vector3 pos = transform.position;
//將它的x改成目標的x
pos.x = target.position.x;
//邊界判斷。需要傳入兩個邊界
if(pos.x > maxX)
{
pos.x = maxX;
}
if(pos.x < minX)
{
pos.x = minX;
}
//再賦值回去
transform.position = pos;
}
瑪里奧動畫
給馬里奧、地面等添加碰撞器、剛體(注意是2D的!)
添加音樂播放器+代碼AudioManager
//音頻播放器有了,首先寫成單例類。
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);
}
檢測是否與地面碰撞(有兩種方法)
法一:利用射線檢測是否碰到地面(適用此遊戲)
//利用射線檢測是否碰到地面(法一)
//畫出射線。從中心點出發,向下*0.1米。
Debug.DrawRay(transform.position, Vector2.down * 0.1f);
/*創建2d射線。特點:可以直接返回。3d返回的是布爾值,hit在上面,利用out給hit值。
而且在括號裏可以直接填寫射線的起點,方向,距離,檢測的層(此處是第8層)。*/
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down ,0.1f,1<<8);
if(hit.collider != null)
{
//說明碰到地面了
isGround = true;
//把跳躍的動畫關閉
ani.SetBool("Jump", false);
}
else
{
//沒碰到地面(在空中)
isGround = false;
ani.SetBool("Jump", true);
}
法二:不通過射線(不適用此遊戲)
//判斷是否碰撞到地面(法二)。此處不適用,比如碰到左邊碰撞體,可以二段跳。
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Ground")
{
isGround = true;
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.tag == "Ground")
{
isGround = false;
}
}
敵人蘑菇+代碼EnemyControl
拖放,添加碰撞器、剛體,添加動畫,編寫代碼,形成預設體。
//血量
public int Hp = 1;
//剛體
private Rigidbody2D rBody;
//動畫
private Animator ani;
//保存方向。方向分爲1(正方向)和-1(負方向)。
private int dir = 1;
void Start () {
//在這裏得到
rBody = GetComponent<Rigidbody2D>();
ani = GetComponent<Animator>();
}
void Update () {
if(Hp <= 0)
{
return;
}
/*移動(方向*速度)。
爲了使敵人碰到物體後向相反方向移動,此處乘以方向(上面設置了默認是正方向)。*/
//老師寫的是Vector3.left
transform.Translate(Vector2.left * 0.2f * dir * Time.deltaTime);
}
//不管碰到什麼物體,都向反方向移動
private void OnCollisionEnter2D(Collision2D collision)
{
dir = -dir;
//判斷玩家碰到自己。注意給玩家標籤。
if(collision.collider.tag == "Player")
{
//contacts[0]碰撞的點,point代表拿到這一點的位置。
//contacts[0].normal它還有一個法線,就是和碰撞點垂直的單位向量。
//比如玩家從上面踩了蘑菇,會產生從碰撞點向下的法線。
if (collision.contacts[0].normal == Vector2.down)
{
//也就是說玩家從上方踩到,敵人死亡
//拿到玩家身上的剛體組件,給它添加一個向上的力。
collision.collider.GetComponent<Rigidbody2D>().AddForce(Vector2.up * 100f);
//死亡方法寫在外面,此處調用。
Die();
}
else
{
//玩家從其他方向碰到敵人,玩家死亡
//拿到玩家的代碼,調用裏面的Die方法。
collision.collider.GetComponent<PlayControl>().Die();
}
}
}
//死亡
void Die()
{
Hp--;
if(Hp <= 0)
{
//死亡
//一秒之後銷燬
Destroy(gameObject, 1f);
//動畫
ani.SetBool("Die", true);
//聲音
AudioManager.Instance.PlaySound("踩敵人");
/*碰撞器失效(因爲死亡了,玩家踩到的時候不能再觸發事件。
而之所以能產生事件,是因爲碰撞器的存在)*/
GetComponent<Collider2D>().enabled = false;
//刪除剛體(碰撞器也可以用此方法。如果刪除了碰撞器,而沒有刪除剛體,那麼蘑菇會掉下去。)
Destroy(GetComponent<Rigidbody2D>());
}
}
代碼:馬里奧PlayControl
//人物的血量
public int Hp = 1;
//是否在地面
private bool isGround = false;
//剛體
private Rigidbody2D rBody;
//動畫
private Animator ani;
//獲取精靈圖片(爲了後面翻轉圖片)
private SpriteRenderer sr;
void Start () {
//在此處拿到這兩個組件
rBody = GetComponent<Rigidbody2D>();
ani = GetComponent<Animator>();
sr = GetComponent<SpriteRenderer>();
}
void Update () {
if (Hp <= 0)
{
return;
}
//因爲人物只是左右跑,所以拿水平軸
float horizontal = Input.GetAxis("Horizontal");
//如果水平軸不爲0
if (horizontal != 0)
{
//前進
transform.Translate(transform.right * Time.deltaTime * 1 * horizontal);
//翻轉圖片(模擬轉頭)
if (horizontal > 0)
{
//說明是往右邊走所以不翻轉
sr.flipX = false;
}
if (horizontal < 0)
{
sr.flipX = true;
}
//移動動畫
ani.SetBool("Run", true);
}
else
{
ani.SetBool("Run", false);
}
//跳躍。按了I鍵,並且人物是站在地上的。
if (Input.GetKeyDown(KeyCode.I) && isGround == true)
{
//跳躍力(向上,作用在剛體上)
rBody.AddForce(Vector2.up * 200);
//播放跳的聲音
AudioManager.Instance.PlaySound("跳");
}
//利用射線檢測是否碰到地面(法一)
//畫出射線。從中心點出發,向下*0.1米。
Debug.DrawRay(transform.position, Vector2.down * 0.1f);
/*創建2d射線。特點:可以直接返回。3d返回的是布爾值,hit在上面,利用out給hit值。
而且在括號裏可以直接填寫射線的起點,方向,距離,檢測的層(此處是第8層)。*/
RaycastHit2D hit = Physics2D.Raycast(transform.position, Vector2.down, 0.1f, 1<<8);
if(hit.collider != null)
{
//說明碰到地面了
isGround = true;
//把跳躍的動畫關閉
ani.SetBool("Jump", false);
}
else
{
//沒碰到地面(在空中)
isGround = false;
ani.SetBool("Jump", true);
}
}
//玩家的死亡方法,因爲在敵人的代碼裏調用,所以此處是public
public void Die()
{
Hp--;
if (Hp <= 0)
{
//死亡
ani.SetTrigger("Die");
//刪除碰撞器。(因爲玩家死亡時,是從場景中掉落的,所以只要刪除碰撞器,不刪剛體)。
Destroy(GetComponent<Collider2D>());
//停止播放背景音樂
AudioManager.Instance.StopMusic();
//播放死亡音樂
AudioManager.Instance.PlaySound("死亡");
//讓玩家靜止
rBody.velocity = Vector2.zero;
//讓玩家靜止,即將它的速度設爲0。爲了避免玩家在不同情況下死亡後,向上跳的高度不同)
rBody.velocity = Vector2.zero;
//跳躍。給一個向上的力
rBody.AddForce(Vector2.up * 150f);
//延時。1秒之後播放
Invoke("Die2", 1f);
}
}
void Die2()
{
AudioManager.Instance.PlaySound("死亡2");
}
補充
使用字符串(即動畫名字)播放動畫
//
//移動動畫
ani.SetBool("Run", true);
將名稱(字符串)轉成ID後使用
每個動畫都有一個ID。
因爲系統開闢字符串比開闢整形更加費性能,如果一個動作需要多次使用,優化方法:
在最開始的時候(Start裏),把動作都轉成int類型,用的時候,只要用int類型就好。
//移動動畫
int run = Animator.StringToHash("Run");
//Debug.Log(run);打印ID
ani.SetBool(run,true);
//獲取數值
bool res = ani.GetBool(run);
靜態金幣+代碼CoinStatic
//觸發
private void OnTriggerEnter2D(Collider2D collision)
{
if(collision.tag == "Player")
{
//播放聲音
AudioManager.Instance.PlaySound("金幣");
//銷燬自己
Destroy(gameObject);
}
}
磚塊+代碼RockControl
//大磚塊
public GameObject Rock;
//小磚塊
public GameObject[] Rocks;
//寫完上面的代碼,需要到unity裏面關聯一下。
// Use this for initialization
void Start () {
}
private void OnCollisionEnter2D(Collision2D collision)
{
//如果玩家碰了我,並且碰撞點的法線向上(說明玩家是從線面碰到的)
if (collision.collider.tag == "Player" && collision.contacts[0].normal == Vector2.up)
{
//播放音樂
AudioManager.Instance.PlaySound("頂破磚");
//小磚塊會四散開來。首先遍歷一下
foreach(GameObject rock in Rocks)
{
//把父物體(大磚塊)設置爲空,小磚塊就沒有父物體了,會顯示在前面
rock.transform.parent = null;
//3D有爆炸力,2D沒有。首先,添加剛體。rock是4個小磚塊
Rigidbody2D rbody = rock.AddComponent<Rigidbody2D>();
//得到從整體的中心點到各個小磚塊中心點的向量。
Vector2 dir = rock.transform.position - transform.position;
//給力。dir沿着這個向量的方向*100的力
rbody.AddForce(dir * 900f);
//1秒之後銷燬
Destroy(rock, 1f);
}
//銷燬大磚塊
Destroy(gameObject);
}
}
箱子、頂出動態金幣+二者代碼
代碼:箱子BoxControl
//血量。(頂幾次)
public int Hp = 5;
//頂出來的物體
public GameObject goPre;
//音效名稱(傳進來)
public string sound;
void Start () {
}
private void OnCollisionEnter2D(Collision2D collision)
{
//如果玩家從下面頂撞
if (collision.collider.tag == "Player" && collision.contacts[0].normal == Vector2.up)
{
if(Hp > 0)
{
Hp--;
//頂出物品
//聲音
AudioManager.Instance.PlaySound(sound);
//實例化物品
Instantiate(goPre, transform.position, Quaternion.identity);
if(Hp <= 0)
{
//變成磚塊(就是下面的“沒了”)
//獲得動畫
GetComponent<Animator>().SetTrigger("Die");
}
}else
{
//箱子已經沒了。
//播放沒了的聲音
AudioManager.Instance.PlaySound("頂磚石塊");
}
}
}
代碼:動態金幣CoinControl
void Start () {
//獲得剛體
GetComponent<Rigidbody2D>().AddForce(Vector2.up * 150f);
//銷燬金幣
Destroy(gameObject, 1f);
}