一、新建工程
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端的程序发布自己百度一下哈,也比较简单。