24U3D開發(fā)之2D拾荒者

2D游戲拾荒者開發(fā)##

效果展示

一仗处、預(yù)支物的制作##

1.獲取資源: https://pan.baidu.com/s/1qYAozV2
2.圖片的截取.

截取圖片
截取效果

3.Player和Enemy的動畫制作.

1.把主角的6張圖片同時拖入到Hierarchy面板中顶霞,制動創(chuàng)建Animator蒲每,有Controller畅蹂,和對應(yīng)的動畫.
2.在把攻擊的圖片拖上去俭驮,自動創(chuàng)建攻擊動畫.同理把收到傷害的圖片拖上去陶贼,得到受到傷害的動畫.

制作過程
完成效果
Enemy敵人的制作
和Player的制作一樣翘悉,但是我們在制作Enemy2的時候茫打,可以不用從新創(chuàng)建一個Controller了.可以創(chuàng)建一個
Animator Override Controller,通過Enemy1創(chuàng)建Enemy2的動畫妖混,改變圖片從新創(chuàng)建一個新的預(yù)支物就可以.


OverriderController

3.Floor老赤,OutWall的Prefab的制作.

Floor,OutWall的制作

二制市、創(chuàng)建地圖##

游戲范圍展示
這里涉及到層的概念:我們要設(shè)計好層次關(guān)系抬旺,不然系統(tǒng)識別不了那個在前面.
我們吧外墻(OutWall),地板(Floor)設(shè)置為最底層(Background).
食物(friut息堂,soda)設(shè)置為Item嚷狞,敵人和Player設(shè)置為Role層.
層次的設(shè)定
Map管理腳本在Inspector中展示
腳本代碼管理:
public class MapManager : MonoBehaviour {


    public GameObject[] OutWalls;
    public GameObject[] Floors;
    public GameObject[] walls;
    public GameObject[] foods;
    public GameObject[] enemys;
    public GameObject exitPrefab;

    public  int line = 10;
    public  int row = 10;
    Transform mapHolder;

    private List<Vector2> positionList = new List<Vector2>();//用來保存在敵人,障礙物生成區(qū)域的位置信息
    private GameManger gameManager;




    int minCountWall = 2;//最少內(nèi)墻個數(shù)
    int maxCountWall = 8;//最多內(nèi)墻個數(shù)荣堰,隨機生成




    void Awake () {
        gameManager = this.GetComponent<GameManger>();
        //InitMap();

    }
    
    
    void Update () {
        
    }

    public void InitMap()
    {
        mapHolder = new GameObject("Map").transform;//穿件一個空物體用來管理生成的地圖
        //創(chuàng)建外圍墻和地板
        for (int i = 0; i < line; i++)
        {
            for (int j = 0; j < row; j++)
            {
                if (i == 0 || i == line - 1 || j == 0 || j == row - 1)
                {
                    int index = Random.Range(0, OutWalls.Length);
                    GameObject go=Instantiate(OutWalls[index], new Vector3(i, j, 0), Quaternion.identity)as GameObject;
                    go.transform.SetParent(mapHolder);
                }
                else
                {
                    int index = Random.Range(0, Floors.Length);
                    GameObject go=Instantiate(Floors[index],new Vector3(i,j,0),Quaternion.identity)as GameObject;
                    go.transform.SetParent(mapHolder);

                }
            }
        }

        positionList.Clear();//承儲敵人床未,障礙物區(qū)域的信息到list里面。
        for (int i = 2; i < line-2; i++)
        {
            for (int j = 2; j < row-2; j++)
            {
                positionList.Add(new Vector2(i,j));
            }
        }

        //創(chuàng)建障礙物
        int wallCount = Random.Range(minCountWall, maxCountWall + 1);
        InstantiateItem(wallCount,walls);

        //創(chuàng)建食物2-level*2
        int foodCount = Random.Range(2, GameManger.level*2+1);//創(chuàng)建的敵人個數(shù)與關(guān)卡有關(guān)系
        InstantiateItem(foodCount,foods);

        //創(chuàng)建敵人level/2
        int enemyCount = GameManger.level/ 2;
        InstantiateItem(enemyCount,enemys);

        //創(chuàng)建出口
        GameObject go1= Instantiate(exitPrefab, new Vector2(line - 2, row - 2), Quaternion.identity) as GameObject;
        go1.transform.SetParent(mapHolder);
    }

    private Vector2 RandomPosition()
    {
        int positionIndex = Random.Range(0, positionList.Count);
        Vector2 pos = positionList[positionIndex];//隨機拿到一個位置List里面的地點信息
        positionList.RemoveAt(positionIndex);//在把這個地點信息移除振坚,避免在同一個地點出現(xiàn)多個物體薇搁。
        return pos;
    }

    private GameObject RandomPrefab(GameObject[]prefabs)
    {
        int index = Random.Range(0, prefabs.Length);
        return prefabs[index];
    }

    private void InstantiateItem(int count,GameObject[] prefabs)
    {
        for (int i = 0; i < count; i++)
        {
            Vector2 pos = RandomPosition();
            GameObject enemyPrefab = RandomPrefab(prefabs);
            GameObject go = Instantiate(enemyPrefab, pos, Quaternion.identity);
            go.transform.SetParent(mapHolder);
        }
    }



}

三、Player和Enemy的動畫完善##

Player動畫Transition過渡參數(shù)詳解
Player動畫Transition過渡參數(shù)詳解2
Enemy動畫完善

四渡八、主角(Player)的移動邏輯##

主角身上的腳本控制
腳本展示:
public class Player : MonoBehaviour {


    public float smoothing = 1;
    public float restTime = 1;

    //聲音文件
    public AudioClip chop1Audio;
    public AudioClip chop2Audio;
    public AudioClip step1Audio;
    public AudioClip step2Audio;

    public AudioClip soda1Audio;
    public AudioClip soda2Audio;
    public AudioClip fruit1Audio;
    public AudioClip fruit2Audio;

    private float restTimer = 0;
    public Animator animator;
   
    [HideInInspector]public Vector2 targetPos = new Vector2(1, 1);//主角開始的位置
    private Rigidbody2D rigibody;
    private BoxCollider2D collider;


    
    void Start () {
        rigibody = GetComponent<Rigidbody2D>();
        collider = GetComponent<BoxCollider2D>();
        animator=GetComponent<Animator>();
    }
    
    
    void Update () {
        rigibody.MovePosition(Vector2.Lerp(transform.position, targetPos, smoothing * Time.deltaTime));

       // if (GameManger.Instance.food <= 0) return;

        restTimer += Time.deltaTime;
        if (restTimer < restTime) return;
        float h = Input.GetAxisRaw("Horizontal");//只會返回-1啃洋,0传货,1
        float v = Input.GetAxisRaw("Vertical");
        //print(h);
        //print(v);
        if (h>0)
        {
            v = 0;
        }
              
        if (h != 0 || v != 0)
        {
            GameManger.Instance.ReduceFood(1);
            //檢測
            collider.enabled = false;//設(shè)置為不可用,不然會檢測到自己
            RaycastHit2D hit=Physics2D.Linecast(targetPos,targetPos+new Vector2(h,v));
            collider.enabled = true;
            if (hit.transform == null)
            {
                targetPos += new Vector2(h, v);
                AudioManager._instance.RandomPlay(step1Audio,step2Audio);
               
            }
            else
            {
                switch (hit.collider.tag)
                {
                    case "OutWall":
                        break;
                    case "Wall":
                        animator.SetTrigger("Attack");
                        AudioManager._instance.RandomPlay(chop1Audio, chop2Audio);
                        hit.collider.SendMessage("TakeDamage");                     
                        break;
                    case "Food":
                        GameManger.Instance.AddFood(10);
                        targetPos += new Vector2(h, v);
                        AudioManager._instance.RandomPlay(step1Audio, step2Audio);
                        Destroy(hit.transform.gameObject);
                        AudioManager._instance.RandomPlay(fruit1Audio,fruit2Audio);
                        break;
                    case "Soda":
                        GameManger.Instance.AddFood(20);
                        targetPos += new Vector2(h, v);
                        AudioManager._instance.RandomPlay(step1Audio, step2Audio);
                        Destroy(hit.transform.gameObject);
                        AudioManager._instance.RandomPlay(soda1Audio, soda2Audio);
                        break;
                    case "Enemy":
                        break;
                }

            }
            GameManger.Instance.OnPlayerMove();//沒幀檢測有沒有到達終點
            restTimer = 0;

        }
        if (GameManger.Instance.food==0||GameManger.Instance.isEnd==true)
        {
            this.enabled = false;
        }
    }

    public void TakeDamage(int lossFood)
    {
        GameManger.Instance.ReduceFood(lossFood);
        animator.SetTrigger("Damager");
    }
}

五宏娄、控制敵人的移動##

敵人Enemy展示
代碼展示:
public class Enemy : MonoBehaviour {

    private Vector2 targetPosition;
    private Transform player;
    private Rigidbody2D rigidbody;

    public float smoothing = 3;
    private BoxCollider2D collider;
    private Animator animator;
    public int lossFood = 10;

    public AudioClip attackAudio;

    void Start()
    {
        player = GameObject.FindGameObjectWithTag("Player").transform;
        targetPosition = transform.position;
        rigidbody = GetComponent<Rigidbody2D>();
        collider = GetComponent<BoxCollider2D>();
        animator = GetComponent<Animator>();
        GameManger.Instance.enemyList.Add(this);//保存敵人到集合里面

    }

    void Update()
    {
        rigidbody.MovePosition(Vector2.Lerp(transform.position,targetPosition,smoothing*Time.deltaTime));
    }


    
    public void Move()
    {
        Vector2 offset = player.position - transform.position;
        if (offset.magnitude < 1.1f)
        {
            //攻擊
            animator.SetTrigger("Attack");
            AudioManager._instance.RandomPlay(attackAudio);
            player.SendMessage("TakeDamage",lossFood);

        }
        else
        {
            float x = 0;
            float y = 0;
            if (Mathf.Abs(offset.y) > Mathf.Abs(offset.x))//按照y軸移動
            {
                if (offset.y < 0)//向反向
                {
                    y = -1;
                }
                else//正向
                {
                    y = 1;
                }
            }
            else//按照x軸移動
            {
                if (offset.x > 0)
                {
                    x = 1;
                }
                else
                {
                    x = -1;
                }
            }
            //設(shè)置目標位置之前问裕,先做檢測;
            collider.enabled = false;
            RaycastHit2D hit = Physics2D.Linecast(targetPosition, targetPosition+ new Vector2(x, y));
            collider.enabled = true;
            if (hit.transform == null)
            {
                targetPosition += new Vector2(x, y);
            }
            else
            {
                if (hit.collider.tag=="Food"||hit.collider.tag=="Soda")
                {
                    targetPosition += new Vector2(x, y);
                }
            }
            
        }
    }




}


六孵坚、游戲管理腳本(對整個游戲進行管理)##

public class GameManger : MonoBehaviour {

    public static int level = 1;//當(dāng)前關(guān)卡
    public int food = 100;

    public AudioClip dieClip;


    private static GameManger _instance;

    public static GameManger Instance
    {
        get
        {
            return _instance;
        }
    }

    [HideInInspector]public bool isEnd = false;
    public List<Enemy> enemyList = new List<Enemy>();
    private bool sleepStep = true;//控制敵人移動的限定粮宛;
    private Text foodText;
    private Text failText;
    private Image dayImage;
    private Text dayText;
    private Player player;
    private MapManager mapManager;

    void Awake()
    {
       
        _instance = this;
        //DontDestroyOnLoad(gameObject);
        InitGame();

    }


    void InitGame()
    {
        //初始化地圖
        mapManager = GetComponent<MapManager>();
        mapManager.InitMap();
        food = PlayerPrefs.GetInt("Food", 10);
        //初始化UI
        foodText = GameObject.Find("FoodText").GetComponent<Text>();
        UpdateFoodText(0);
        failText = GameObject.Find("FailText").GetComponent<Text>();
        failText.enabled = false;
        player = GameObject.FindGameObjectWithTag("Player").GetComponent<Player>();
        mapManager = GetComponent<MapManager>();
        dayImage = GameObject.Find("DayImage").GetComponent<Image>();
        dayText = GameObject.Find("DayText").GetComponent<Text>();
        dayText.text = "Day" + " " + level;
        Invoke("HideBlack", 1);

        //初始化參數(shù)
        isEnd = false;
        enemyList.Clear();
    }

    void UpdateFoodText(int foodChange)
    {
        if (foodChange == 0)
        {
            foodText.text = "Food:" + food;
        }
        else
        {
            string str = "";
            if (foodChange<0)
            {
                str = foodChange.ToString();
            }
            else
            {
                str = "+" + foodChange;
            }
            foodText.text = str+" " + "Food:" + food;
        }
        
    }



    public void ReduceFood(int count)
    {
        food -= count;
        UpdateFoodText(-count);
        if(food<=0)
        {
            failText.enabled = true;
            AudioManager._instance.StopBgMusic();
            AudioManager._instance.RandomPlay(dieClip);
        }
    }

    public void AddFood(int count)
    {
        food += count;
        UpdateFoodText(count);
    }


    public void OnPlayerMove()//通知敵人行走,邏輯卖宠,主角走2步巍杈,敵人走一步
    {
        if (sleepStep == true)
        {
            sleepStep = false;
        }
        else
        {
            foreach (var enemy in enemyList)
            {
                enemy.Move();
            }
            sleepStep = true;
        }
        //檢測有沒有到達終點
        if (player.targetPos.x==mapManager.line-2&&player.targetPos.y==mapManager.row-2)
        {
            PlayerPrefs.SetInt("Food", food);
            isEnd = true;
            //加載下一個關(guān)卡
            SceneManager.LoadScene(0);
            //Application.LoadLevel(Application.loadedLevel);//從新加載本關(guān)卡
        }
    }

    void OnLevelWasLoaded()
    {
        //PlayerPrefs.GetFloat("level", 1);
        level++;
        //PlayerPrefs.SetFloat("level", level);
       // InitGame();
    }

    void HideBlack()
    {
        dayImage.gameObject.SetActive(false);    
    }
}

七、Player對敵人扛伍,食物筷畦,和墻里面障礙物的處理##

對內(nèi)墻的攻擊處理:
public class Wall : MonoBehaviour {

    public int hp = 2;
    public Sprite damageSprite;//受到攻擊的圖片


    public void TakeDamage()
    {
        hp -= 1;
        GetComponent<SpriteRenderer>().sprite = damageSprite;
        if(hp==0)
        {
            Destroy(this.gameObject);
        }
    }
}

八、食物的UI處理##

UI處理
UI處理2

九刺洒、聲音文件的添加##

聲音文件很重要鳖宾,在適當(dāng)?shù)臅r候,合適的位置添加聲音文件.
腳本管理:
public class AudioManager : MonoBehaviour {

    public float minPitch = 0.9f;
    public float maxPitch = 1.1f;

    public static AudioManager _instance;

    public AudioSource efxSouce;
    public AudioSource bgSource;

    void Awake()
    {
        _instance = this;
    }
   


    public void RandomPlay(params AudioClip[]clips)//播放聲音文件
    {
        float pitch = Random.Range(minPitch,maxPitch);
        int index = Random.Range(0,clips.Length);
        AudioClip clip = clips[index];
        efxSouce.clip = clip;
        efxSouce.pitch = pitch;//播放速度
        efxSouce.Play();


    }

    public void StopBgMusic()//游戲結(jié)束時作媚,結(jié)束背景音樂的播放
    {
        bgSource.Stop();
    }



}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末攘滩,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子纸泡,更是在濱河造成了極大的恐慌漂问,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件女揭,死亡現(xiàn)場離奇詭異蚤假,居然都是意外死亡,警方通過查閱死者的電腦和手機吧兔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門磷仰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人境蔼,你說我怎么就攤上這事灶平。” “怎么了箍土?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵逢享,是天一觀的道長。 經(jīng)常有香客問我吴藻,道長瞒爬,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮侧但,結(jié)果婚禮上矢空,老公的妹妹穿的比我還像新娘。我一直安慰自己禀横,他們只是感情好屁药,可當(dāng)我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著燕侠,像睡著了一般者祖。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上绢彤,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音蜓耻,去河邊找鬼茫舶。 笑死,一個胖子當(dāng)著我的面吹牛刹淌,可吹牛的內(nèi)容都是我干的饶氏。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼有勾,長吁一口氣:“原來是場噩夢啊……” “哼疹启!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔼卡,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤喊崖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后雇逞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體荤懂,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年塘砸,在試婚紗的時候發(fā)現(xiàn)自己被綠了节仿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡掉蔬,死狀恐怖廊宪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情女轿,我是刑警寧澤箭启,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站谈喳,受9級特大地震影響册烈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一赏僧、第九天 我趴在偏房一處隱蔽的房頂上張望大猛。 院中可真熱鬧,春花似錦淀零、人聲如沸挽绩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽唉堪。三九已至,卻和暖如春肩民,著一層夾襖步出監(jiān)牢的瞬間唠亚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工持痰, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留灶搜,地道東北人星爪。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓官硝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贼急。 傳聞我的和親對象是個殘疾皇子患雏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容