Unity3d中动态添加3D物体到场景的方法

3
我正在处理一个Unity3d项目,需要在按下某个键时在同一位置和方向上动态添加3D对象到场景中。为此,我导入了这些对象并制作了所有对象的预制件。我使用以下脚本进行操作,但它并不能达到预期的效果。新对象被实例化并添加到场景中,但旧对象没有被销毁。而且,新对象的位置不总是相同的。场景最初由一个立方体组成。当我按下“1”、“2”等键时,我希望一个新的对象替换显示的1(在同一位置)。

脚本:

var myCar : GameObject;
var Cube : GameObject;
var Globe: GameObject;
var Clock : GameObject;
var Pistol : GameObject;
var LCD : GameObject;
var prev : int;
var temp: GameObject; 
function Start ()
{
    prev =0;
    temp=null;

}

function Update () 
{
    if(prev==0)
        temp=Cube;
    else if(prev==1)
        temp=myCar;
    else if(prev==2)
        temp=Globe;
    else if(prev==3)
        temp=Pistol;
    else if(prev==4)
        temp=Clock;
    else if(prev==5)
        temp=LCD;       

    if(Input.GetKey(KeyCode.Alpha1 || KeyCode.Keypad1))
    {
        if(prev!=1)
        {
            Instantiate(myCar,temp.transform.position ,temp.transform.rotation);
            myCar.transform.localScale = Vector3(0.06,0.06,0.06);
            Destroy(temp);
            prev=1;
        }     
    }
    else if(Input.GetKey(KeyCode.Alpha2 || KeyCode.Keypad2))
    {
     if(prev!=2)
     {
        Instantiate(Globe,temp.transform.position ,temp.transform.rotation);
        Globe.transform.localScale = Vector3(0.04,0.04,0.04);
        Destroy(temp);
        prev=2;
     }

    }
    else if(Input.GetKey(KeyCode.Alpha3 || KeyCode.Keypad3))
    {
     if(prev!=3)
     {
        Instantiate(Pistol,temp.transform.position ,temp.transform.rotation);
        Pistol.transform.localScale = Vector3(0.03,0.03,0.03);
        Destroy(temp);
        prev =3;
     }
    }
    else if(Input.GetKey(KeyCode.Alpha4 || KeyCode.Keypad4))
    {
     if(prev!=4)
     {
          Instantiate(Clock,temp.transform.position ,temp.transform.rotation);
          Clock.transform.localScale = Vector3(0.08,0.08,0.08);
            Destroy(temp);
            prev=4;
     }

    }
    else if(Input.GetKey(KeyCode.Alpha5 || KeyCode.Keypad5))
    {
     if(prev!=5)
     {
        Instantiate(LCD,temp.transform.position ,temp.transform.rotation);
        LCD.transform.localScale = Vector3(0.04,0.04,0.04);
        Destroy(temp);
        prev=5;
     }
    }
}
1个回答

4

有几个需要考虑的问题:

  1. 最好将当前活动对象的引用存储起来,而不是使用 if-else-if 部分。
  2. Destroy 被调用在预制体上,而不是现有的 GameObject 实例上,因此没有任何作用。
  3. 对于所有对 transform 的操作都只影响预制体。
  4. 不是真正的 bug,但确实是一个增强功能:在我们的 3D 软件中缩放模型,这样就可以在不调整 localScale 的情况下进行实例化。
    更新:如果您无法访问 3D 软件(如 Blender、Maya 等)的原始模型,则可以在预制体中轻松定义适当的缩放比例。关键点是将代码中重复的内容最小化,并将各种属性设置放入预制体中。

综合以上建议:

  1. 像第4条建议一样完善您的原始模型。
  2. 引入成员变量来存储对当前对象的引用。
    更新:如果您想要一个特殊的对象,例如 Cube 在启动时被初始化,您首先将其拖入场景,然后从层次结构视图中将新创建的 Cube 拖到变量 current 中。这样,当脚本需要替换它时,您首先看到立方体。
  3. 创建一个用于对象实例化的方法。

我使用的是 C#,但应该是类似于以下代码:

var current : GameObject;  

...

function ReplaceObject (prefab : GameObject, newKey : int) {
    if (newKey != prev) {
        GameObject newObject = Instantiate(prefab, current.transform.position, 
            current.transform.rotation);
        Destroy(current);
        current = newObject;
        prev = newKey;
    }
}  

...

function Update () 
{
    if(Input.GetKey(KeyCode.Alpha1 || KeyCode.Keypad1)) {
        ReplaceObject (myCar, 1);
    } else if(Input.GetKey(KeyCode.Alpha2 || KeyCode.Keypad2))
        ReplaceObject (Globe, 2);

谢谢您的回复。我真的很新于Unity.. 我有点理解你所解释的.. 但我如何缩放对象并保持它们(当我没有将它们添加到场景中时)?我应该将它们保存在预制件中吗?而且,当前变量最初应指向立方体(已添加到场景中).. 对吗? - Heramb
1
非常感谢您的解释和代码,它完全按照我想要的方式工作。 :) - Heramb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接