理解siki学院吃豆人案例脚本

Gamemanager.cs(全局控制)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Collections;
using UnityEngine.SceneManagement;//引入场景管理库
using UnityEngine.UI;//引入ui库
public class GameManager : MonoBehaviour {
    private static GameManager _instance;
    public static GameManager Instance//将Gamemanager实例化,
    {
        get
        {//这一段目前并不太理解,老师说是做单例?
            return _instance;
        }
    }

    public GameObject Pacman;//定义主角Gameobject
    public GameObject Blinky;//定义四个敌人Gameobject
    public GameObject Clyde;
    public GameObject Inky;
    public GameObject Pinky;
    public GameObject Win;

    private GameObject RestartClick;//定义私有Gameobject RestartClick

    public GameObject gameover;//定义游戏结束图片
    public AudioClip StartClip;//定义AudioClip开头音乐
    public int score,remain;//定义整型变量储存分数和剩余豆子数
    public Text scoretext;//定义分数文本物件
    public Text remaintext;//定义剩余数文本物件
    public GameObject startCountDownPrefab;//定义倒计时动画的预制体
    public bool Wined=false,died=false;//定义bool变量"是否赢了"和"是否死了"
    public bool isSuperPacman = false;//定义bool变量"是不是无敌状态"
    public List<int> rawIndex = new List<int> {0,1,2,3};//备用数组,要使用时可以从中取数
    public List<int> usingIndex = new List<int> ();//实际使用的数组
    private List<GameObject> pacdotGos = new List<GameObject>();//一个Gameobject数组用来存地图上的豆子物体
    private void Start(){ 
        score = 0;//刚开始时分数赋初值0(由于吃豆人出生的瞬间与3个豆子发生碰撞取得分数,但玩家并未采取操作,所以将这3个豆子移除了分数才能从0开始)
        RestartClick = GameObject.Find ("RestartButton");//RestartClick对应目录中的重新开始按钮
        AudioSource.PlayClipAtPoint (StartClip,new Vector3(23f,16f,-10f));//游戏一开始就播放4秒长度的音乐
        StopGameState ();//冻结游戏
        StartCoroutine (PlayStartCountDown());//播放倒计时动画
        Invoke ("Continue",4f);//因为倒计时动画是4秒,所以4秒后解除冻结
        Invoke ("CreateSuperPacdot",10f);//游戏开始10秒后生成道具豆子
    }
    private void Update(){//每帧都要刷新
        remain = pacdotGos.Count;//刷新remain变量的值为pacdotGos数组里的元素数量,也就是场景中仍然可用的豆子数量
        remaintext.text = "  " + remain;//修改剩余数文本
        if (score >= 0 && score <= 9)//这些if是为了让分数数字总是显示在合适的位置
            scoretext.text = "   " + score;

        if (score >= 10 && score <= 999)
            scoretext.text = "  " + score;
        if (score >= 1000 && score <= 99999)
            scoretext.text = " " + score;
        if (score >= 100000 && score <= 9999999)
            scoretext.text = "" + score;

        if (pacdotGos.Count==0) {//当豆子被吃完,也就是数组长度为0
            Wined = true;//更新游戏状态为赢
            Win.GetComponent<SpriteRenderer> ().color = new Color (255f,255f,255f,255f);//显示胜利图片
        }
        if (Wined) {
            StopGameState ();//冻结游戏
        }
        if (died || Wined) {//只有当死了或者赢了,重新开始按钮才显示
            RestartClick.SetActive (true);

        }
        else {
            RestartClick.SetActive (false);
        }
    }
    IEnumerator PlayStartCountDown(){//这一块也不太懂,叫做协程?
        GameObject go = Instantiate (startCountDownPrefab);//实例化倒计时动画
        yield return new WaitForSeconds (4f);//四秒后停止,因为动画播放一次是四秒
        Destroy (go);//播放一次就摧毁这个临时物体


        GetComponent<AudioSource> ().Play();//开始播放游戏进行音乐
    }
    private void Awake(){
        _instance = this;//这个语句用来实例化
        int tempCount = rawIndex.Count;//为了让循环次数正确定义一个临时变量
        for(int i=0;i<tempCount;i++){
            int tempIndex = Random.Range (0,rawIndex.Count);//在剩下的备用数组里获得一个随机下标
            usingIndex.Add (rawIndex [tempIndex]);//把下标对应的数加在usingIndex数组里面
            rawIndex.RemoveAt (tempIndex);//每次给usingIndex里加数就移除备用数组的对应数字
        }
        foreach(Transform child in GameObject.Find("Maze").transform){
            pacdotGos.Add (child.gameObject);
        }//将地图上所有点更新给pacdotGos数组
    }
    private void ResetDots(){
        pacdotGos.Clear ();//清空存豆子的数组
        foreach(Transform child in GameObject.Find("Maze").transform){
            child.gameObject.SetActive (true);//将之前因为被主角碰撞到禁用的豆子都重设为可用
            pacdotGos.Add (child.gameObject);//将所有的点添加给pacdotGos数组里
        }
    }
    public void EatPacdot(GameObject dot){
        pacdotGos.Remove (dot);//每吃掉一个豆子数组对应删除一个元素

    }
    public void EatSuperPacdot(){//当吃掉道具豆
        FreezeEnemy ();//冻结敌人

        Invoke ("CreateSuperPacdot", 8f);//8秒后再生成一个道具豆
        isSuperPacman = true;//主角变成无敌状态
        StartCoroutine (RecoveryEnemy());//执行恢复敌人的函数
    }
    private void FreezeEnemy(){//冻结敌人的函数,移动脚本都禁用,通过调整RGB值实现半透明状态
        Blinky.GetComponent<GhostMove> ().enabled = false;
        Clyde.GetComponent<GhostMove> ().enabled = false;
        Pinky.GetComponent<GhostMove> ().enabled = false;
        Inky.GetComponent<GhostMove> ().enabled = false;
        Blinky.GetComponent<SpriteRenderer> ().color = new Color (0.7f, 0.7f, 0.7f, 0.7f);
        Clyde.GetComponent<SpriteRenderer> ().color = new Color (0.7f, 0.7f, 0.7f, 0.7f);
        Inky.GetComponent<SpriteRenderer> ().color = new Color (0.7f, 0.7f, 0.7f, 0.7f);
        Pinky.GetComponent<SpriteRenderer> ().color = new Color (0.7f, 0.7f, 0.7f, 0.7f);
    }
    private void DisFreezeEnemy(){//解冻敌人,和冻结敌人的相反
        Blinky.GetComponent<GhostMove> ().enabled = true;
        Clyde.GetComponent<GhostMove> ().enabled = true;
        Pinky.GetComponent<GhostMove> ().enabled = true;
        Inky.GetComponent<GhostMove> ().enabled = true;
        Blinky.GetComponent<SpriteRenderer> ().color = new Color (1f, 1f, 1f, 1f);
        Clyde.GetComponent<SpriteRenderer> ().color = new Color (1f, 1f, 1f, 1f);
        Inky.GetComponent<SpriteRenderer> ().color = new Color (1f, 1f, 1f, 1f);
        Pinky.GetComponent<SpriteRenderer> ().color = new Color (1f, 1f, 1f, 1f);
    }
    IEnumerator RecoveryEnemy(){
        yield return new WaitForSeconds (3f);//三秒后解冻敌人
        DisFreezeEnemy ();
        isSuperPacman = false;//主角无敌状态取消
    }
    public void GotoPlayScene(){//切换到play场景
        SceneManager.UnloadSceneAsync ("StartPanel");//卸载StartPanel场景
        SceneManager.LoadScene ("Main");//装载Main场景
    }
    public void GotoStartPanel(){//没用上
        SceneManager.UnloadSceneAsync ("Main");
        SceneManager.LoadScene ("StartPanel");
    }
    public void Exit(){//退出按钮用的脚本
        Application.Quit();//关闭应用的语句
    }
    private void CreateSuperPacdot(){
        if (pacdotGos.Count<8) {
            return;//当剩余豆子不足8个时不再生成道具豆
        }
        int tempindex = Random.Range (0,pacdotGos.Count);//随机选一个剩下的豆子作为道具豆
        pacdotGos [tempindex].transform.localScale = new Vector3 (3,3,3);//将选中的豆子放大3倍
        pacdotGos [tempindex].GetComponent<Pacdot> ().isSuperPacDot = true;//将附属脚本里的isSuperPacdot变量变真
    }
    private void StopGameState(){//将各个物体的移动脚本都禁用来实现冻结
        Blinky.GetComponent<GhostMove> ().enabled = false;
        Clyde.GetComponent<GhostMove> ().enabled = false;
        Pinky.GetComponent<GhostMove> ().enabled = false;
        Inky.GetComponent<GhostMove> ().enabled = false;
        Pacman.GetComponent<PacmanMove> ().enabled = false;
    }
    public void Continue(){//反过来解冻
        Blinky.GetComponent<GhostMove> ().enabled = true;
        Clyde.GetComponent<GhostMove> ().enabled = true;
        Pinky.GetComponent<GhostMove> ().enabled = true;
        Inky.GetComponent<GhostMove> ().enabled = true;
        Pacman.GetComponent<PacmanMove> ().enabled = true;
    }
    public void RestartGame(){//当点击重新开始按钮时执行这个脚本
        StopGameState ();//冻结游戏
        score = 0;//分数归0
        ResetDots ();//重置场景中的豆子
        gameover.GetComponent<SpriteRenderer> ().color = new Color (0,0,0,0);//将gameover或win的图片都设置为全透明
        Win.GetComponent<SpriteRenderer> ().color = new Color (0,0,0,0);
        Pacman.SetActive(true);//如果死了将主角复活
        StartCoroutine (PlayStartCountDown());//倒计时函数
        Invoke ("Continue",4f);//倒计时结束后解冻
        Blinky.GetComponent<GhostMove> ().Restart();//通过各个物体的Restart函数重置他们的位置
        Clyde.GetComponent<GhostMove> ().Restart();
        Pinky.GetComponent<GhostMove> ().Restart();
        Inky.GetComponent<GhostMove> ().Restart();
        Pacman.GetComponent<PacmanMove> ().Restart();
        Pacman.GetComponent<CircleCollider2D> ().enabled = true;//启用主角的碰撞体

        died = false;//取消死了或赢了的状态
        Wined = false;
    }
}

Ghostmove.cs(敌人相关功能)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GhostMove : MonoBehaviour {
    private int index=0;//index是移动目标点的序号
    public GameObject[] wayPointsGos;//储存可选的巡逻路径
    private List<Vector3> wayPoints = new List <Vector3> ();//储存要经过的路径点(在摆放路径点时要保证两两路径点相连不会与墙壁碰撞体相交)
    public float speed=0.15f;//单位移动速度
    public GameObject gameover;//gameover图片

    private Vector3 StartPos;//每个敌人都有各自的startpos
    private void Start(){
        StartPos=transform.position + new Vector3 (0,3,0);//startpos设置为出生点上方3个单位
        LoadAPath (wayPointsGos[GameManager.Instance.usingIndex[GetComponent<SpriteRenderer>().sortingOrder-2]]);//根据敌人的自身序号-2来对应选择随机生成的usingindex数组里的路径
    }
    private void FixedUpdate () //目前还不知道FixedUpdate和Update的区别
    {
        if (transform.position != wayPoints [index]) //如果没有到达目标点
        {
            Vector2 temp = Vector2.MoveTowards (transform.position, wayPoints [index], speed);//用MoveTowards函数和MovePosition函数控制向目标点移动
            GetComponent<Rigidbody2D> ().MovePosition (temp);
        } 
        else 
        {//如果到达路径点
            index +=1;//index加一,目标点设为数组的下一个元素
            if (index >= wayPoints.Count) {
                index = 0;//控制满一圈后index的重置
            }
        }
        Vector2 dir = wayPoints [index] - transform.position;
        GetComponent<Animator> ().SetFloat ("DirX",dir.x);
        GetComponent<Animator> ().SetFloat ("DirY",dir.y);
        //用目标点和当前位置的差值的x、y值来控制敌人移动动画的播放
    }

    private void LoadAPath(GameObject go){
        wayPoints.Clear ();//清空路径点数组
        foreach (Transform t in go.transform) {
            wayPoints.Add (t.position);
        }//根据对应的预设路径补全路径点数组
        wayPoints.Insert (0,StartPos);//为了能让敌人回到原位,在路径点数组前后加上startpos那个点
        wayPoints.Add (StartPos);
    }
    public void Restart(){
        gameObject.transform.position = StartPos- new Vector3(0f,3f,0f);//重置位置
        index = 0;//重置目标点
    }
    public void deleteGameoverImage(){
        gameover.GetComponent<SpriteRenderer> ().color = new Color (255,255,255,255);//没用上
    }
    private void OnTriggerEnter2D(Collider2D collision)//碰撞函数
    {
        if (collision.gameObject.name == "Pacman") //若碰到主角
        {
            if (GameManager.Instance.isSuperPacman) {//若主角无敌
                transform.position = StartPos - new Vector3 (0,3,0);//打回老巢
                index = 0;
                GameManager.Instance.score += 500;//分数+500
            } 
            else{
                gameover.GetComponent<SpriteRenderer> ().color = new Color (255,255,255,255);//显示gameover图片
                GameManager.Instance.died = true;//主角状态为死亡
                collision.gameObject.SetActive (false);//禁用但不删除主角
            }
        }
    }
}

Pacmanmove.cs(主角相关功能)

using UnityEngine;

public class PacmanMove : MonoBehaviour
{
    //吃豆人的移动速度
    public float speed = 0.35f;
    //吃豆人下一次移动将要去的目的地
    private Vector2 dest = Vector2.zero,StartPos;
    private void Start()
    {
        //保证吃豆人在游戏刚开始的时候不会动
        dest = transform.position;
        StartPos = transform.position;
    }

    private void FixedUpdate()
    {
        //插值得到要移动到dest位置的下一次移动坐标
        Vector2 temp = Vector2.MoveTowards(transform.position, dest, speed);
        //通过刚体来设置物体的位置
        GetComponent<Rigidbody2D>().MovePosition(temp);
        //必须先达到上一个dest的位置才可以发出新的目的地设置指令
        if ((Vector2)transform.position == dest)
        {//通过WASD或方向键来控制dest目标点的变化
            if ((Input.GetKey(KeyCode.UpArrow) || Input.GetKey(KeyCode.W)) && Valid(Vector2.up))
            {
                dest = (Vector2)transform.position + Vector2.up;//dest位置y+1单位
            }
            if ((Input.GetKey(KeyCode.DownArrow) || Input.GetKey(KeyCode.S)) && Valid(Vector2.down))
            {
                dest = (Vector2)transform.position + Vector2.down;
            }
            if ((Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A)) && Valid(Vector2.left))
            {
                dest = (Vector2)transform.position + Vector2.left;
            }
            if ((Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D)) && Valid(Vector2.right))
            {
                dest = (Vector2)transform.position + Vector2.right;
            }
            //通过计算目标点和当前位置的差值获取移动方向
            Vector2 dir = dest - (Vector2)transform.position;
            //把获取到的移动方向设置给动画状态机来播放正确的动画
            GetComponent<Animator>().SetFloat("DirX", dir.x);
            GetComponent<Animator>().SetFloat("DirY", dir.y);
        }
    }
    public void Restart(){//重置位置和移动目标点
        gameObject.transform.position = StartPos;
        dest = transform.position;
    }
    //检测将要去的位置是否可以到达
    private bool Valid(Vector2 dir)
    {
        //记录下当前位置
        Vector2 pos = transform.position;
        //从将要到达的位置向当前位置发射一条射线,并储存下射线信息
        RaycastHit2D hit = Physics2D.Linecast(pos + dir, pos);
        //返回此射线是否打到的是吃豆人自身上的碰撞器,不是其他collider
        return (hit.collider == GetComponent<Collider2D>());
    }
}

Pacdot.cs(豆子相关功能)

using UnityEngine;

public class Pacdot : MonoBehaviour
{
    public bool isSuperPacDot = false;
    public GameObject scoretext;
    public GameObject remaindots;
    private void OnTriggerEnter2D(Collider2D collision){
        if(collision.gameObject.name == "Pacman"){//碰撞到主角
            if (isSuperPacDot) {//如果是道具豆
                GameManager.Instance.EatPacdot (gameObject);//执行Gamemanager里的EatPacdot函数
                GameManager.Instance.EatSuperPacdot ();//执行Gamemanager里的EatSuperPacdot函数
                gameObject.SetActive (false);//禁用被碰撞到的豆子
                isSuperPacDot = false;//取消超级豆状态
                gameObject.transform.localScale = new Vector3 (1,1,1);//恢复原型
                GameManager.Instance.score += 100;//加100分
            } 
            else {//普通豆子时
                GameManager.Instance.EatPacdot (gameObject);
                gameObject.SetActive (false);
                GameManager.Instance.score += 10;
            }
        }
    }
}

ScreenWindowSetting.cs(游戏运行窗口的设置)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ScreenWindowSetting : MonoBehaviour {

    // Use this for initialization
    void Start () {
        Screen.SetResolution (1024,768,false);//设置运行窗口大小1024*768,不全屏
        /*如果不通过脚本强制设置运行窗口的大小,运行时自动匹配的窗口会导致ui的布局混乱,所以给两个场景的maincamera添加这个脚本之后无论是unity的启动动画还是游戏运行都是强制设置的分辨率*/
    }

    // Update is called once per frame
    void Update () {

    }
}
  • 1
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值