喵喵接水果2D(01)

本文档详细介绍了使用Unity开发2D接水果游戏的步骤,从新建工程、导入素材到游戏逻辑实现,包括小猫移动、水果生成、碰撞检测、得分系统、UI界面设计等关键环节,最后介绍游戏的发布流程。
摘要由CSDN通过智能技术生成

一、新建工程

1、打开UnityHub新建项目工程

创建一个Unity项目工程很简单,但我还是写了。哈哈。基础的常规操作!

2、导入项目需要的素材

1)、项目素材我已经准备好了,放在文末的资源里面。读者也可以根据自己的需求自己设计UI等画面。我的素材包:素材包里面包括背景,小猫,分数,水果等等的图片,我们需要把对应的图片改成Sprite模式,才能正常使用。

2)在Unity中导入相应的素材包

我们导入了Sound和Texture的文件素材包,用于游戏中的使用。Sound保存着声音文件,当小猫接住水果的时候,会发出声音。

3、项目的搭建

1)、导入素材包之后,需要把相应的图片改成Sprite模式,不然不能使用。

2)、将Bg图片拖入到项目窗口中,按住Shift键,调整图片的大小,我把窗口大小设置的为1024*768。将图片铺满整个窗口。将小猫咪的图片拖入到项目窗口中。调整一下层的顺序,不然看不见小猫咪。Order In Layer数值越大,越显示在最上层。

3)、接下来我们需要做的是控制小猫咪的左右移动,写一个脚本去控制猫咪的移动,我们在Assets目录下新建一个Scripts文件夹目录,这个目录专门用来存储脚本的。新建的Player_Move.cs脚本,脚本内容如下;

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

public class Player_Move : MonoBehaviour
{
    public float Move_Speed = 5f; //移动的速度
    public Sprite[] Texture;
    public float Sec = 0.5f;
    private int Num = 0;
    private bool Walk_State = false;

    // Start is called before the first frame update
    void Start()
    {

    }

    // Update is called once per frame
    void Update()
    {
        if (Game_Start.Game_State == true)
        {
            if (Input.GetKey(KeyCode.LeftArrow) || Input.GetKey(KeyCode.A)) //左键按下
            {
                transform.Translate(Move_Speed * Time.deltaTime, 0, 0);//移动
                transform.rotation = Quaternion.Euler(0, 180, 0);//旋转

                if (Walk_State == false)
                {
                   Walk_State = true;
                   InvokeRepeating("SetInterial", 0f, Sec);//Unity内置的回调机制,0秒后,每2秒执行一次SetInterial函数
                }
            }
            if (Input.GetKey(KeyCode.RightArrow) || Input.GetKey(KeyCode.D))
            {
                transform.Translate(Move_Speed * Time.deltaTime, 0, 0);
                transform.rotation = Quaternion.Euler(0, 0, 0);

                if (Walk_State == false)
                {
                    Walk_State = true;
                    InvokeRepeating("SetInterial", 0f, Sec);
                }
            }
            if (Input.GetKeyUp(KeyCode.A) || Input.GetKeyUp(KeyCode.D) || Input.GetKeyUp(KeyCode.LeftArrow) || Input.GetKeyUp(KeyCode.RightArrow))
            {
                CancelInvoke();
                Walk_State = false;
            }

            if (transform.position.x > 7)
            {
                transform.position = new Vector3(7, transform.position.y, 0);
            }
            if (transform.position.x < -7)
            {
                transform.position = new Vector3(-7, transform.position.y, 0);
            }
        }
    }

    void SetInterial()
    {
        if (Num == 0)
        {
            GetComponent<SpriteRenderer>().sprite = Texture[0];
            Num += 1;
        }
        else if (Num == 1)
        {
            GetComponent<SpriteRenderer>().sprite = Texture[1];
            Num -= 1;
        }
    }
}

查看需要设置的参数

实现的效果如下:

4)、我们希望在游戏过程中有个背景音乐,背景音乐的素材我已经准备好了,放在Assets文件夹下的Sound文件夹中。按住下图操作,游戏一启动,就可以听到背景音乐了。

4、水果游戏物体的搭建

1)、将水果分别拖入到项目视口中,调整图片的层级顺序。以便显示水果图片.每个水果上还要添加RigidBody,RigidBody的作用是使水果可以自由下落。把水果调成合适的大小。为了使不同的水果下落的速度不一样,需要修改RIgidBody的Gravity Scale的大小。

2)、还需要在每个水果上添加碰撞体,这样当碰撞到某个游戏物体时会有反馈。

3)、小猫咪的篮子也需要配置碰撞体

4)、因为都有碰撞体,会发生碰撞,我们不需要碰撞,所以我们需要把水果的碰撞体Is Trigger的勾给打上。小猫上的篮子不需要勾。(注意这一块,小猫咪和水果必须至少有一个IsTrigger前的勾需要打上,那样就不会发生碰撞反应,但会有反馈

5)、水果掉落到地上,水果会消失。所以我们还需要一个Ground_Line。

碰撞器中的IsTrigger前的勾需要打上。

6)、新建多个标签,并且把各个水果的标签改成我们设置的,后面程序会用到。

5、接水果程序得分撰写

1)、新建一个Destroy_Fruit.cs脚本用来销毁水果。然后把脚本挂载在各个水果上。

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

public class Destroy_Fruit : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Ground_Line")
        {
            Destroy(gameObject);
        }
    }
}

分别挂载后,启动游戏,会看到各个水果碰到地板就会消失了。

2)、新建一个Catch_Fruit.cs脚本,用来控制小猫咪接水果的程序。需要在Cat对象上添加Audio Source组件。

Catch_Fruit.cs脚本内容:

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

public class Catch_Fruit : MonoBehaviour
{
    public AudioClip Catch_Sound;
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if(collision.gameObject.tag == "Watermelon")
        {
            Score_Time.Score_Num += 20;
        }
        if (collision.gameObject.tag == "Banana")
        {
            Score_Time.Score_Num += 10;
        }
        if (collision.gameObject.tag == "Apple")
        {
            Score_Time.Score_Num += 8;
        }
        if (collision.gameObject.tag == "Orange")
        {
            Score_Time.Score_Num += 5;
        }
        if (collision.gameObject.tag == "Strawberry")
        {
            Score_Time.Score_Num += 2;
        }

        GetComponent<AudioSource>().PlayOneShot(Catch_Sound);
        Destroy(collision.gameObject);
    }
}

这时候你会看到,当小猫咪接受到水果后,水果会消失,同时会发出声音。

3)、不同的水果大小不一样,下落的速度也不一样。我们可以修改Rigid Body中的GraScale属性,修改不同水果下落的速度。

4)、不同的水果在下落的过程中需要旋转一定的度数,我们新建一个Rotate_Myself.cs的脚本,然后挂载在不同的水果身上,来实现自转。

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

public class Rotate_Myself : MonoBehaviour
{
    public int Rotate_X;
    public int Rotate_Y;
    public int Rotate_Z;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Rotate(Rotate_X*Time.deltaTime, Rotate_Y * Time.deltaTime, Rotate_Z * Time.deltaTime);
    }
}

5)、将素材中的分数图片拖拽到项目视口中。然后新建一个Score_MoveUp.cs脚本。用于移动分数,然后消失。

Score_MoveUp.cs的具体内容代码:

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

public class Score_MoveUp : MonoBehaviour
{
    public int Up_Speed = 3;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        transform.Translate(0*Time.deltaTime,Up_Speed*Time.deltaTime,0*Time.deltaTime);
        Destroy(gameObject,0.5f);
    }
}

具体的效果如下:

6)、接下来我们需要把分数变成预制体。然后删除项目窗口的分数。

7)、修改Catch_Fruit.cs文件的内容,当水果碰撞到篮子的时候,分数显示出来。

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

public class Catch_Fruit : MonoBehaviour
{
    public AudioClip Catch_Sound;
    public GameObject[] ShowScore;
    public float Y_Num = 0.5f;
    private Vector3 Y_Pos;

    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    private void OnTriggerEnter2D(Collider2D collision)
    {
        Y_Pos.y = Y_Num;
        collision.transform.position += new Vector3(0,Y_Pos.y,0);

        if(collision.gameObject.tag == "Watermelon")
        {
            Score_Time.Score_Num += 20;
            Instantiate(ShowScore[0],collision.transform.position,transform.rotation);
        }
        if (collision.gameObject.tag == "Banana")
        {
            Score_Time.Score_Num += 10;
            Instantiate(ShowScore[1], collision.transform.position, transform.rotation);
        }
        if (collision.gameObject.tag == "Apple")
        {
            Score_Time.Score_Num += 8;
            Instantiate(ShowScore[2], collision.transform.position, transform.rotation);
        }
        if (collision.gameObject.tag == "Orange")
        {
            Score_Time.Score_Num += 5;
            Instantiate(ShowScore[3], collision.transform.position, transform.rotation);
        }
        if (collision.gameObject.tag == "Strawberry")
        {
            Score_Time.Score_Num += 2;
            Instantiate(ShowScore[4], collision.transform.position, transform.rotation);
        }

        GetComponent<AudioSource>().PlayOneShot(Catch_Sound);
        Destroy(collision.gameObject);
    }
}

修改一下参数

6、分数的界面显示

1)、我们需要新建一个时间和分数的标签

2)、新建一个脚本Score_Time.cs脚本,用于控制时间和分数。

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

public class Score_Time : MonoBehaviour
{
    public static int Score_Num = 0;
    public static float Time_Num = 120;
    public Sprite[] Texture;
    public GameObject[] Score_UI;
    public GameObject[] Time_UI;
    
    private int Score_Num_0;
    private int Score_Num_1;
    private int Score_Num_2;
    
    private int Time_Num_0;
    private int Time_Num_1;
    private int Time_Num_2;

    // Start is called before the first frame update
    void Start()
    {
        Score_Num = 0;
        Time_Num = 120;

    }

    // Update is called once per frame
    void Update()
    {
        Time_Num -= Time.deltaTime;   
        if(Time_Num <= 0)
        {
            Time_UI[0].SetActive(true);
            Time_UI[1].SetActive(false);
            Time_UI[2].SetActive(false);
            Time_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[0];
        }
        if(Time_Num > 0 && Time_Num < 10)
        {
            Time_UI[0].SetActive(true);
            Time_UI[1].SetActive(false);
            Time_UI[2].SetActive(false);
            Time_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[(int)(Time_Num)];
        }
        if(Time_Num >=10 && Time_Num < 100)
        {
            Time_Num_0 = (int)(Time_Num / 10);
            Time_Num_1 = (int)(Time_Num % 10);
            Time_UI[0].SetActive(true);
            Time_UI[1].SetActive(true);
            Time_UI[2].SetActive(false);
            Time_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[Time_Num_0];
            Time_UI[1].GetComponent<SpriteRenderer>().sprite = Texture[Time_Num_1];
        }
        if (Time_Num >= 100 && Time_Num < 1000)
        {
            Time_Num_0 = (int)(Time_Num / 100);
            Time_Num_1 = (int)((Time_Num % 10) /10);
            Time_Num_2 = (int)((Time_Num % 100) % 10);

            Time_UI[0].SetActive(true);
            Time_UI[1].SetActive(true);
            Time_UI[2].SetActive(true);
            Time_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[Time_Num_0];
            Time_UI[1].GetComponent<SpriteRenderer>().sprite = Texture[Time_Num_1];
            Time_UI[2].GetComponent<SpriteRenderer>().sprite = Texture[Time_Num_2];
        }

        if (Score_Num <= 0)
        {
            Score_UI[0].SetActive(true);
            Score_UI[1].SetActive(false);
            Score_UI[2].SetActive(false);
            Score_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[0];
        }
        if (Score_Num > 0 && Score_Num < 10)
        {
            Score_UI[0].SetActive(true);
            Score_UI[1].SetActive(false);
            Score_UI[2].SetActive(false);
            Score_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[(int)(Score_Num)];
        }
        if (Score_Num >= 10 && Score_Num < 100)
        {
            Score_Num_0 = (int)(Score_Num / 10);
            Score_Num_1 = (int)(Score_Num % 10);
            Score_UI[0].SetActive(true);
            Score_UI[1].SetActive(true);
            Score_UI[2].SetActive(false);
            Score_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[Score_Num_0];
            Score_UI[1].GetComponent<SpriteRenderer>().sprite = Texture[Score_Num_1];
        }
        if (Score_Num >= 100 && Score_Num < 1000)
        {
            Score_Num_0 = (int)(Score_Num / 100);
            Score_Num_1 = (int)((Score_Num % 10) / 10);
            Score_Num_2 = (int)((Score_Num % 100) % 10);

            Score_UI[0].SetActive(true);
            Score_UI[1].SetActive(true);
            Score_UI[2].SetActive(true);
            Score_UI[0].GetComponent<SpriteRenderer>().sprite = Texture[Score_Num_0];
            Score_UI[1].GetComponent<SpriteRenderer>().sprite = Texture[Score_Num_1];
            Score_UI[2].GetComponent<SpriteRenderer>().sprite = Texture[Score_Num_2];
        }
    }
}

3)、将脚本挂载在MainCamera上,还需要设置相应的参数

7、随机生成水果与位置

1)、新建一个Empty GameObject。用于随机生成水果,写一个脚本挂载这个空物体身上。

2)、新建一个Inst_Fruit.cs脚本,用于生成随机位置的水果

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

public class Inst_Fruit : MonoBehaviour
{
    public GameObject[] Fruit;
    public int Sec = 2;
    private Vector3 X_Num;
    private int i;

    // Start is called before the first frame update
    void Start()
    {
        InvokeRepeating("SetInterial",0f,Sec);
    }

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

    void SetInterial()
    {
        X_Num.x = Random.Range(-5,6);
        transform.position += new Vector3(X_Num.x,0,0);
        if(transform.position.x > 7)
        {
            transform.position = new Vector3(6,transform.position.y,0);
        }
        if(transform.position.x < -6)
        {
            transform.position = new Vector3(-6, transform.position.y, 0);
        }
        i = Random.Range(0,5);
        if(i == 0)
        {
            Instantiate(Fruit[0],transform.position,transform.rotation);
        }
        if (i == 1)
        {
            Instantiate(Fruit[1], transform.position, transform.rotation);
        }
        if (i == 2)
        {
            Instantiate(Fruit[2], transform.position, transform.rotation);
        }
        if (i == 3)
        {
            Instantiate(Fruit[3], transform.position, transform.rotation);
        }
        if (i == 4)
        {
            Instantiate(Fruit[4], transform.position, transform.rotation);
        }
    }
}

3)、修改Catch_Fruit.cs的内容,让水果分数显示的方向和小猫咪的方向一致

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

public class Catch_Fruit : MonoBehaviour
{
    public AudioClip Catch_Sound;
    public GameObject[] ShowScore;
    public float Y_Num = 0.5f;
    private Vector3 Y_Pos;

    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    private void OnTriggerEnter2D(Collider2D collision)
    {
        Y_Pos.y = Y_Num;
        collision.transform.position += new Vector3(0,Y_Pos.y,0);
        collision.transform.rotation = Quaternion.Euler(0,0,0);
        if(collision.gameObject.tag == "Watermelon")
        {
            Score_Time.Score_Num += 20;
            Instantiate(ShowScore[0],collision.transform.position,collision.transform.rotation);
        }
        if (collision.gameObject.tag == "Banana")
        {
            Score_Time.Score_Num += 10;
            Instantiate(ShowScore[1], collision.transform.position, collision.transform.rotation);
        }
        if (collision.gameObject.tag == "Apple")
        {
            Score_Time.Score_Num += 8;
            Instantiate(ShowScore[2], collision.transform.position, collision.transform.rotation);
        }
        if (collision.gameObject.tag == "Orange")
        {
            Score_Time.Score_Num += 5;
            Instantiate(ShowScore[3], collision.transform.position, collision.transform.rotation);
        }
        if (collision.gameObject.tag == "Strawberry")
        {
            Score_Time.Score_Num += 2;
            Instantiate(ShowScore[4], collision.transform.position, collision.transform.rotation);
        }

        GetComponent<AudioSource>().PlayOneShot(Catch_Sound);
        Destroy(collision.gameObject);
    }
}

4)、下面就是要实现的效果

二、游戏UI界面的显示

1、文本显示和按钮

1)、新建两个文本显示和两个按钮

2)、将文本和按钮隐藏

3)、新建Game_Over.cs脚本,挂载到MainCamera上。

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

public class Game_Over : MonoBehaviour
{
    public GameObject UI;
    public GameObject Replay_Btn;
    public GameObject Exit_Btn;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Score_Time.Time_Num <= 0)
        {
            StartCoroutine("Show_UI");//延时
        }
    }

    IEnumerator Show_UI()
    {
        UI.SetActive(true);
        yield return new WaitForSeconds(0.3f);//延时时间
        Replay_Btn.SetActive(true);
        Exit_Btn.SetActive(true);
    }
}

2、按钮的功能

1)、新建一个脚本,实现按钮的功能Replay_Exit_Btn.cs脚本。挂载在MainCamera上。

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

public class Replay_Exit_Btn : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

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

    public void Replay_Fun()
    {
        SceneManager.LoadScene("Game");
    }
    public void Exit_Fun()
    {
        Application.Quit();
    }
}

2)、上面我们创建了Game_Over.cs脚本,没有创建游戏过关的脚本。现在我们来创建一个游戏过关的脚本,Game_Pass.cs脚本。挂载到MainCamera上。

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

public class Game_Pass : MonoBehaviour
{
    public GameObject UI;
    public GameObject Replay_Btn;
    public GameObject Exit_Btn;

    // Start is called before the first frame update
    void Start()
    {
        
    }

    // Update is called once per frame
    void Update()
    {
        if(Score_Time.Time_Num > 0 && Score_Time.Score_Num >= 40)
        {
            StartCoroutine("Show_UI");//延时
        }
    }

    IEnumerator Show_UI()
    {
        UI.SetActive(true);
        yield return new WaitForSeconds(0.3f);//延时时间
        Replay_Btn.SetActive(true);
        Exit_Btn.SetActive(true);
    }
}

这样效果就完成了。

3、游戏开始

1)、新建一个Game_Start.cs用来控制游戏开始,挂载MainCamera上。

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

public class Game_Start : MonoBehaviour
{
    public static bool Game_State = false;
    public GameObject UI;

    // Start is called before the first frame update
    void Start()
    {
        StartCoroutine("GameStart");
    }

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

    IEnumerator GameStart()
    {
        yield return new WaitForSeconds(1f);
        UI.SetActive(false);
        Game_State = true;
    }
}

到这里我们的游戏就开发完了,接下来就是发布程序了。

4、发布程序

1)、我发布的是PC端程序。Android端的程序发布自己百度一下哈,也比较简单。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

weixin_41392061

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值