Building a wall
Unity 101
I'm currently working on a small script as part of a larger project. I'm trying to write a simple script to build a wall of blocks along a set axis using Cube shapes.
The final outcome would control placement and position of each newly created object on a 3D plain. At the moment I'm testing this on a 2D plane.
Example image: Initial Design | Framework
I'm trying to create a set of new objects (or prefabs) after each object stack, and limit this to the maximum width (x axis) of my Floor object. I would also like to be able to delete each object on key press - ultimately I would like objects to be removed and added at any time.
My question is: How would I go about implementing Destroy() on my Transform object?
N.B. I'm new to Unity and programming.
MY CODE:
#pragma strict
var brick : Transform;
// Set x and y variables
var y : int = 1;
var x : int = 0;
function Start () {
}
function Update () {
// If spacebar pressed create new object
if (Input.GetKeyDown ("space")) {
Instantiate(brick, Vector3(x,y,-4), Quaternion.identity);
// Increase y value and place new object on top of previous object
y = y + 1;
// If y is greater than set value
// Return y value to zero and increase x value
if (y > 3) {
y = 1;
x = x + 1;
print("x = " + x + " " + "y = " + y);
// If x is greater than Floor width set x value back to zero
if( x > 9) {
x = 0;
}
}
}
// If left ctrl press, delete brick object
if(Input.GetButtonUp("Fire1")){
Destroy(brick);
}
}
I suppose I have two questions, but my main question is this:
would like to know how to remove or Destroy() objects in my script. I'm trying to get it so that I can control the number of objects (Cubes) in my Scene - I'm essentially creating columns of cubes in my Game to simulate a procedural wall effect.*
Note: At the moment I keep receiving: "Destroying assets is not permitted..." error.
Answer by Freaking-Pingo · Nov 03, 2013 at 11:18 PM
I think the problem arises when you try to run Destroy(brick). Your prefab is assigned to brick in the Unity Inspector, which is simply a reference to the prefab in your local assets. The problem is, you are actually trying to "`Destroy()`" the local prefab in your Unity assets. Unity is just so nice and friendly, not letting you do that.
Instead, you should store the Instantiated gameobject into a GameObject variable, such as:
var newBrick : GameObject = Instantiate(brick, Vector3(x,y,-4), Quaternion.identity);
If you wan't to destroy this brick in the future, you should use Destroy(newBrick).
Ah, O$$anonymous$$, this is making sense.
I'm pretty much using examples from the Unity script resources. $$anonymous$$aybe you could help me understand something.
At the moment I'm creating a Transform prefab, and I get error:
"...can't convert 'UnityEngine.Transform' to 'UnityEngine.GameObject'"
When I change my brick var to GameObject (at the start of the script - from Transform) I lose control of translations.
I think I'm misunderstanding how prefabs and Transform work.
One way of doing it would be to change the variable type to Transform:
var newBrick : Transform = Instantiate(brick, Vector3(x,y,-4), Quaternion.identity);
And then you can destroy the object like this:
Destroy(newBrick.gameObject);
Thanks, seems to work, but I'm getting an error to assign instance reference:
"Object reference not set to an instance of an object"
I'm looking at the Destroy() reference. I take it that I need to keep track of each instance created to call destroy. I'm not clear on how to get around this.
Source reference: http://unity3d.com/learn/tutorials/modules/beginner/scripting/destroy
"Object reference not set to an instance of an object" is an error that often occurs when you are trying to use or access a variable like Transform or GameObject that is empty (No values assigned to it).
An example of this case would be Destroy(newBrick.gameObject);
where newBrick
haven't been assigned with any value.
I think I'm misunderstanding how instances work. I have a prefab
assigned to my Script
attached to an Empty
GameObject
. Calling Transform object with Instantiate
creates a clone of my prefab
. I'm not sure where I'm not assigning newBrick
i.e.
var newBrick : GameObject = Instantiate(brick, Vector3(x,y,-4), Quaternion.identity);
I've tried this with a single GameObject
(Cube) instance. I think I'm misunderstanding how GameObjects work entirely.
References:
http://docs.unity3d.com/Documentation/$$anonymous$$anual/InstantiatingPrefabs.html
http://www.unity3dstudent.com/2010/07/beginner-b05-instantiate-to-create-objects/
http://www.unity3dstudent.com/2010/07/beginner-b04-destroying-objects/
http://unity3d.com/learn/tutorials/modules/beginner/scripting/destroy
Answer by steveh2112 · Dec 24, 2016 at 11:47 PM
i wrote a script to generate a brick wall that allows for configurable height, width, randomness of brick width, tapering in height and random material.
here is the script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BrickWall : MonoBehaviour {
public AudioClip audioClip;
public GameObject source_brick;
public Material[] materials;
public int n_high = 10;
public int n_wide = 0;
public float width = 100;
public Vector3 brick_size = new Vector3(.7f, .5f, 5); // this is the basic brick size, can me modified by brick_random_x_max and brick_top_row_z
public float brick_random_x_max = 1.4f;
public float brick_top_row_z = .5f;
public Vector2 gap;
public bool bottomRowKinematic;
// Use this for initialization
void Start() {
Time.timeScale = 1;
Vector3 pos = Vector3.zero;
Quaternion rotation = Quaternion.identity;
// mother should i build a wall
// pre calc widths
for (int y = 0; y < n_high; y++, pos.y += brick_size.y+gap.y)
{
Vector3 localScale = brick_size;
if (brick_top_row_z != 0) {
localScale.z = Mathf.Lerp(brick_size.z, brick_top_row_z, (float)y / n_high);
}
pos.x = 0;
for (int x = 0 ; (n_wide==0) ? pos.x < width : x < n_wide ; x++)
{
// build a row
if (brick_random_x_max != 0)
{
// randomize width
localScale.x = Random.Range(brick_size.x, brick_random_x_max);
}
Vector3 place_pos = transform.position + pos;
place_pos.x += localScale.x / 2; // alling left size
GameObject brick = Instantiate(source_brick, place_pos, rotation, transform);
brick.transform.localScale = localScale;
Renderer rend = brick.GetComponent<Renderer>();
if (rend != null)
{
rend.material = materials[Random.Range(0, materials.Length-1)];
}
brick.name = "brick_" + x.ToString("D2") + "_" + y.ToString("D2");
pos.x += localScale.x + gap.y;
if(y==0)
{
if(bottomRowKinematic)
{
Rigidbody rb = brick.GetComponent<Rigidbody>();
if (rb != null)
rb.isKinematic = true;
}
}
}
}
}
}
to use it, create an empty object for your wall and attach this script. then create a cube (i guess any object will work) and make the scale 1,1,1. attach rigid body if you care about the physics. in the script, drag the cube to the source_brick slot drag your materials to the materials list (1 is ok) set the brick size if you set brick_random_x_max and public float brick_top_row_z to 0 it will be a standard brick wall brick_random_x_max gives you more of a stone wall effect brick_top_row_z lets you make a pyramid but in z direction only
i used this to make a dam wall
enjoy
PS, it doesn't scale or rotate. scaling you can take care of by changing the brick size parameter but it need rotation adding. maybe i'll add that when i have time