初学unity, 通过查阅资料以及自己的一些见解完成了自己做的第一款游戏.
现在把代码分享出来, 仅供参考,不足之处还请指正。
游戏中有三个场景,主要用到六个c#脚本:
脚本 | 作用 |
---|---|
buttonClick.cs | 控制游戏中所有的按钮 |
appearFruits.cs | 控制所有水果出现 |
cutFruit.cs | 判断水果被切以及产生其他对象 |
knife.cs | 控制切水果的的刀痕轨迹 |
scoreManager.cs | 控制分数面板的脚本 |
healthManager.cs | 控制玩家的生命值 |
场景介绍:
StartScence:
PlayScence:
OverScence:
接下来开始逐个介绍脚本:
该脚本需要控制游戏中所有的按钮,其中包括:
1. 场景跳转的按钮
2. 控制音乐播放的按钮
按钮通过NGUI的OnClick()函数触发的:
代码:
using UnityEngine;
using System.Collections;
public class ButtonClick : MonoBehaviour {
public Sprite png1, png2; // 静音时的贴图,与播放时的贴图
private SpriteRenderer spr;
private bool flag; //flag判断是否播放音乐
private AudioSource bgm;
void Start()
{
spr = GetComponent();
bgm = GetComponent();
flag = true;
}
void OnClick() //通过按钮Gameobject的名字判断是哪个按钮被点击
{
if (name == "playScence") //play按钮切换到开始场景
Application.LoadLevel("play");
else if (name == "sound") //音量按钮只需切换 SpriteRenderer组件中的贴图即可
{
if (flag)
{
spr.sprite = png2;
bgm.Stop();
}
else
{
bgm.Play();
spr.sprite = png1;
}
flag = !flag;
}
else if (name == "main") //回主界面按钮
Application.LoadLevel("StartScence");
else
Application.OpenURL("http://blog.csdn.net/axuan_k");
}
}
控制游戏中所有水果从游戏下方以抛物线的形式出现;
关键是要准备好需要用到的预制对象(各种水果) ,并添加到脚本上
代码:
using UnityEngine;
using System.Collections;
public class appearFruits : MonoBehaviour {
public GameObject[] fruits; //水果预制对象数组
private static float interval; //出现水果的间隔时间
private float time;
void Start () {
interval = 0.9f;
InvokeRepeating("Create", interval, interval); //重复隔interval时间出现一个水果
}
void Create()
{
float y = -5.75f;
float x = Random.Range(-6.5f, 6.5f); //随机水果出现的x坐标
GameObject fruit = Instantiate(fruits[Random.Range(0, fruits.Length)]) as GameObject; //实例化
fruit.transform.position = new Vector3(x, y, 0);
//根据x坐标决定 水果飞行的 带方向初始速度范围
float xSpeed = 0f;
if (x <= -3f)
xSpeed = Random.Range(2f, 4f);
else if (x < 3f)
xSpeed = Random.Range(-1f, 1f);
else
xSpeed = Random.Range(-4f, -2f);
fruit.GetComponent().velocity = new Vector2(xSpeed, 14f); //通过Rigidbody2D组件给水果一个初始速度
}
/*
void Create()
{
GameObject obj = Instantiate(fruit[Random.Range(0, fruit.Length)], transform.position, Quaternion.AngleAxis(Random.Range(-30f, 30f), Vector3.back)) as GameObject;
Rigidbody2D rgd = obj.GetComponent(); //得到新生成苹果的rigidbody 来给它一个速度
rgd.velocity = Vector2.left * Random.Range(-10f, 10f);
Destroy(obj, 2f);
}
*/
}
这个脚本需要添加到每一种水果的预制对象上面
处理的逻辑包括:
1. 判断水果是否被切中
2. 产生水果碎片 以及背景污渍
3. 出界面自动销毁
4. 向scoreManager.cs脚本中的函数传递切中加减分的信息
代码:
using UnityEngine;
using System.Collections;
public class CutFruit : MonoBehaviour {
public GameObject obj1, obj2; //分开后的两边水果
public GameObject[] wz; //几种污渍背景
private BoxCollider2D col;
private Vector2[] vec = { Vector2.left, Vector2.right }; //切后的半截往两个方向飞出
private GameObject scores; //放置scoreManager.cs和healthManager.cs脚本的游戏对象
void Start()
{
col = GetComponent();
scores = GameObject.Find("score1");
}
private void CreateHalf(GameObject obj, int index) //创建半个水果
{
obj = Instantiate(obj, transform.position, Quaternion.AngleAxis(Random.Range(-30f, 30f), Vector3.back)) as GameObject;
Rigidbody2D rgd = obj.GetComponent();
float v = Random.Range(2f, 4f); //随机飞出速度
rgd.velocity = vec[index] * v;
Destroy(obj, 2f);
}
private void Createwz() //切开水果随机创建污渍
{
if (wz.Length == 0) //仓鼠没有水果污渍
return;
GameObject obj = Instantiate(wz[Random.Range(0,wz.Length)], transform.position, Quaternion.AngleAxis(Random.Range(-30f, 30f), Vector3.back)) as GameObject;
Destroy(obj, 1f);
}
void Update () {
if (Input.GetMouseButton(0))
{
if (col.OverlapPoint(Camera.main.ScreenToWorldPoint(Input.mousePosition))) //鼠标在当前水果2Dcollider内
{
if (name == "jpg0(Clone)") //金苹果+20分
scores.SendMessage("setScore", 20);
else if (name != "cs(Clone)") //非仓鼠+1分
scores.SendMessage("setScore", 1);
else //切开仓鼠扣血
scores.SendMessage("cutOne");
CreateHalf(obj1, 0);
CreateHalf(obj2, 1);
Createwz();
Destroy(this.gameObject);
}
}
else if (this.transform.position.y <= -6f) //水果掉落到范围外扣分自动销毁
{
scores.SendMessage("setScore", -1);
Destroy(this.gameObject);
}
}
}
图为各种需要用到的预制对象prefab以及组件component
打印出刀痕轨迹的脚本;
为了实现折线的刀痕, 这里我用到了LineRenderer组件, 每隔固定时间记录鼠标所在的坐标从而完成对刀痕的渲染
代码:
using UnityEngine;
using System.Collections;
public class knife : MonoBehaviour {
private LineRenderer myLinRenderer; //该游戏对象的LineRenderer组件
private int count; //LineRenderer中position的数量
private static float timeInterval; //每隔interval时间记录一次鼠标的坐标
private float time;
// Use this for initialization
void Start()
{
count = 0;
timeInterval = 0.3f;
myLinRenderer = GetComponent();
}
// Update is called once per frame
void addline()
{
Vector3 pos = Camera.main.ScreenToWorldPoint(new Vector3(Input.mousePosition.x, Input.mousePosition.y, 1)); //切换到世界坐标系
myLinRenderer.SetVertexCount(++count);
myLinRenderer.SetPosition(count - 1, pos);
if(count==5) //清除刀痕 保证刀痕不能一直存在 无限延长
myLinRenderer.SetVertexCount(count = 0);
}
void Update()
{
if (Input.GetMouseButtonDown(0)) //当鼠标左键按下的时候记录第一个点
{
myLinRenderer.SetVertexCount(count = 0); //先清除之前未清除的刀痕
GetComponent().Play();
time = timeInterval;
addline();
}
else if (Input.GetMouseButton(0)) //鼠标按下时每隔interval秒记录一个点
{
time -= Time.deltaTime;
if (time <= 0)
{
addline();
time = timeInterval;
}
}
else if (Input.GetMouseButtonUp(0)) //松开鼠标记录linerenderer的最后一个点
{
addline();
time = timeInterval; //松开后interval秒清除刀痕
}
else
{
time -= Time.deltaTime; //松开后interval秒清除刀痕
if (time <= 0)
myLinRenderer.SetVertexCount(count = 0);
}
}
}
准备好实例化数字需要的预制对象,再用一个贴图数组保存所有数字的贴图.
每收到一次分数变更消息, 销毁之前存在的分数, 逐个创建新的数字对象贴上对应的图片即可
代码:
using UnityEngine;
using System.Collections;
public class ScoreManager : MonoBehaviour
{
public GameObject DObj; //所有数字对应的 预制对象(tag需要手动添加并更改为score,方便下面销毁)
public Sprite[] Digits; //每个数字对应的贴纸
private int score;
// Use this for initialization
void Start()
{
score = 0;
setScore(score);
}
void setScore(int newScore)
{
//先删除已存在的数字
GameObject[] objs = GameObject.FindGameObjectsWithTag("score");
foreach (GameObject i in objs)
Destroy(i);
score += newScore;
score = score<0?0:score; //保证不出现负分
string str = score.ToString();
int cnt = 0;
//逐个数字实例化预制对象
foreach(char ch in str)
{
GameObject dobj = Instantiate(DObj) as GameObject;
dobj.GetComponent().sprite = Digits[ch-'0']; //贴上对应的贴图
dobj.transform.position =new Vector2(-4.8f+0.6f*cnt, 4.05f);
++cnt;
}
}
}
将已创建的游戏对象(代表血量的X)作为脚本的参数, 失去一条生命,修改对应位置上游戏对象贴图的颜色。
代码:
using UnityEngine;
using System.Collections;
public class healthManager : MonoBehaviour {
public SpriteRenderer[] spr;
private int count;
// Use this for initialization
void Start () {
count = 0;
}
// Update is called once per frame
void cutOne()
{
spr[count++].color = Color.red;
if (count == 5)
Application.LoadLevel("gameOver");
}
}