nflacco
nflacco

Reputation: 5082

Unity prefab object is appearing in scene as its own object- not just clones

I'm trying to make a simple game where a player flies a cube through a series of gates. I'm running into a problem where the prefab of the player cube appears as in the scene when instantiated GameObject.Instantiate(Resources.Load("CubePrefab")), before it is cloned. This is unexpected, because I'm doing the exact same loading scheme for a different prefab, and it doesn't create this duplication where the prefab exists alongside its clones. Am I misunderstanding how prefabs work, or did I mess up a single line somewhere?

Below is a screenshot- gates in red, player cubes in blue. Selected in the hierarchy are the player cube prefab and gate prefab. Note that the player prefab appears as an actual cube.

I've attached code below for the GameMap/Gates, which create gate clones from a prefab properly, and the Player/Cube, which do not.

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;
    }
}

Upvotes: 0

Views: 811

Answers (1)

R1PFake
R1PFake

Reputation: 420

I think the problem is:

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

You Instantiate the prefab directly after loading it, i don't think that this is what you want, because this will create the additional object in your scene.

I think you want just load the prefab and instantiate it later in this case it should work if you change the line to:

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

Now you will only load the prefab from the resources and you can instantiate it later

Upvotes: 3

Related Questions