预制体Prefab就是事先制作好的物体,可以提高开发效率。
第一步:在界面编辑器中先创建一个三维模型,比如创建一个正方体,命名为“骰子”,然后给它添加一个材质,再挂载一个旋转的脚本,如图所示:
第二步:经过上述步骤制作好模型后,鼠标在Hierarchy层级窗口内选中模型,按住鼠标左键,将其拖拽到事先建立好的Assets -> Prefabs文件夹内,即可创建对应模型的预制体,如下图所示:
制作完成后,在Hierarchy窗口的原始模型即可删除,想要使用模型时,直接在预制体文件夹内拖拽上去即可,创建多个都行。
想要让自己做的预制体给别人使用或者在其它项目中使用,还需要将预制体导出,依赖文件也要一并导出,Prefab文件只是记录了节点的信息,不包含材质和贴图数据,仅包含引用。
导出预制体,选中预制体,点击鼠标右键,选择Export Package,即可弹出导出框,如图:
第一:使用预制体创建的模型,在层级窗口内显示为蓝色
第二:在层级窗口中选中模型,在属性窗口内会多出三个按键(Open按钮:打开预制体模型,Select:定位到预制体模型原型所在位置,Overrides:覆盖预制体模型的更改到预制体原型上)
第三:每一个使用预制体创建的模型,都和预制体本身有绑定关系
第四:右键预制体创建的模型,在菜单中会多出一个Prefab选项,可进行解绑操作,如图所示:
第一种方式:双击
在预制体文件夹内,找到预制体,直接双击打开,此时会显示一个蓝色的场景区域,表示已经单独进入编辑模式,操作如图所示:
第二种方式:点击预制体模型多出来的三个按钮之一(见上上图):open按钮
这种方式打开后会在场景中直接进行模型编辑,不会单独进入一个窗口,如下图:
也可以在层级窗口中将鼠标悬浮在预制体模型上面,此时其右边会出现一个小箭头,点击之后也能进入编辑模式,如下图所示:
第三种方式:不进入编辑状态,直接进行属性的更改,更改之后,在上面说的三个按钮中,选择Overrides按钮,会弹出对话框,如下图,选择Apply All即可应用更改,并将更改应用到预制体原生模型上面。
使用创建好的预制体,动态创建实例
API:
Object.Instantiate(original,parent);//其中original是创建好的预制体
案例:模拟子弹发射
首先创建一个空节点,命名为子弹节点,这个空节点的用途是挂在动态生成子弹的脚本,创建完成后挂载如下脚本:
BulletScript.cs测试代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletScript : MonoBehaviour
{
public GameObject bulletObj; //定义的变量需要在界面中指定
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))//每次按下鼠标左键,都可创建一个子弹实体
{
GameObject node = Object.Instantiate(bulletObj,null);
node.transform.position = Vector3.zero;
node.transform.localEulerAngles = Vector3.zero;
}
}
}
在上述脚本中,定义了一个变量用于接收子弹预制体的赋值,这样就能使用动态创建的方式引用到预制体模型,如下图所示:
对上述脚本代码进行优化:上面创建的子弹都没有指定父节点,默认会创建在根节点下面,为了统一管理子弹,可以再创建一个空节点,命名为子弹盒,当作所有子弹实体的父节点,同时将这个子弹盒节点传输到脚本中进行使用;然后需要确定子弹在场景视图中的初始位置,可以再创建一个空节点,命名为出生点,放在发射架的子节点处,并手动移动出生点位置到炮筒端口,如下图所示:
然后在脚本中使用这个出生点节点,定义变量传输到脚本中,将子弹的初始位置设置为出生点节点的位置;然后需要调整子弹的角度,因为炮筒是可以旋转的,子弹的初始角度应该始终和炮筒的角度保持一致,这样在发射时才能保证沿着炮筒的方向发射,可以将炮筒预制体引用到脚本中进行使用。最后子弹产生后,还需要飞出去,这个飞出去的脚本需要添加到预制体上,因为每一个子弹都要飞出去,代码如下:
FlyScript.cs:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed = 0.0f;
void Start()
{
}
// Update is called once per frame
void Update()
{
this.transform.Translate(0, speed * Time.deltaTime, 0, Space.Self);
}
}
BulletScript.cs完整代码:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletScript : MonoBehaviour
{
public GameObject bulletObj;
//一般都是使用Transform,GameObject很少使用
public Transform parentNode;
public Transform firePoint;
public Transform canno;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))
{
GameObject node = Object.Instantiate(bulletObj, parentNode);//生成子弹实例
node.transform.position = this.firePoint.position;//更改子弹的初始位置
node.transform.eulerAngles = this.canno.eulerAngles;//更改子弹的角度
//启动子弹飞行
FlyScript flyScript = node.GetComponent<FlyScript>();
flyScript.speed = 10.0f;//设置飞行速度
}
}
}
效果展示:
unity子弹发射案例
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FlyScript : MonoBehaviour
{
// Start is called before the first frame update
public float speed = 0.0f;
public float maxDistance;
void Start()
{
float lifeTime = 1;
if(speed > 0.0f)
{
lifeTime = maxDistance / speed; //根据距离和速度计算飞行时间
Invoke("SelfDestroy", lifeTime);//延迟调用自毁函数
}
}
// Update is called once per frame
void Update()
{
this.transform.Translate(0, speed, 0, Space.Self);
}
private void SelfDestroy()
{
Object.Destroy(this.gameObject);
}
}
同时优化BulletScript.cs代码,在其中设置子弹飞行速度和飞行时长,并将参数暴漏出去,方便在界面中进行设置,以免代码写死:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletScript : MonoBehaviour
{
public GameObject bulletObj;
//一般都是使用Transform,GameObject很少使用
public Transform parentNode;
public Transform firePoint;
public Transform canno;
public float flySpeed;
public float flyTime;
// Start is called before the first frame update
void Start()
{
}
// Update is called once per frame
void Update()
{
if(Input.GetMouseButtonDown(0))
{
GameObject node = Object.Instantiate(bulletObj, parentNode);//生成子弹实例
node.transform.position = this.firePoint.position;//更改子弹的初始位置
node.transform.eulerAngles = this.canno.eulerAngles;//更改子弹的角度
//启动子弹飞行
FlyScript flyScript = node.GetComponent<FlyScript>();
flyScript.speed = this.flySpeed;
flyScript.maxDistance = flyScript.speed * this.flyTime;
}
}
}