10. unity预制体、动态创建实体案例

1. 预制体

预制体Prefab就是事先制作好的物体,可以提高开发效率。

1.1 预制体的制作

第一步:在界面编辑器中先创建一个三维模型,比如创建一个正方体,命名为“骰子”,然后给它添加一个材质,再挂载一个旋转的脚本,如图所示:
10. unity预制体、动态创建实体案例_第1张图片
第二步:经过上述步骤制作好模型后,鼠标在Hierarchy层级窗口内选中模型,按住鼠标左键,将其拖拽到事先建立好的Assets -> Prefabs文件夹内,即可创建对应模型的预制体,如下图所示:
10. unity预制体、动态创建实体案例_第2张图片
制作完成后,在Hierarchy窗口的原始模型即可删除,想要使用模型时,直接在预制体文件夹内拖拽上去即可,创建多个都行。
想要让自己做的预制体给别人使用或者在其它项目中使用,还需要将预制体导出,依赖文件也要一并导出,Prefab文件只是记录了节点的信息,不包含材质和贴图数据,仅包含引用。
导出预制体,选中预制体,点击鼠标右键,选择Export Package,即可弹出导出框,如图:
10. unity预制体、动态创建实体案例_第3张图片

1.2 预制体的相关特征

第一:使用预制体创建的模型,在层级窗口内显示为蓝色
第二:在层级窗口中选中模型,在属性窗口内会多出三个按键(Open按钮:打开预制体模型,Select:定位到预制体模型原型所在位置,Overrides:覆盖预制体模型的更改到预制体原型上)
第三:每一个使用预制体创建的模型,都和预制体本身有绑定关系
第四:右键预制体创建的模型,在菜单中会多出一个Prefab选项,可进行解绑操作,如图所示:
10. unity预制体、动态创建实体案例_第4张图片

1.3 预制体的编辑

第一种方式:双击
在预制体文件夹内,找到预制体,直接双击打开,此时会显示一个蓝色的场景区域,表示已经单独进入编辑模式,操作如图所示:
10. unity预制体、动态创建实体案例_第5张图片
第二种方式:点击预制体模型多出来的三个按钮之一(见上上图):open按钮
这种方式打开后会在场景中直接进行模型编辑,不会单独进入一个窗口,如下图:
10. unity预制体、动态创建实体案例_第6张图片
也可以在层级窗口中将鼠标悬浮在预制体模型上面,此时其右边会出现一个小箭头,点击之后也能进入编辑模式,如下图所示:
10. unity预制体、动态创建实体案例_第7张图片
第三种方式:不进入编辑状态,直接进行属性的更改,更改之后,在上面说的三个按钮中,选择Overrides按钮,会弹出对话框,如下图,选择Apply All即可应用更改,并将更改应用到预制体原生模型上面。
10. unity预制体、动态创建实体案例_第8张图片

2. 动态创建实例

使用创建好的预制体,动态创建实例
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;
        }
    }
}

在上述脚本中,定义了一个变量用于接收子弹预制体的赋值,这样就能使用动态创建的方式引用到预制体模型,如下图所示:
10. unity预制体、动态创建实体案例_第9张图片
对上述脚本代码进行优化:上面创建的子弹都没有指定父节点,默认会创建在根节点下面,为了统一管理子弹,可以再创建一个空节点,命名为子弹盒,当作所有子弹实体的父节点,同时将这个子弹盒节点传输到脚本中进行使用;然后需要确定子弹在场景视图中的初始位置,可以再创建一个空节点,命名为出生点,放在发射架的子节点处,并手动移动出生点位置到炮筒端口,如下图所示:
10. unity预制体、动态创建实体案例_第10张图片
然后在脚本中使用这个出生点节点,定义变量传输到脚本中,将子弹的初始位置设置为出生点节点的位置;然后需要调整子弹的角度,因为炮筒是可以旋转的,子弹的初始角度应该始终和炮筒的角度保持一致,这样在发射时才能保证沿着炮筒的方向发射,可以将炮筒预制体引用到脚本中进行使用。最后子弹产生后,还需要飞出去,这个飞出去的脚本需要添加到预制体上,因为每一个子弹都要飞出去,代码如下:
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子弹发射案例


子弹销毁:子弹射出后,在飞行一段时间后应该销毁,或者是射击到目标物体后,子弹也应该自毁,这样才符合游戏逻辑。在上述代码中,子弹销毁的代码应该放在预制体内,因为每个子弹都应该有销毁这个动作,优化 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;

    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;

        }
    }
}

界面参数设置
10. unity预制体、动态创建实体案例_第11张图片

持续更新中,请大家多多关注…

你可能感兴趣的:(Unity,unity,游戏引擎)