查看: 22082|回复: 133

[在unity中制作] 在运行时实例化预设

  [复制链接]

1

主题

342

帖子

7万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
75866
发表于 2016-7-6 03:08:34 | 显示全部楼层 |阅读模式
通过这一点你应该明白预设在一个基本水平。他们是一组预定义的游戏对象 & 组件这是在游戏中重复使用。如果你不知道一个预设是什么,我们建议你阅读预设一个更基本的介绍页面。


问题就在手边的时候要复杂对象在运行时实例化。实例化预设可选择创建游戏对象从零开始使用代码。实例化预设在替代方法的优点:


你可以实例化预设一行代码,功能完备。创建等效对象的代码以平均有五行代码,但可能更多。
你可以设置,测试,和修改预置的迅速和容易地在现场督察。
你可以改变被实例化的预置物体不改变实例化代码。一个简单的火箭可能改变成一个超级火箭,没有代码所做的更改。
常见的场景


为了说明问题的力量,让我们考虑一些基本的情况,他们将派上用场:


建筑墙体的一个单一的“砖”,创造了几次不同位置的预制。
一个火箭发射器实例一个飞行的火箭预置发射时。预置物体包含一个网格,刚体,对撞机,和自己的孩子游戏对象跟踪粒子系统。
一个机器人爆炸成许多碎片。完整的、操作的机器人被破坏和更换一个毁坏的机器人预制。这个预置包含机器人分成很多部分,都建立了它们自己的刚体和粒子系统。这种技术允许你炸毁一个机器人成许多碎片,只有一行代码,一个预制更换一个对象。
建一堵墙


这个例子说明使用预制VS代码创建对象的优势。


首先,使用代码创建一堵砖墙:


// JavaScript
function Start () {
    for (var y = 0; y < 5; y++) {
        for (var x = 0; x < 5; x++) {
            var cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
            cube.AddComponent.<Rigidbody>();
            cube.transform.position = Vector3 (x, y, 0);
        }
    }
}




// C#
public class Instantiation : MonoBehaviour {


    void Start() {
        for (int y = 0; y < 5; y++) {
            for (int x = 0; x < 5; x++) {
                GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                cube.AddComponent<Rigidbody>();
                cube.transform.position = new Vector3(x, y, 0);
            }
        }
    }
}
使用上面的脚本,我们只需保存脚本并将其拖到一个空的游戏对象。
创建一个空的游戏对象GameObject->Create Empty。
如果你执行的代码,你将看到创建的整个砖墙当你进入播放模式。有两对每一块砖的功能的相关线路:createprimitive线,和addcomponent线。不太坏的现在,但我们的每一砖不变形。每一个额外的行动要对砖进行,如改变纹理,摩擦,或刚体群众,是一个额外的线。


如果你创建一个预设,在执行前你所有的设置,你用一行代码来执行创建和设置每一块砖。这可以让你保持和改变了很多代码,当你决定你想要做出改变。用预制件,你只是让你的变化和玩。无需修改代码。


如果你使用一个预设为每一块砖,这是你需要创建墙的代码。


// JavaScript


var brick : Transform;
function Start () {
    for (var y = 0; y < 5; y++) {
        for (var x = 0; x < 5; x++) {
            Instantiate(brick, Vector3 (x, y, 0), Quaternion.identity);
        }
    }
}




// C#
public Transform brick;


void Start() {
    for (int y = 0; y < 5; y++) {
        for (int x = 0; x < 5; x++) {
            Instantiate(brick, new Vector3(x, y, 0), Quaternion.identity);
        }
    }
}
这不仅是很干净也很可。没有什么说我们实例化一个立方体,它必须包含刚体。所有的这一切都是在预制定义,可以快速在编辑器修改。


现在我们只需要创建的预设,我们的编辑做的。这里的如何:


选择GameObject > 3D Object > Cube
选择Component > Physics > Rigidbody
选择Assets > Create > Prefab
在项目视图,改变你的新的预置名称“砖”
把你创建的立方体等级制度我们的“砖”在预置物体项目视图
与预制的创建,你可以安全地从层次结构中删除立方体(删除在Windows,命令键MAC)
我们创建了砖的预制件,所以我们必须重视它的砖在我们的脚本变量。当你选择包含脚本的空的游戏对象,砖变会在检查可见。


现在将“砖”活动从项目视图上砖在检查变量。按下播放键,你会看到墙采用预制。


这是一个工作流模式,可以一次次在统一使用。在开始的时候,你可能不知道为什么这么好,因为脚本代码创建多维数据集只有2线更长。


但因为你使用的是预制的现在,你可以在几秒钟内调节预置。想改变所有实例的质量?调整刚体在预置只有一次。想使用一个不同的材料对于所有的情况吗?拖动材料到预置的唯一一次。想改变摩擦?使用不同的物理材质在预置的对撞机。要添加一个粒子系统,所有这些盒子吗?对预制添加子只有一次。


Instantiating rockets & explosions


这里的如何融入这个场景分类:


火箭发射器实例一个火箭预制当用户按下开火。预置物体包含一个网格,刚体,碰撞,和一个子游戏物体包含尾粒子系统。
火箭撞击并实例化一个爆炸预置。爆炸预置包含一个粒子系统,光消失了一段时间,和一个脚本,适用于周围物体的伤害。
而这将有可能建立一个火箭游戏对象完全从代码,手工添加组件并设置属性,它是实例化预设更容易。您可以实例化火箭仅仅一行代码,不管火箭的组合是多么复杂。在实例化预设还可以修改任何属性的实例化的对象(例如,你可以设置火箭刚体的速度)。


除了更容易使用,你可以更新预制后。所以,如果你正在建设一个火箭,你不马上要添加一个粒子跟踪它。你可以稍后。当你添加TRAIL作为一个孩子的游戏对象的预设,所有实例的火箭将粒子轨迹。最后,你可以快速调整在检查火箭预置的属性,使它更容易调整你的游戏。


这个脚本显示了如何发射火箭的使用instantiate()功能。


// JavaScript


// Require the rocket to be a rigidbody.
// This way we the user can not assign a prefab without rigidbody
var rocket : Rigidbody;
var speed = 10.0;


function FireRocket () {
    var rocketClone : Rigidbody = Instantiate(rocket, transform.position, transform.rotation);
    rocketClone.velocity = transform.forward * speed;
    // You can also acccess other components / scripts of the clone
    rocketClone.GetComponent.<MyRocketScript>().DoSomething();
}


// Calls the fire method when holding down ctrl or mouse
function Update () {
    if (Input.GetButtonDown("Fire1")) {
        FireRocket();
    }
}




// C#


// Require the rocket to be a rigidbody.
// This way we the user can not assign a prefab without rigidbody
public Rigidbody rocket;
public float speed = 10f;


void FireRocket () {
    Rigidbody rocketClone = (Rigidbody) Instantiate(rocket, transform.position, transform.rotation);
    rocketClone.velocity = transform.forward * speed;
   
    // You can also acccess other components / scripts of the clone
    rocketClone.GetComponent<MyRocketScript>().DoSomething();
}


// Calls the fire method when holding down ctrl or mouse
void Update () {
    if (Input.GetButtonDown("Fire1")) {
        FireRocket();
    }
}




一个布娃娃或沉船替换字符


让我们说你有一个完全操纵敌人的角色谁死。你可以在角色扮演的死亡动画和禁用所有脚本通常应付敌人的逻辑。你需要小心的删除一些脚本,添加一些自定义的逻辑来确保没有人会继续攻击敌人的死了,和其他清理工作。


更好的方法是立即删除整个角色和取代它的一个实例化了预制。这给你一个很大的灵活性。你可以使用不同的材料为死字,附加完全不同的脚本,创建的预置包含物体破碎成许多碎片来模拟消灭的敌人,或简单的实例一个预置包含一个版本的特性。


这些选项的任何可以实现的一个电话instantiate(),你只需要将它连接到正确的预制和你!


要记住的最重要的部分是你的残骸instantiate()可以由完全不同的对象比原来。例如,如果你有一架飞机,要准备两个版本的模型。其中一个飞机由一个单一的游戏对象网格渲染器和飞机物理脚本。通过保持模型只是一个游戏,你的游戏将运行的更快,因为你将能以更少的三角形,使模型因为它包含较少的对象,它将比使用许多小部分快。当你的飞机也高兴地飞来飞去,没有理由将其分开的部分。


创建一个破坏的飞机预置,一般步骤是:


把飞机模型在您最喜爱的模型有很多不同的地方
创建一个空的场景
拖动模型到空场景
添加刚体的所有部件,通过选择各零件和选择Component->Physics->Rigidbody
加框碰撞所有部件通过选择各零件和选择Component->Physics->Box Collider
一个额外的特殊效果,添加一个烟雾状粒子系统作为一个孩子的游戏对象的每一部分
现在你有一个飞机具有多个爆炸的部分,它们通过物理地将创建一个粒子轨迹由于连接的粒子系统。点击播放预览模型的反映,并做一些必要的调整。
选择Assets->Create Prefab
将含有所有飞机部件到预置的根对象
下面的例子说明了这些步骤是仿照代码。


// JavaScript


var wreck : GameObject;


// As an example, we turn the game object into a wreck after 3 seconds automatically
function Start () {
    yield WaitForSeconds(3);
    KillSelf();
}


// Calls the fire method when holding down ctrl or mouse
function KillSelf () {
    // Instantiate the wreck game object at the same position we are at
    var wreckClone = Instantiate(wreck, transform.position, transform.rotation);


    // Sometimes we need to carry over some variables from this object
    // to the wreck
    wreckClone.GetComponent.<MyScript>().someVariable = GetComponent.<MyScript>().someVariable;


    // Kill ourselves
    Destroy(gameObject);




// C#


public GameObject wreck;


// As an example, we turn the game object into a wreck after 3 seconds automatically
IEnumerator Start() {
    yield return new WaitForSeconds(3);
    KillSelf();
}


// Calls the fire method when holding down ctrl or mouse
void KillSelf () {
    // Instantiate the wreck game object at the same position we are at
    GameObject wreckClone = (GameObject) Instantiate(wreck, transform.position, transform.rotation);
   
    // Sometimes we need to carry over some variables from this object
    // to the wreck
    wreckClone.GetComponent<MyScript>().someVariable = GetComponent<MyScript>().someVariable;
   
    // Kill ourselves
    Destroy(gameObject);
}


}


将一组对象在一个特定的模式


比如说你想把一组对象在一个方形或圆形图案。通常这会做的:


建筑完全从代码的对象。这是乏味的!从脚本的输入值是缓慢的,直观的和不值得的麻烦。
使完全操纵的对象,它并把它复制多次在现场。这是乏味的,配售对象在网格中是很难准确。
所以使用instantiate()用预制件代替!我们认为你的问题是为什么在这些情况下非常有用的想法。这里的这些场景的必要的代码:


// JavaScript


// Instantiates a prefab in a circle


var prefab : GameObject;
var numberOfObjects = 20;
var radius = 5;


function Start () {
    for (var i = 0; i < numberOfObjects; i++) {
        var angle = i * Mathf.PI * 2 / numberOfObjects;
        var pos = Vector3 (Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
        Instantiate(prefab, pos, Quaternion.identity);
    }
}




// C#
// Instantiates a prefab in a circle


public GameObject prefab;
public int numberOfObjects = 20;
public float radius = 5f;


void Start() {
    for (int i = 0; i < numberOfObjects; i++) {
        float angle = i * Mathf.PI * 2 / numberOfObjects;
        Vector3 pos = new Vector3(Mathf.Cos(angle), 0, Mathf.Sin(angle)) * radius;
        Instantiate(prefab, pos, Quaternion.identity);
    }
}




// JavaScript


// Instantiates a prefab in a grid


var prefab : GameObject;
var gridX = 5;
var gridY = 5;
var spacing = 2.0;


function Start () {
    for (var y = 0; y < gridY; y++) {
        for (var x=0;x<gridX;x++) {
            var pos = Vector3 (x, 0, y) * spacing;
            Instantiate(prefab, pos, Quaternion.identity);
        }
    }
}




// C#


// Instantiates a prefab in a grid


public GameObject prefab;
public float gridX = 5f;
public float gridY = 5f;
public float spacing = 2f;


void Start() {
    for (int y = 0; y < gridY; y++) {
        for (int x = 0; x < gridX; x++) {
            Vector3 pos = new Vector3(x, 0, y) * spacing;
            Instantiate(prefab, pos, Quaternion.identity);
        }
    }
}


回复

使用道具 举报

0

主题

837

帖子

2713

积分

vip会员

Rank: 1

积分
2713
发表于 2016-7-13 19:28:53 | 显示全部楼层
来看看
回复 支持 反对

使用道具 举报

0

主题

851

帖子

2801

积分

vip会员

Rank: 1

积分
2801
发表于 2016-7-13 19:35:09 来自手机 | 显示全部楼层
楼主造福人类了谢谢
回复 支持 反对

使用道具 举报

0

主题

818

帖子

2684

积分

vip会员

Rank: 1

积分
2684
发表于 2016-7-13 20:04:16 来自手机 | 显示全部楼层
看看价格支持下
回复 支持 反对

使用道具 举报

0

主题

914

帖子

3035

积分

vip会员

Rank: 1

积分
3035
发表于 2016-7-13 20:38:48 来自手机 | 显示全部楼层
谢谢楼主分享!回复看下
回复 支持 反对

使用道具 举报

0

主题

855

帖子

2841

积分

vip会员

Rank: 1

积分
2841
发表于 2016-7-13 21:17:48 | 显示全部楼层
来看看
回复 支持 反对

使用道具 举报

0

主题

844

帖子

2754

积分

vip会员

Rank: 1

积分
2754
发表于 2016-7-13 21:58:22 来自手机 | 显示全部楼层
我是收集控~多谢分享~
回复 支持 反对

使用道具 举报

0

主题

910

帖子

2970

积分

vip会员

Rank: 1

积分
2970
发表于 2016-7-13 22:15:02 | 显示全部楼层
这个必须顶,撸主好人
回复 支持 反对

使用道具 举报

0

主题

884

帖子

2975

积分

vip会员

Rank: 1

积分
2975
发表于 2016-7-13 22:46:36 来自手机 | 显示全部楼层
这个不会又是超级贵吧.
回复 支持 反对

使用道具 举报

0

主题

827

帖子

2684

积分

vip会员

Rank: 1

积分
2684
发表于 2016-7-13 23:29:42 | 显示全部楼层
搬运工 辛苦了
回复 支持 反对

使用道具 举报

*滑块验证:
您需要登录后才可以回帖 登录 | enginedx注册

本版积分规则

 
 



邮件留言:


 
返回顶部