这次我们做一个打箱子的小项目,不是推箱子= = 。目标是实现自动生成一堵由箱子(Cube)组成的墙,然后鼠标对准箱子按下左键会蓄力,松开后生成一个子弹(Sphere)射向瞄准的箱子。
首先我们创建一个Scene场景,场景中有一个地面(Plane)和一个空物体(Box,用来做箱子-Cube的父级),如图:
然后我们在脚本中用代码实现自动创造一堵墙,代码如下:
public GameObject box;//获取我们Scene中的Box空物体
void Start () {
//创造墙的代码写在Start方法中,因为游戏一运行就会有一堵墙
for (int i = 0; i < 18; i++)
{
for (int j = 0; j < 10; j++)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);//创造物体Cube做为箱子
go.transform.localScale = new Vector3(5,5,5);//设置箱子大小
go.transform.position = new Vector3(-45+i*5,2.5f+j*5,38);//-45和38是根据我的场景位置设置的,i和j分别用来确定箱子的x,y位置
go.transform.parent = box.transform;//把每一个创造的箱子都变成Box的子级
go.GetComponent<Renderer>().material.color= new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));//给箱子加上随机颜色
go.AddComponent<Rigidbody>();//给箱子加上刚体组件
go.tag = "Player";//把箱子的tag值设置为Player(在这之前要确保你的Tag里面有Player,否则需要先创造一个名为Player的tag值)
}
}
}
如图是如何创建一个新的Tag值:
运行项目,得到如图所示效果:
接下来我们就需要用鼠标进行交互,自动生成子弹(Sphere),并射向瞄准的箱子,代码如下:
private Vector3 offset;//目标位置和相机位置的向量,也就是子弹射向的方向
void Update () {
if (Input.GetMouseButtonDown(0))//按一下鼠标左键(此时射击像手枪,单击一下射一发;如果是GetMouseButton就会像机关枪,按住不动一直射),其中0表示鼠标左键,1是右键
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//射线检测,从主相机发射一条射线到鼠标点击的位置(该脚本就是挂在主相机上面),返回该射线
RaycastHit hit;//声明一个RaycastHit,有点类似Collision,自行进行对比 = =
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.tag == "Player")//判断鼠标点击的物体是不是箱子
{
GameObject gb = GameObject.CreatePrimitive(PrimitiveType.Sphere);//生成子弹
gb.GetComponent<Renderer>().material.color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));//给子弹随机颜色
gb.transform.localScale = new Vector3(1,1,1);//设置子弹大小
gb.transform.position = transform.position;//设置子弹的初始位置为主相机的位置
offset = hit.transform.position - transform.position;//获取子弹要射向的方向
gb.AddComponent<Rigidbody>().AddForce(offset*50);//给子弹加刚体,并给一个力(乘以50是让子弹飞的快)
gb.GetComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Continuous;//因为子弹速度如果太快会穿过箱子或者地面,这时就需要设置一下刚体中的collisionDetectionMode属性,这在刚体中讲过,不再叙述
Destroy(gb,2f);//2秒后销毁子弹,因为子弹创造太多会消耗性能
}
}
}
}
运行效果如图:
下面我们再进行一些改进:把鼠标样式改成一个瞄准星,按下鼠标左键就开始蓄力,蓄力越久,子弹速度越大,子弹碰撞到箱子时产生特效。
更改后的代码如下(鼠标按下发射子弹的方法改成鼠标松开发射,):
public GameObject box;//获取我们Scene中的Box空物体
private Vector3 offset;//目标位置和相机位置的向量,也就是子弹射向的方向
public Texture2D pic;//力度条图片
public Texture2D mousepic;//要代替鼠标的图片,是一个瞄准星图片
private float width;//需要绘制的蓄力条长度
private float forcetime = 3f;//设定蓄力时间最多3秒
private float timer;//蓄力时间差值
private float t = 0;//开始蓄力的时间点为0秒;
private bool isui=false;//判断是否开始绘制蓄力条
void Start () {
//Cursor.visible = false;
//创造墙的代码写在Start方法中,因为游戏一运行就会有一堵墙
for (int i = 0; i < 18; i++)
{
for (int j = 0; j < 10; j++)
{
GameObject go = GameObject.CreatePrimitive(PrimitiveType.Cube);//创造物体Cube做为箱子
go.transform.localScale = new Vector3(5,5,5);//设置箱子大小
go.transform.position = new Vector3(-45+i*5,2.5f+j*5,38);//-45和38是根据我的场景位置设置的,i和j分别用来确定箱子的x,y位置
go.transform.parent = box.transform;//把每一个创造的箱子都变成Box的子级
go.GetComponent<Renderer>().material.color= new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));//给箱子加上随机颜色
go.AddComponent<Rigidbody>();//给箱子加上刚体组件
go.tag = "Player";//把箱子的tag值设置为Player(在这之前要确保你的Tag里面有Player,否则需要先创造一个名为Player的tag值)
}
}
}
void Update () {
if (Input.GetMouseButtonUp(0))//按一下鼠标左键(此时射击像手枪,单击一下射一发;如果是GetMouseButton就会像机关枪,按住不动一直射),其中0表示鼠标左键,1是右键
{
isui = false;//鼠标抬起后不再绘制蓄力条
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);//射线检测,从主相机发射一条射线到鼠标点击的位置(该脚本就是挂在主相机上面),返回该射线
RaycastHit hit;//声明一个RaycastHit,有点类似Collision,自行进行对比 = =
if (Physics.Raycast(ray, out hit))
{
if (hit.collider.tag == "Player")//判断鼠标点击的物体是不是箱子
{
GameObject gb = GameObject.CreatePrimitive(PrimitiveType.Sphere);//生成子弹
gb.GetComponent<Renderer>().material.color = new Color(Random.Range(0f, 1f), Random.Range(0f, 1f), Random.Range(0f, 1f));//给子弹随机颜色
gb.transform.localScale = new Vector3(1, 1, 1);//设置子弹大小
gb.transform.position = transform.position;//设置子弹的初始位置为主相机的位置
offset = hit.transform.position - transform.position;//获取子弹要射向的方向
gb.AddComponent<Rigidbody>().AddForce(offset * 50f*(forcetime-timer));//给子弹加刚体,并给一个力(乘以50是让子弹飞的快),
gb.GetComponent<Rigidbody>().collisionDetectionMode = CollisionDetectionMode.Continuous;//因为子弹速度如果太快会穿过箱子或者地面,这时就需要设置一下刚体中的collisionDetectionMode属性,这在刚体中讲过,不再叙述
Destroy(gb, 2f);//2秒后销毁子弹,因为子弹创造太多会消耗性能
}
}
}
if (Input.GetMouseButtonDown(0))
{
isui = true;//鼠标左键按下开始绘制蓄力条
t = 0;//重置开始蓄力的时间点为0秒;
}
}
void OnGUI()
{
Cursor.SetCursor(mousepic, new Vector2(mousepic.width/2,mousepic.height/2), CursorMode.Auto);//用系统自带的方法更换鼠标图片,图片格式必须是Cursor
//Vector2 mouse_Pos = Input.mousePosition;//获取鼠标点击位置
//GUI.DrawTexture(new Rect(mouse_Pos.x-15, Screen.height - mouse_Pos.y-15, 30, 30), mousepic); //自己绘制鼠标图片,图片的大小可以自己设置;
if (isui)
{
t += Time.deltaTime;//计时
timer = Mathf.Clamp((forcetime - t),0f,3f);//该方法获得蓄力时间差值
width = pic.width - timer/forcetime*pic.width;//计算出需要绘制的蓄力条长度
GUI.DrawTexture(new Rect(530f, 20f, width, pic.height), pic);//绘制蓄力条
}
}