Unity预制对象作为自己的对象出现在场景中 - 而不仅仅是克隆

时间:2018-03-18 03:08:21

标签: unity3d

我正在尝试制作一个简单的游戏,玩家通过一系列大门飞过一个立方体。我遇到了一个问题,播放器多维数据集的预制在实例化GameObject.Instantiate(Resources.Load("CubePrefab"))之前出现在场景中,然后才会被克隆。这是意料之外的,因为我正在为不同的预制件执行完全相同的加载方案,并且它不会在预制件与其克隆一起存在的情况下创建这种重复。 我误解了预制件是如何工作的,还是我在某个地方乱了一条线?

下面是红色的屏幕截图,蓝色的玩家立方体。在层次结构中选择的是播放器立方体预制件和门预制件。请注意,播放器预制件显示为实际的多维数据集。

我在下面为GameMap / Gates附加了代码,它们可以正确地从预制件创建门克隆,而播放器/多维数据集则没有。

enter image description here

GameMap.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameMap {
    private GameObject gatePrefab = GameObject.Instantiate(Resources.Load("GatePrefab")) as GameObject;

    public GameMap() {}

    public void Setup () {
        Vector3 position;
        Quaternion rotation;

        position = new Vector3(0, 0, 0);
        rotation = Quaternion.identity;
        CreateGate(position, rotation, 10.0f, 2.0f, "Gate 1");

        position = new Vector3(0, 0, 20);
        rotation =  Quaternion.identity * Quaternion.Euler(0, 45, 0);
        CreateGate(position, rotation, 10.0f, 1.0f, "Gate 2");

        position = new Vector3(20, 0, 20);
        rotation =  Quaternion.identity * Quaternion.Euler(0, 90, 0);
        CreateGate(position, rotation, 8.0f, 1.0f, "Gate 3");

        CreateGround();
    }

    private void CreateGate(Vector3 position, Quaternion rotation, float lengthOfSide, float thickness, string name) {
        // Create the gates, and call the "Initialize" method to populate properties as Unity doesn't have constructors.
        GameObject clone = GameObject.Instantiate(gatePrefab, position, rotation) as GameObject;
        clone.name = name;
        clone.GetComponent<Gate>().Initialize(lengthOfSide, thickness);
    }

    private void CreateGround() {
        GameObject ground = GameObject.CreatePrimitive(PrimitiveType.Plane);
        ground.name = "Ground";
        ground.transform.localPosition = new Vector3(0, -10, 0);
        ground.transform.localRotation = Quaternion.identity;
        ground.transform.localScale = new Vector3(50, 1, 50);

        ground.GetComponent<Renderer>().material.color = Color.grey;
    }
}

Gate.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Gate : MonoBehaviour {
    float lengthOfSide;
    float thickness;

    public void Initialize (float lengthOfSide, float thickness) {
        this.lengthOfSide = lengthOfSide;
        this.thickness = thickness;
    }

    // Use this for initialization
    void Start () {
        SetupRigidBody();
        Setup3dEntities();
    }

    void SetupRigidBody() {
        Rigidbody rb = this.gameObject.AddComponent<Rigidbody>();
        rb.detectCollisions = true;
        rb.mass = 1000;
        rb.useGravity = false;
    }

    // Create the physical gate
    void Setup3dEntities() {
        Vector3 position;
        Vector3 scale;
        float lengthOfVeritcalSegment = lengthOfSide - (2 * thickness);
        float yPosHorizontalSegment = (lengthOfSide - thickness) / 2;
        float xPosVerticalSegment = lengthOfSide - thickness;

        // Bottom
        position = new Vector3(0, -yPosHorizontalSegment, 0);
        scale = new Vector3(lengthOfSide, thickness, thickness);
        CreatePrimitiveCube(position, scale);

        // Top
        position = new Vector3(0, yPosHorizontalSegment, 0);
        scale = new Vector3(lengthOfSide, thickness, thickness);
        CreatePrimitiveCube(position, scale);

        // Left
        position = new Vector3(xPosVerticalSegment/2, 0, 0);
        scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
        CreatePrimitiveCube(position, scale);

        // Right
        position = new Vector3(-xPosVerticalSegment/2, 0, 0);
        scale = new Vector3(thickness, lengthOfVeritcalSegment, thickness);
        CreatePrimitiveCube(position, scale);
    }

    void CreatePrimitiveCube(Vector3 position, Vector3 scale) {
        // Create a primitive cube. Note that we want to set the position and rotation to match the parent!
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.transform.parent = gameObject.transform; // TODO: is this safe to have here?
        cube.transform.localPosition = position;
        cube.transform.localRotation = Quaternion.identity;
        cube.transform.localScale = scale;

        // TODO: Make a better color/material mechanism!
        cube.GetComponent<Renderer>().material.color = Color.red;

//      Debug.Log("Cube.parent: " + cube.transform.parent.gameObject.name);
//      Debug.Log("Cube.localScale: " + cube.transform.localScale);
    }
}

Player.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Player
{
    private GameObject cubePrefab = GameObject.Instantiate(Resources.Load("CubePrefab")) as GameObject;
    public float moveSpeed = 3f;
    private GameObject playerObject;

    private Vector3 startingPosition;
    private Quaternion startingRotation;
    private Transform transform;

    public Player(){}

    public void Setup() {
        startingPosition = new Vector3(0, 0, 0);
        startingRotation = Quaternion.identity;
        Vector3 scale = new Vector3(2, 2, 2);

        GameObject clone = GameObject.Instantiate(cubePrefab, startingPosition, startingRotation) as GameObject;
        clone.name = "Playercube";
        clone.GetComponent<Cube>().Initialize();
        playerObject = clone;

        // Make main camera child of drone
        Camera.main.transform.parent = playerObject.transform;
    }

    public void Move(float verticalInput, float horizontalInput) {
        float moveSpeed = 3f;
        float verticalSpeed = verticalInput * moveSpeed;
        float horizontalSpeed = horizontalInput * moveSpeed;

        Debug.Log("Player.Move verticalSpeed:"+verticalSpeed+" horizontalSpeed:"+horizontalSpeed);

        //Moves Forward and back along z axis                           //Up/Down
        playerObject.transform.Translate(Vector3.forward * Time.deltaTime * verticalSpeed);
        //Moves Left and right along x Axis                               //Left/Right
        playerObject.transform.Translate(Vector3.right * Time.deltaTime * horizontalSpeed);
    }
}

Cube.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Cube : MonoBehaviour {

    public void Initialize () {
    }

    // Use this for initialization
    void Start () {
        Vector3 position = new Vector3(0, 0, 0);
        Vector3 scale = new Vector3(2, 2, 2);
        CreatePrimitiveCube(position, scale);
//      SetupPhysics();
    }

    void CreatePrimitiveCube(Vector3 position, Vector3 scale) {
        // Create a primitive cube. Note that we want to set the position and rotation to match the parent!
        GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
        cube.transform.parent = gameObject.transform;
        cube.transform.localPosition = position;
        cube.transform.localRotation = Quaternion.identity;
        cube.transform.localScale = scale;

        // TODO: Make a better color/material mechanism!
        cube.GetComponent<Renderer>().material.color = Color.blue;
    }

    void SetupPhysics() {
        Rigidbody rb = gameObject.AddComponent<Rigidbody>();
        rb.detectCollisions = true;
        rb.mass = 1;
        rb.useGravity = false;

        gameObject.AddComponent<MeshRenderer>();
        BoxCollider boxCollider = gameObject.AddComponent<BoxCollider>();
        MeshRenderer renderer = gameObject.GetComponent<MeshRenderer>();
        boxCollider.center = renderer.bounds.center;
        boxCollider.size = renderer.bounds.size;
    }
}

1 个答案:

答案 0 :(得分:2)

我认为问题是:

private GameObject cubePrefab = GameObject.Instantiate(Resources.Load("CubePrefab")) as GameObject;

您在加载后直接实例化预制件,我不认为这是您想要的,因为这将在您的场景中创建其他对象。

我认为您只想加载预制件并稍后将其实例化,在这种情况下,如果您将线路更改为:

private GameObject cubePrefab = Resources.Load("CubePrefab") as GameObject;

现在您只需从资源加载预制件,然后可以稍后实例化