Unity新手入门项目——AngryBird(愤怒的小鸟)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档




前言

这个游戏算是本Unity菜鸡真正意义上从头到尾跟着教程,一步步踩坑到完成的游戏了。

写这篇博客主要是用于总结学习该游戏项目,嗯,下面开始吧。

(PS:这个游戏是跟着siki学院的愤怒的小鸟教程做的,b站地址: 【SiKi学院Unity】Unity初级案例 - 愤怒的小鸟_哔哩哔哩_bilibili

  官网的课程资料、源码及笔记下载地址: http:// http://www.sikiedu.com/course/134)


提示:以下是本篇文章正文内容,下面案例可供参考

一、游戏逻辑与设计

本款游戏作为一个入门级的Unity项目,它的实现逻辑并不复杂,首先把游戏场景分为三个:

  • 加载界面
  • 关卡选择界面
  • 游戏界面

其中,加载界面和关卡选择界面,可以选择Unity自带的UI功能进行实现,也就是用Image来显示背景图片和各个按键等组件布局;

关于游戏界面,例如小鸟、小猪、木块、背景和草地等对象,这里是通过新建一个空物体,然后添加图片的形式进行实现,然后例如暂停窗口、胜利窗口、失败窗口就可以使用UI进行实现,把所有窗口放在一个Canvas里,然后默认取消显示,当达成目标功能时(例如关卡胜利、失败,点击暂停按键等),就将它对应的组件设置为激活状态,这样就达成了界面显示的功能;

然后是关于游戏的逻辑了,由于愤怒的小鸟它主要的游戏核心,其实就是——碰撞。

所以在这里,绝大部分的游戏逻辑其实都是通过碰撞和触发进行实现,我们把小鸟、小猪、障碍物等组件加上刚体和碰撞器,然后根据需求针对特殊的个体组件添加触发器,然后我们可以通过判断碰撞和触发的状态,来决定是否发生了游戏对象的逻辑碰撞,然后选择执行对应代码。




二、游戏场景搭建




1.游戏背景

游戏背景就是由几个图片(背景图片、地面、草丛)拼接而成,并给地面添加一个碰撞器(BoxCollider2D),以便小鸟和敌方单位不会一直落下。

2.玩家模块

玩家模块由以下几个对象组成:

  • 弹弓左部
  • 弹弓右部
  • 当前小鸟
  • 预备小鸟

对于小鸟,需要添加其刚体与碰撞器组件,并根据不同小鸟的大小,调整碰撞范围;

关于小鸟的“弹弓模拟”操作,这里使用了Spring Joint2D组件进行实现,中心点为小鸟中心,左右两个点分别设置在左弹弓和右弹弓上的合适位置,然后可以根据情况调整距离和频率,这样就可以初步实现类似弹弓弹簧的效果(目前还无法飞出);

接下来关于拖拽小鸟,形成画线的功能,这里使用LineRender进行画线操作,在脚本中,当可以进行画线操作时(当前小鸟已经激活,但是还没有飞行),设置其每一段Line的两点并画线;

    /// <summary>
    /// 划线
    /// </summary>
    public void Line()
    {
        right.enabled = true;
        left.enabled = true;

        right.SetPosition(0, rightPos.position);
        right.SetPosition(1, this.transform.position);

        left.SetPosition(0, leftPos.position);
        left.SetPosition(1, this.transform.position);
    }

3.敌人模块

敌人模块就是靠自己进行发挥了,针对不同的物体对象(小猪、木块、木条、铁块、柱子...)设置其刚体和碰撞器(主要是碰撞体大小),然后设置其血量(最小和最大承受速度),受伤图片等等其它的变量,然后根据自己的想象和设计,设计出不同的关卡;

                                        

三、游戏代码模块

1.小鸟(包括特殊小鸟)

通过控制canMove来区分当前小鸟和等待小鸟的状态,当该小鸟为激活状态时,canMove为true,可以执行Line(弹弓画线)和Fly(飞行过程)方法,进行弹弓的操控与飞行操作,当飞行状态时,重新置canMove为false(防止重复操作),其中控制小鸟的操作由鼠标来执行,在代码中即是,在OnMouseUp、OnMouseDown来进行监听;

当飞行过程中,可以通过点击鼠标调用ShowSkill方法执行特殊小鸟的技能操作,这个方法可以写成虚方法,在后面的特殊小鸟中,进行重写并调用;当该小鸟飞出后,通过延时调用Next方法,重新销毁当前小鸟,并激活下一个等待小鸟;

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

public class Bird : MonoBehaviour
{
    public bool isClick = false;
    
    public float maxDis = 1.5f;
    [HideInInspector]
    public SpringJoint2D sp;
    protected Rigidbody2D rg;

    public LineRenderer right;
    public LineRenderer left;
    public Transform rightPos;
    public Transform leftPos;

    public GameObject boom;
    protected TestMyTrail myTrail;
    [HideInInspector]
    public bool canMove = false;
    public float amooth = 3;

    public AudioClip select;
    public AudioClip fly;
    private bool isFlay;
    public bool isReleased = false;

    public Sprite hurt;
    public SpriteRenderer render;

    public void Awake()
    {
        sp = GetComponent<SpringJoint2D>();
        rg = GetComponent<Rigidbody2D>();
        render = GetComponent<SpriteRenderer>();
        myTrail = GetComponent<TestMyTrail>();
        
    }
    private void OnMouseDown()
    {
        if (canMove)
        {
            AudioPlay(select);
            isClick = true;
            rg.isKinematic = true;
        }
    }

    private void OnMouseUp()
    {
        if (canMove)
        {
            isClick = false;
            rg.isKinematic = false;
            Invoke("Fly", 0.1f);
            right.enabled = false;
            left.enabled = false;

            canMove = false;
        }
    }

    public void Update()
    {
        //如果点击的是UI界面,则直接返回
        if (EventSystem.current.IsPointerOverGameObject())
        {
            return;
        }


        if (isClick)
        {
            this.transform.position = Camera.main.ScreenToWorldPoint(Input.mousePosition);

            this.transform.position += new Vector3(0, 0, -Camera.main.transform.position.z);

            if(Vector3.Distance(this.transform.position,rightPos.position) > maxDis)
            {
                Vector3 pos = (this.transform.position - rightPos.position).normalized;
                pos *= maxDis;
                this.transform.position = pos + rightPos.position;
            }

            Line();
        }
        //相机跟随
        CamereMove();
        //飞行时,点击左键
        if (isFlay)
        {
            if (Input.GetMouseButtonDown(0))
            {
                ShowSkill();
            }
        }
    }
    public void CamereMove()
    {
        float posX = this.transform.position.x;
        Camera.main.transform.position = Vector3.Lerp(Camera.main.transform.position, new Vector3(Mathf.Clamp(posX,0,17),Camera.main.transform.position.y,
            Camera.main.transform.position.z), amooth*Time.deltaTime);
    }

    public void Fly()
    {
        isReleased = true;
        isFlay = true;
        AudioPlay(fly);
        myTrail.StartTrail();
        sp.enabled = false;
        Invoke("Next", 3);
    }

    /// <summary>
    /// 划线
    /// </summary>
    public void Line()
    {
        right.enabled = true;
        left.enabled = true;

        right.SetPosition(0, rightPos.position);
        right.SetPosition(1, this.transform.position);

        left.SetPosition(0, leftPos.position);
        left.SetPosition(1, this.transform.position);
    }

    public virtual void Next()
    {
        Gamemanager._instance.birds.Remove(this);
        Destroy(this.gameObject);
        Instantiate(boom, this.transform.position, Quaternion.identity);
        Gamemanager._instance.NextBird();
    }

    public void OnCollisionEnter2D(Collision2D collision)
    {
        isFlay = false;
        myTrail.ClearTrail();
       
    }

    public void AudioPlay(AudioClip clip)
    {
        AudioSource.PlayClipAtPoint(clip,this.transform.position);
    }

    public virtual void ShowSkill()
    {
        isFlay = false;
    }

    public void Hurt()
    {
        render.sprite = hurt;
    }
}

剩下的黄鸟(加速)、绿鸟(回旋)和黑鸟(爆炸),就是继承了redbird这个类,然后根据需求,重写ShowSkill方法即可;

public class YellowBird : Bird
{
    public override void ShowSkill()
    {
        base.ShowSkill();
        rg.velocity *= 2;
    }
}

 

public class GreenBird : Bird
{
    public override void ShowSkill()
    {
        base.ShowSkill();
        Vector3 speed = rg.velocity;
        speed.x *= -1;
        rg.velocity = speed;
    }
}

 其中,BlackBird因为要通过触发判断爆炸效果,并且爆炸后直接进行销毁,所以要额外多写几个方法进行实现

public class BlackBird : Bird
{
    public List<Pig> blocks = new List<Pig>();

    /// <summary>
    /// 进入触发区域
    /// </summary>
    /// <param name="collision"></param>
    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Enemy")
        {
            blocks.Add(collision.gameObject.GetComponent<Pig>());
        }
        
    }

    /// <summary>
    /// 退出触发区域
    /// </summary>
    /// <param name="collision"></param>
    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "Enemy")
        {
            blocks.Remove(collision.gameObject.GetComponent<Pig>());
        }
    }

    public override void ShowSkill()
    {
        base.ShowSkill();
        if( blocks!=null && blocks.Count > 0)
        {
            for(int i = 0; i < blocks.Count; i++)
            {
                blocks[i].Dead();
            }
        }

        OnClear();
    }

    public void OnClear()
    {
        rg.velocity = Vector3.zero;
        Instantiate(boom, this.transform.position, Quaternion.identity);
        render.enabled = false;
        GetComponent<CircleCollider2D>().enabled = false;
        myTrail.ClearTrail();
    }

    public override void Next()
    {
        Gamemanager._instance.birds.Remove(this);
        Destroy(this.gameObject);
        Gamemanager._instance.NextBird();
    }
}

 

2.敌人(包括小猪、木块等障碍物)

这里主要就是调整敌方的“血量”,但是这里的血量并不是一点一点扣除的,而是进行一个判断,当该物体碰撞的对象是Player(小鸟),并且当

  • 碰撞速度>maxspeed时,敌方死亡
  • minspeed<碰撞速度<maxspeed时,敌方调整为受伤状态
  • 碰撞速度<minspeed时,敌方不受伤

然后写一个Dead方法,用于处理死亡后的操作(播放死亡音乐、爆炸特效、销毁物体等)

public class Pig : MonoBehaviour
{
    public float maxSpeed = 10;
    public float minSpeed = 4;
    private SpriteRenderer render;
    public Sprite hurt;
    public GameObject boom;
    public GameObject score;
    public bool isPig = false;
    public AudioClip hurtClip;
    public AudioClip dead;
    public AudioClip birdCollision;


    private void Awake()
    {
        render = GetComponent<SpriteRenderer>();
    }

    private void OnCollisionEnter2D(Collision2D collision)
    {
        if(collision.gameObject.tag == "Player")
        {
            AudioPlay(birdCollision);
            collision.transform.GetComponent<Bird>().Hurt();
        }

        if(collision.relativeVelocity.magnitude > maxSpeed)
        {
            Dead();
        }
        else if( collision.relativeVelocity.magnitude>minSpeed && collision.relativeVelocity.magnitude < maxSpeed)
        {
            AudioPlay(hurtClip);
            render.sprite = hurt;
        }
    }


    public void Dead()
    {
        if (isPig)
        {
            Gamemanager._instance.pigs.Remove(this);
        }
        AudioPlay(dead);
        Destroy(this.gameObject);
        Instantiate(boom, this.transform.position, Quaternion.identity);
        GameObject go = Instantiate(score, this.transform.position + new Vector3(0,0.5f,0), Quaternion.identity);
        Destroy(go, 1.5f);
    }

    public void AudioPlay(AudioClip clip)
    {
        AudioSource.PlayClipAtPoint(clip, this.transform.position);
    }
}

3.游戏管理器

游戏管理器用于控制游戏逻辑,这里定义两个列表,用于存储所有小鸟和所有小猪,

在开始时,激活小鸟列表的第一个对象为当前小鸟,其它小鸟等待,当当前小鸟飞行完成后,调用Next方法,删除已发射小鸟,并激活下一个等待小鸟进行操纵;

当小鸟数量=0或是小猪数量=0时,进行逻辑判断

  • 当小猪数量=0时,胜利!
  • 当小猪数量<0,并且小鸟数量=0时,失败!

然后显示对应的UI界面,其中当胜利时,获得的星星个数为 当前剩余小鸟个数+1,以此逻辑进行得分判断,并通过Unity自带的PlayerPrefs类,以键值对的形式(key为当前的关卡名称),进行数据的存储;

剩下的就是定义一些UI按键的绑定方法,例如

  • Next     下一关
  • SaveData   当游戏胜利时,保存当前关卡得分(取最大)
  • Home    返回游戏首页
  • RePlay   重新开始当前游戏关卡
public class Gamemanager : MonoBehaviour
{
    public List<Bird> birds;
    public List<Pig> pigs;
    public static Gamemanager _instance;
    public Vector3 originPos; //初始位置
    public GameObject win;
    public GameObject lose;
    public GameObject[] starts;
    public int starsNum = 0;
    public int totalNum = 5;

    public void Start()
    {
        Initialized();
    }

    public void Awake()
    {
        _instance = this;
        originPos = birds[0].transform.position;
    }
    /// <summary>
    /// 初始化小鸟
    /// </summary>
    private void Initialized()
    {
        for(int i = 0; i < birds.Count; i++)
        {
            if (i == 0)//第一只小鸟
            {
                birds[0].transform.position = originPos;
                birds[i].enabled = true;
                birds[i].sp.enabled = true;
                birds[i].canMove = true;
            }
            else
            {
                birds[i].enabled = false;
                birds[i].sp.enabled = false;
            }
        }
    }


    public void NextBird()
    {
        if (pigs.Count > 0)
        {
            if (birds.Count > 0)
            {
                //下一只小鸟
                Initialized();
            }
            else
            {
                //输了
                lose.SetActive(true);
            }
        }
        else
        {
            //赢了
            win.SetActive(true);
        }
    }

    public void ShowStarts()
    {
        StartCoroutine("show");
        //Debug.Log("胜利!!!" + birds.Count);
        
    }

    IEnumerator show()
    {
        for (; starsNum < birds.Count + 1; starsNum++)
        {
            if(starsNum >= starts.Length)
            {
                break;
            }
            yield return new WaitForSeconds(0.2f);
            //Debug.Log(starts[i].name);
            starts[starsNum].SetActive(true);
        }
    }

    public void RePlay()
    {
        SaveData();
        SceneManager.LoadScene(2);
    }

    public void Home()
    {
        SaveData();
        SceneManager.LoadScene(1);
    }

    public void Next()
    {
        SaveData();
        string currentLevel = PlayerPrefs.GetString("nowLevel");
        Debug.Log(currentLevel);
        int num = int.Parse(currentLevel.Substring(5,1)) + 1;
        string nextLevel = currentLevel.Substring(0, currentLevel.Length - 1) + System.Convert.ToString(num);
        Debug.Log("下一关为: " + nextLevel);
        //加载下一关
        PlayerPrefs.SetString("nowLevel", nextLevel);
        SceneManager.LoadScene(2);
    }

    public void SaveData()
    {
        Debug.Log("当前关卡的星星数量为: " + starsNum);

        //当前的星星数目大于已存储星星数目时,进行更新存储
        if (starsNum > PlayerPrefs.GetInt(PlayerPrefs.GetString("nowLevel")))
        {
            PlayerPrefs.SetInt(PlayerPrefs.GetString("nowLevel"), starsNum);
        }

        //存储所有的星星个数
        int sum = 0;
        for(int i = 1; i <= totalNum; i++)
        {
            sum += PlayerPrefs.GetInt("level" + i.ToString());
            //Debug.Log("第"+ i.ToString() +"关的星星为: " + PlayerPrefs.GetInt("level" + i.ToString()));
            //Debug.Log("sum为: " + sum);
        }
        Debug.Log("将要存储的星星总数为: " + sum);
        PlayerPrefs.SetInt("totalNum", sum);
       
    }
}

4.地图选择

地图UI设计为以下四个部分,其中最后一个部分没有功能实现,所以真正的关卡其实只有前面三部分

 在开始时,我们先读取所有已通关关卡的星星数目总和,当星星综合大于设定的map星星数目时,该map才进行解锁,设置isSelect=true,否则锁定该关卡,设置isSelect=false;

当点击该map时,隐藏map视图,显示关卡视图level

public class MapSelect : MonoBehaviour
{
    
    public int starsNum;
    public bool isSelect = false;

    public GameObject locks;
    public GameObject starts;
    public GameObject map;
    public GameObject panel;

    public Text startsText;
    public int startNum = 1;
    public int endNum = 5;
    public void Start()
    {
        //清除所有游戏数据
        //PlayerPrefs.DeleteAll();

        if(PlayerPrefs.GetInt("totalNum",0) >= starsNum)
        {
            Debug.Log("星星总数为: " + PlayerPrefs.GetInt("totalNum"));
            isSelect = true;
        }

        if (isSelect)
        {
            locks.SetActive(false);
            starts.SetActive(true);

            //TODO:Text显示
            TextShow();
        }
    }

    public void TextShow()
    {
        int count = 0;
        
        for (int i = startNum; i <= endNum; i++)
        {          
            count += PlayerPrefs.GetInt("level" + i.ToString(), 0);
        }
        
        startsText.text = count.ToString() + "/15";
    }

    public void Selected()
    {
        if (isSelect)
        {
            panel.SetActive(true);
            map.SetActive(false);
        }
    }

    public void PanelSelect()
    {
        panel.SetActive(false);
        map.SetActive(true);
    }
}

5.关卡选择

当激活关卡视图时,首先激活第一关,设置isSelect = true,然后遍历剩下的关卡,通过PlayerPrefs获取已存储的数据,当目标关卡的星星数目>0时,激活该关卡,否则进行锁定;

当激活某一关时,要通过PlayerPrefs得到该关卡的星星数目,然后通过控制star[i](星星列表)进行星星的显示;

然后定义一个Slect方法,用于选择关卡,当点击某个关卡时,通过PlayerPrefs设置当前关卡为点击关卡,并通过SceneManager读取场景

public class LevelSelect : MonoBehaviour
{
    public bool isSelect = false;
    public Sprite levelBG;
    public Image img;

    public GameObject[] stars;

    public void Awake()
    {
        img = GetComponent<Image>();
    }

    public void Start()
    {
        //是第一关
        if(this.transform.name == this.transform.parent.GetChild(0).name)
        {
            isSelect = true;
        }
        else
        {
            int beforeNum = int.Parse(this.gameObject.name) - 1;
            if( PlayerPrefs.GetInt("level"+beforeNum.ToString()) > 0)
            {
                isSelect = true;
            }
        }

        //激活关卡
        if (isSelect)
        {
            img.overrideSprite = levelBG;
            this.transform.Find("num").gameObject.SetActive(true);

            //读取星星个数
            int count = PlayerPrefs.GetInt("level" + this.gameObject.name);
            if (count > 0)
            {
                for(int i = 0; i < count; i++)
                {
                    stars[i].SetActive(true);
                }
            }
        }
    }


    public void Selected()
    {
        if (isSelect)
        {
            PlayerPrefs.SetString("nowLevel", "level" + this.gameObject.name);
            SceneManager.LoadScene(2);
            //Debug.Log("选择成功");
        }
    }
}

6.暂停界面

通过UI设计一个暂停界面,当为激活时,它在游戏窗口外,当激活时,通过动画,将UI界面移入游戏窗口;

定义方法Pause,当点击暂停按钮时,调用该方法,然后调用暂停动画,将UI窗口移入游戏界面,

设置Time.timeScale = 0,以达到暂停游戏的效果,并隐藏该暂停按钮;

然后定义Resume方法,当点击还原按钮时,调用该方法,调用还原动画,重新将UI窗口移除游戏界面,并设置第一个小鸟为激活状态,并显示暂停按钮;

接下来定义Home方法和Retry方法,分别实现返回首页,和重新开始该关卡的操作,这里可以调用Gamemaneger中的Home和Retry方法,不过要注意提前设置Time.timeScale = 1,以免游戏继续暂停;

public class PausePanel : MonoBehaviour
{
    private Animator anim;
    public GameObject button;
    public void Awake()
    {
        anim = GetComponent<Animator>();
    }
    /// <summary>
    /// Home按键
    /// </summary>
    public void Home()
    {
        Time.timeScale = 1;
        Gamemanager._instance.Home();

    }
    /// <summary>
    /// Retry按键
    /// </summary>
    public void Retry()
    {
        Time.timeScale = 1;
        Gamemanager._instance.RePlay();
    }
    /// <summary>
    /// Pause按键
    /// </summary>
    public void Pause()
    {
        anim.SetBool("isPause", true);
        button.SetActive(false);

        //暂停
        if (Gamemanager._instance.birds.Count > 0)
        {
            if(Gamemanager._instance.birds[0].isReleased == false)
            {
                Gamemanager._instance.birds[0].canMove = false;
            }
        }
    }
   
    /// <summary>
    /// Resume按键
    /// </summary>
    public void Resume()
    {
        Time.timeScale = 1;
        anim.SetBool("isPause", false);

        //还原
        if (Gamemanager._instance.birds.Count > 0)
        {
            if (Gamemanager._instance.birds[0].isReleased == false)
            {
                Gamemanager._instance.birds[0].canMove = true;
            }
        }
    }

    /// <summary>
    /// pause动画结束后调用
    /// </summary>
    public void PauseAnimEnd()
    {
        Time.timeScale = 0;
    }
    /// <summary>
    /// resume动画结束后调用
    /// </summary>
    public void ResumeAnimEnd()
    {
        button.SetActive(true);
    }
}

 

四、场景间的组合搭配

一个游戏场景由以下几个模块构成:

  • Main Camera        主摄像机
  • Player          玩家模块,包括弹弓、当前小鸟、准备小鸟
  • Enemy         敌人模块,包括所有敌方单位:小猪、木块等障碍物
  • env               游戏背景:背景图片,地面,草丛
  • Cavas          UI画布,所有的UI组件都放在这里,用于管理UI的所有操作
  • UICamera    UI摄像机,查看UI镜头
  • Gamemenager    游戏管理器,挂载Gamemaneger脚本,管理几乎所有的游戏逻辑与功能模块

五、游戏的发布

关于游戏的发布,首先在项目设置里,设置你的游戏画面、游戏图标、鼠标图标等设置

然后进入Build Settings,设置需要发布的场景画面Scenes,根据需求,在不同的平台上发布游戏,在这里我选择发布的平台是Windows和Android(安卓发布,需要设置例如jdk、sdk,ndk等环境配置)

最后点击Build,铛铛,大功告成~





总结

以上就是一个Unity入门菜鸡开发的入门级2D游戏项目,本文主要用于自己学习总结,如有不对的地方望各位大佬指正。

下面是已发布成功的游戏本体:

PC和安卓: https://pan.baidu.com/s/1Q6SH-YWx7u4qF5DFDjOVqw       提取码:9xpx 

安卓(蓝奏云): 愤怒的小鸟    密码:2zp4

从前慢y
关注 关注
  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity初级案例-愤怒小鸟AngryBird
12-22
Unity实现耳熟能详的游戏愤怒小鸟,内含游戏素材和游戏源码
愤怒小鸟(angrybirds) unity项目
11-20
完整的愤怒小鸟unity项目的源代码,可以直接在unity上面运行,做类似抛射项目的同学很值得借鉴和参考~,下载完后请给个好评赚点积分就好.
unity入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
最新发布
baimao__Ch的博客
06-28 3566
在新建完成后会在创建的目录下生成相关工程文件如图所示:Assets: 资源(场景脚本模型)Library: 库(系统)Logs: 日志Packages: 导入的包ProjectSettings: 工程设置Temp: 临时文件(文件过大可以删除部分缓存)UserSettings: 设置。
Unity入门实践小项目
SunsetSunup的博客
04-26 783
UML类图拖入模型和添加脚本让场景动起来先用自己写的GUI工具包拼出来加代码先拼出来加代码BeginPanel也添加代码,达到互斥的效果音效数据——MusicData数据管理类——GameDataMgr音效设置面板的更改达到音效数据存储的功能排行榜逻辑代码BeginPanel添加代码要完成排行榜数据存储、更新、显示排行榜单条数据类和总体数据类排行榜面板逻辑更新GameDataMgr 添加用一个空物体添加背景音乐,并且写一个背景音乐的脚步背景音乐脚本相关逻辑GameDataMgr 逻辑更新开始场景完成先拼Ga
unity愤怒小鸟
09-26
unity愤怒小鸟,android版,把touch部分代码改为mousebuttondown就可以在电脑上运行了
愤怒小鸟 AngryBird Unity(打弹弓的那种)
weixin_39538253的博客
06-14 3134
03 资源导入 场景简单搭建 切图 带很多子图的 (了解)图标大小 (了解)图层顺序 视频多了为小鸟新建Player层 04 SpringJoint组件介绍 弹弓右,静态2D刚体,挂到小鸟弹簧组件上 小鸟,SpringJoint2D(弹簧),2D圆形碰撞器 以“遛狗”为例,“已连接锚点”是“你”,“锚点”是“狗” (了解) 坐标系 屏幕坐标是左下原点 Unity世界坐标默认是中心原点 (问题)一点小鸟跑到摄像机的位置 一点,z值变得和主相机一样,两种方法: 01 限死z为0 02 减去相机的z
基于C#+UnityAngryBirds愤怒小鸟游戏设计与实现.zip
06-22
资源包含文件:论文文档+系统设计书+需求方分析说明书+用户使用手册+答辩PPT+演示视频+源码及游戏包+项目截图等 该游戏不需要安装任何其他插件和其他库,玩家在解压游戏压缩包至自己选定的位置之后,点开文件夹,...
(5.x-2019)愤怒小鸟 unity源码angryBird-unity.zip
10-29
在“angryBird-unity项目中,每个关卡都对应一个场景,包含了游戏的所有视觉元素,如角色、背景、障碍物等。这些元素通常由游戏对象(GameObject)组成,每个对象都可以附加各种组件,如Transform(变换)、...
安卓Android源码——FlappyBird像素鸟Unity+cocos2dx项目.zip
10-12
《安卓Android源码——FlappyBird像素鸟Unity+cocos2dx项目详解》 在移动游戏开发领域,Flappy Bird是一款非常著名的休闲游戏,其简洁的画面和极具挑战性的玩法深受玩家喜爱。本项目提供了Flappy Bird在Android平台...
unity制作愤怒小鸟
qq_20179331的博客
06-15 2740
动画制作协程异步资源加载resource文件夹存储关卡数据playerprefs存储关卡信息trail拖尾效果。
愤怒小鸟unity3d
11-23
愤怒小鸟unity3d版本,C#脚本编写,素材齐全,功能完整。
Unity愤怒小鸟1.0
12-24
UNITY+c#2017制作的愤怒小鸟游戏,场景不同的3关*3个地图选择
Unity项目小游戏源码、新手入门资源
02-10
Unity项目小游戏源码、新手入门资源。含源代码
unity3d 愤怒小鸟
04-03
unity3d 愤怒小鸟.
愤怒小鸟Unity3d
08-05
愤怒小鸟unity3d版,根据龚老师的视频教程制作的,资源还有关卡都有的,绝对值得拥有!
Unity 制作愤怒小鸟
热门推荐
Baker的博客
01-15 1万+
Unity 制作愤怒小鸟一、项目准备二、切片三、实现小鸟的拖拽1. 添加并设置Spring Joint 2D2. 编写脚本 参考视频: 【SiKi学院UnityUnity初级案例 - 愤怒小鸟 一、项目准备 资源下载: http://www.sikiedu.com/course/134 新建工程: 选择2D,填写项目名称并选择项目路径: 将资源中的Image和Music复制到项目文件夹中: 二、切片 选择猪和鸟的第一章图片,将其Sprite Mode改为Multiple并App
Unity案例---愤怒小鸟
renwen1579的博客
10-31 4660
笔记要点 edit--->project settings--->editor 导入资源 单击右键--->Show in Explorer--->Assets复制粘贴 图层问题 springjoint组件 Static 保持静止 不受重力 Scripts用来存放脚本 public class Bird : MonoBehaviour { private bool isClick = ...
自己初学时做的一个小项目,希望对一起刚学Unity的白白有帮助
weixin_43028359的博客
01-15 265
一个简单易上手的,针对新手入门项目覆盖面较广而且有相对简单的一些应用@一起努力的白白猿胖儿简单项目教程 项目包含:NGUI简单应用、本地登录,注册、json数据存储,解析(背包系统、关卡选择,物品使用、属性加成)、人物移动、动画系统(Animation,Animator)、怪物自动导航、简易地图的制作、技能的释放、虚拟摇杆、HUD插件(受伤掉血显示以及打击怪物掉血显示)、掉血效果制作Slider...
Unity制作愤怒小鸟_菜鸟篇
qq_57250692的博客
08-10 933
这款游戏算是小时候的童年了,比较适合我这种新手练手,刚开始也是不知道用什么组件和逻辑去制作,后面也是看视频学的。游戏结构:UI页面(加载画面和关卡选择)和游戏场景。
Unity新手入门:探索用户界面与3D对象操作
"Unity界面入门教程.pdf" Unity是世界上最流行的跨平台游戏引擎之一,它提供了强大的3D和2D游戏开发工具。本教程是专为初学者设计的,旨在引导学习者熟悉Unity的用户界面(GUI)和基本操作,如创建、移动和缩放游戏...
写文章

热门文章

  • Unity新手入门项目——AngryBird(愤怒的小鸟) 1941
  • JAVA算法笔记 168

大家在看

  • 基于Android的爱心小屋公益机构智慧管理APP系统设计与实现(源码+文档+数据库+部署视频) 1840
  • Activiti7《第六式:破索式》——工作流中的细节缠绕
  • 01 基础request 23
  • 实例讲解使用Matlab_Simulink整车模型进行车速控制策略仿真测试验证方法 1379
  • 数电课设(路口交通灯管理系统的设计—西大) 1103

最新文章

  • JAVA算法笔记
2024年1篇
2021年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值

玻璃钢生产厂家抽象玻璃钢景观雕塑小品杭州美陈最好的商场莱阳玻璃钢动物雕塑海口玻璃钢雕塑哪里有玻璃钢佛像雕塑工艺品龙泉玻璃钢雕塑热线电话聊城玻璃钢雕塑联系方式镇江玻璃钢大象雕塑长沙专业不锈钢玻璃钢彩绘雕塑黑龙江景区玻璃钢雕塑定做光棍节商场美陈安阳玻璃钢动物雕塑定做厂家玻璃钢海洋雕塑有哪些四川超市商场美陈海口玻璃钢雕塑产品厂家咨询玻璃钢抽象不锈钢雕塑生产南京商场新春美陈吉林玻璃钢卡通雕塑羊定做九江水果玻璃钢雕塑海南玻璃钢雕塑厂家欢迎来电公园校园玻璃钢雕塑价格湖南城市广场雕塑玻璃钢玻璃钢雕塑摆件施工清远玻璃钢仿铜雕塑玻璃钢动物雕塑推荐货源莆田模压法玻璃钢雕塑定制玻璃钢雕塑关公坐像商场雕塑车玻璃钢雕塑江门树脂玻璃钢雕塑制作铜陵玻璃钢雕塑定做香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化