- Home /
Problems with the instantiation of a GameObject C#
I have a problem when i try to create a wall in unity, you see, i have a mouse dragging sistem than avoid to create tiles & walls, the tiles creation/destruction works fine, but the wall creation is creating an object but not initialising any of the data of it at all, really i don't know what else to do, i was following this tutorial:
https://www.youtube.com/playlist?list=PLbghT7MmckI4_VM5q3va043FgAwRim6yX
I modify some things to learn about, but it was working perfectly, now i can't not even know why the GameObject do not initialize after beeing successfully created, i must say, it would be cool if some of you tell me how to fix my problem, here is all the code involved.
its seems than my code "create two times the object" in the same place because it report than an object already has been created there, in that location, an also create this new GameObject without name, parent or sprite at all of the wall intended, but still i can't find where is the first creation coming.
The parts than are mainly involved are surrounded by /////////////////////////////////////////////////////////, please not than this are not the only part vinculated to the process, but are the most suspicious about it.
If anyone request some clarification somewhere about this or have any question, please let me know, i'll add the answer &/or new data to the question itself to avoid it in the future.
Here is the code:
InstalledObject.cs
using UnityEngine;
using System.Collections;
using System;
public class InstalledObject {
Tile tile;
//To know what render in the spriteRenderer
public string ObjectType { get; protected set; }
public Tile Tile { get; protected set; }
float movementCost = 1f; //This is a multiplier. So a value of "2" here means you move twice as slowly
//for the image in the world only
int width = 1;
int height = 1;
Action<InstalledObject> cbOnChanged;
//TODO: Implement larger objects & rotation
/////////////////////////////////////////////////////////(start)
protected InstalledObject(){
}
public static InstalledObject CreatePrototype(string objectType, float movementCost=1f, int width=1, int height=1) {
InstalledObject InstObjNew = new InstalledObject();
InstObjNew.ObjectType = objectType;
InstObjNew.movementCost = movementCost;
InstObjNew.width = width;
InstObjNew.height = height;
return InstObjNew;
}
public static InstalledObject PlaceInstance(InstalledObject proto, Tile tile){
InstalledObject InstObjNew = new InstalledObject();
InstObjNew.ObjectType = proto.ObjectType;
InstObjNew.movementCost = proto.movementCost;
InstObjNew.width = proto.width;
InstObjNew.height = proto.height;
InstObjNew.tile = tile;
//This asume is 1x1
if ( !tile.PlaceObject (InstObjNew) ) {
//for some reason we weren't able to place our object in this tile.
//(Probably it was already occupied.)
Debug.LogError ("Space already in use");
//Do NOT return our newly instantiated object.
//(It will be garbage collected.)
return null;
}
return InstObjNew;
}
/////////////////////////////////////////////////////////(end)
public void RegisterOnChangedCallback (Action<InstalledObject> callbackFunc){
cbOnChanged += callbackFunc;
}
public void UnregisterOnChangedCallback (Action<InstalledObject> callbackFunc){
cbOnChanged -= callbackFunc;
}
}
WorldController.cs
using System;
using UnityEngine;
using System.Collections.Generic;
public class WorldController : MonoBehaviour {
public static WorldController Instance { get; protected set;}
//To know how must look at it make array &/or database
public Sprite floorSprite; //FIXME
/////////////////////////////////////////////////////////(start)
public Sprite wallSprite; //FIXME
/////////////////////////////////////////////////////////(end)
Dictionary<Tile, GameObject> DicTileGameObjectMap;
/////////////////////////////////////////////////////////(start)
Dictionary<InstalledObject, GameObject> DicInstalledObjectGameObjectMap;
/////////////////////////////////////////////////////////(end)
public World World { get; protected set; }
void Start(){
if (Instance != null) {
Debug.Log("There should never be two world controllers, it just can be one!");
}
Instance = this;
//Create a world with empty tiles
World = new World ();
World.RegisterInstalledObjectCreated (OnInstalledObjectCreated);
// Instantiate our dictionary that track which GameObject is rendering which Tile data
DicTileGameObjectMap = new Dictionary<Tile, GameObject> ();
/////////////////////////////////////////////////////////(start)
DicInstalledObjectGameObjectMap = new Dictionary<InstalledObject, GameObject> ();
/////////////////////////////////////////////////////////(end)
//Create a GameObject for each of our tiles, so they show visually. (and redunt redundantly)
for (int x = 0; x < World.Width; x++) {
for (int y = 0; y < World.Height; y++) {
Tile tile_data = World.GetTileAt(x,y);
GameObject tile_GO = new GameObject();
//Add our tile/GameObject to the dictionary
DicTileGameObjectMap.Add(tile_data,tile_GO);
tile_GO.name = "Tile_"+x+"_"+y;
tile_GO.transform.position = new Vector3(tile_data.X,tile_data.Y,0);
tile_GO.transform.SetParent(this.transform, true);
/*
SpriteRenderer tile_spr = tile_GO.AddComponent<SpriteRenderer>();
if(tile_data.Type == Tile.TileType.Floor){
tile_spr.sprite = floorSprite;
}
*/
//Add a sprite renderer, but not set a sprite (Yet)
tile_GO.AddComponent<SpriteRenderer>();
//Register our callback so that our GameObject gets updated whenever the tile type change
tile_data.RegisterTileTypeChangedCallback( OnTileTypeChanged );
}
}
World.RandomizeTiles ();
}
//float randomizeTileTimer = 2f;
void Update (){/*
randomizeTileTimer -= Time.deltaTime;
if (randomizeTileTimer < 0) {
World.RandomizeTiles ();
randomizeTileTimer = 2f;
} */
}
void DestroyAllTileGameObjects(){
foreach (var pair in DicTileGameObjectMap) {
Tile tile_data = pair.Key;
GameObject tile_GO = pair.Value;
//Remove the pair from the map
DicTileGameObjectMap.Remove(pair.Key);
//Unregister the callback!
tile_data.UnregisterTileTypeChangedCallback(OnTileTypeChanged);
//Destroy the visual GameObject
Destroy (tile_GO);
}
}
public void OnTileTypeChanged(Tile tile_data){
GameObject tile_GO = DicTileGameObjectMap [tile_data];
if (!DicTileGameObjectMap.ContainsKey (tile_data)) {
Debug.Log ("dataObject not find in the dictionary, please chech than the GameObject was successfully added with the dataObject and then try again");
return;
}
if (tile_GO != null) {
if (tile_data.Type == Tile.TileType.Floor) {
tile_GO.GetComponent<SpriteRenderer> ().sprite = floorSprite;
} else if (tile_data.Type == Tile.TileType.Empty) {
tile_GO.GetComponent<SpriteRenderer> ().sprite = null;
} else {
Debug.LogError ("OnTileTypeChanged - Unrecognized tile Type: " + tile_data.Type.ToString ());
}
} else {
Debug.Log ("dataObject not find in the dictionary, please chech than the GameObject was successfully added with the dataObject and then try again");
return;
}
}
public Tile GetTileAtWorldCoord(Vector3 coord){
int x = Mathf.FloorToInt (coord.x);
int y = Mathf.FloorToInt (coord.y);
return World.GetTileAt (x, y);
}
/////////////////////////////////////////////////////////(start)
//Create a visual GameObject linked to this data
public void OnInstalledObjectCreated(InstalledObject objNew){
Debug.Log ("OnInstalledObjectCreated");
//Game Object creation
GameObject InstObjNew_GO = new GameObject ();
//Adding it to the dictionary and vinculating with the data Object
DicInstalledObjectGameObjectMap.Add (objNew, InstObjNew_GO);
//Game Object instantiation
InstObjNew_GO.name = objNew.ObjectType+"_"+objNew.Tile.X+"_"+objNew.Tile.Y;
InstObjNew_GO.transform.position = new Vector3 (objNew.Tile.X, objNew.Tile.Y, 0);
InstObjNew_GO.transform.SetParent (this.transform, true);
//FIXME: WE ASSUME THAT THE OBJECT MUST BE A WALL, FOR NOW,
InstObjNew_GO.AddComponent<SpriteRenderer>().sprite = wallSprite; //FIXME
//Register our callback so that our GameObject gets updated whenever
//the object's into change.
objNew.RegisterOnChangedCallback (OnInstalledObjectChanged);
}
/////////////////////////////////////////////////////////(end)
void OnInstalledObjectChanged(InstalledObject obj){
}
}
MouseController.cs
using UnityEngine;
using System.Collections.Generic;
using UnityEngine.EventSystems;
public class MouseController : MonoBehaviour {
// What are you building
bool isTileOrInstall;
// If object of the Installed ones, of which type
string buildModeObjectType;
// to reset the buttons
bool isSelectedButton = false;
// Some requested base data
int varTileType = 99;
public GameObject circleCursorPrefab;
// The world-position of the mouse last frame.
Vector3 lastFramePosition;
Vector3 currFramePosition;
// The world-position of our left-mouse drag operation.
Vector3 dragStartPosition;
//The list of selected objects via Selection dragging.
List<GameObject> dragPreviewGameObjects;
// Use this for initialization
void Start () {
//mouseCursor_GO.AddComponent <SpriteRenderer>();
dragPreviewGameObjects = new List<GameObject> ();
}
// Update is called once per frame
void Update () {
currFramePosition = Camera.main.ScreenToWorldPoint (Input.mousePosition);
currFramePosition.z = 0;
// UpdateCursor ();
UpdateDragging ();
UpdateCameraMovement ();
// Save the mouse position from this frame
// We don't use currFramePosition because we may have moved the camera.
lastFramePosition = Camera.main.ScreenToWorldPoint( Input.mousePosition );
lastFramePosition.z = 0;
//ChangeTileOnClick ();
}
// public void UpdateCursor(){
// //Update the circle cursor position
// Tile tileUnderMouse = WorldController.Instance.GetTileAtWorldCoord(currFramePosition);
// if(tileUnderMouse != null){
// circleCursor.SetActive(true);
// Vector3 cursorPosition = new Vector3 (tileUnderMouse.X, tileUnderMouse.Y, 0);
// //To follow over without been fixed in the middle of Tiles
// //circleCursor.transform.position = currFramePosition;
// //To be fixed in the middle of the Tiles
// circleCursor.transform.position = cursorPosition;
// } else {
// circleCursor.SetActive(false);
// }
// }
public void UpdateDragging (){
// Start Selection drag.
if (Input.GetMouseButtonDown (0)) {
dragStartPosition = currFramePosition;
} else if (EventSystem.current.IsPointerOverGameObject ()) {
return;
}
// Prepare data for selection drag.
int start_x = Mathf.FloorToInt (dragStartPosition.x);
int end_x = Mathf.FloorToInt (currFramePosition.x);
int start_y = Mathf.FloorToInt (dragStartPosition.y);
int end_y = Mathf.FloorToInt (currFramePosition.y);
//Ordering data to make the showing of the drag
if (start_x > end_x) {
int tmpInt = end_x;
end_x = start_x;
start_x = tmpInt;
//Debug.Log ("start_x: " + start_x + " > end_x: " + end_x);
} else {
//Debug.Log ("start_x: " + start_x + " < end_x: " + end_x);
}
if (start_y > end_y) {
int tmpInt = end_y;
end_y = start_y;
start_y = tmpInt;
//Debug.Log ("start_y: " + start_y + " > end_y: " + end_y);
} else {
//Debug.Log ("start_y: " + start_y + " < end_y: " + end_y);
}
// Clean up old drag previews
while (dragPreviewGameObjects.Count > 0 ) {
GameObject go = dragPreviewGameObjects[0];
dragPreviewGameObjects.RemoveAt(0);
SimplePool.Despawn (go);
}
// Display a preview hint of the dragged area.
if (Input.GetMouseButton (0)) {
for(int x = start_x; x<=end_x; x++){
for(int y = start_y; y<=end_y; y++){
if(WorldController.Instance.World.GetTileAt(x,y) != null){
GameObject GO = SimplePool.Spawn(circleCursorPrefab, new Vector3(x,y,0),Quaternion.identity);
GO.transform.SetParent(this.transform, true);
dragPreviewGameObjects.Add(GO);
Debug.Log("Tile_"+WorldController.Instance.World.GetTileAt(x,y).X.ToString()+"_"+WorldController.Instance.World.GetTileAt(x,y).Y.ToString() + " has been sucessfully instanciated");
} else {
Debug.Log ("Invalid Tile, it hasn't been sucessfully instancianted");
}
}
}
}
// End Selection drag
if (Input.GetMouseButtonUp (0)) {
/////////////////////////////////////////////////////////(start)
// Loop through all the tiles
for(int x = start_x; x<=end_x; x++){
for(int y = start_y; y<=end_y; y++){
Tile t = WorldController.Instance.World.GetTileAt (x, y);
if (t != null) {
if (isTileOrInstall && isSelectedButton) {
t.ChangeType (varTileType);
} else if (!isTileOrInstall && isSelectedButton) {
WorldController.Instance.World.PlaceInstalledObject (buildModeObjectType, t);
Debug.Log (buildModeObjectType + " successfully created at: " + t.X.ToString () + " " + t.Y.ToString ());
}
if (WorldController.Instance.World.GetTileAt (x, y) != null) {
Debug.Log ("Tile_" + WorldController.Instance.World.GetTileAt (x, y).X.ToString () + "_" + WorldController.Instance.World.GetTileAt (x, y).Y.ToString () + " added successfully");
} else {
Debug.Log ("Tile invalido, no ha sido agregado a la lista");
}
}
}
}
//dragPreviewGameObjects.Clear();
} /////////////////////////////////////////////////////////(end)
}
public void UpdateCameraMovement (){
// Handle screen dragging
if (Input.GetMouseButton (1) || Input.GetMouseButton(2)) { // Right or middle mouse Button
Vector3 diff = lastFramePosition - currFramePosition;
Camera.main.transform.Translate( diff);
Debug.Log (diff+" Es la posicion del mouse en este momento");
}
// Work Zoom in, Zoom out
Camera.main.orthographicSize += Camera.main.orthographicSize * Input.GetAxis ("Mouse ScrollWheel")*-1;
//Limits of the Zoom
Camera.main.orthographicSize = Mathf.Clamp (Camera.main.orthographicSize, 1f, 25f);
}
public void BuildTileOnDemand(){
//Tile Tle = WorldController.Instance.World.GetTileAt((int)currFramePosition.x,(int)currFramePosition.y);
ResetButton ();
isTileOrInstall = true;
if (!isSelectedButton) {
varTileType = 1;
isSelectedButton = true;
} else {
varTileType = 99; //this intentionaly does nothing
isSelectedButton = false;
}
}
public void BulldozeOnDemand(bool tmpBoolBulldoze){
ResetButton ();
if (!isSelectedButton && tmpBoolBulldoze) {
varTileType = 0; //this destroy Tiles
isTileOrInstall = true;
isSelectedButton = true;
//Debug.Log ("isSelectedButton: " + isSelectedButton.ToString () + " tmpBoolBulldoze: " + tmpBoolBulldoze.ToString());
//Debug.Log("isTileOrInstall: "+isTileOrInstall);
} else {
varTileType = 99; //this intentionaly does nothing
isTileOrInstall = false;
isSelectedButton = false;
//Debug.Log("isTileOrInstall: "+isTileOrInstall);
//Debug.Log ("isSelectedButton: " + isSelectedButton.ToString () + " tmpBoolBulldoze: " + tmpBoolBulldoze.ToString());
}
}
/////////////////////////////////////////////////////////(start)
public void BuildObject_BuildInstalledObject(string objType){
ResetButton ();
isTileOrInstall = false;
if (!isSelectedButton) {
isSelectedButton = true;
buildModeObjectType = objType;
} else {
isSelectedButton = false;
}
Debug.Log ("State isTileOrInstall: " + isTileOrInstall.ToString());
Debug.Log ("State isSelectedButton: " + isSelectedButton.ToString());
Debug.Log ("State buildModeObjectType: " + buildModeObjectType);
}
public void ResetButton(){
Debug.Log ("Pre ResetButton() executed - " + isSelectedButton.ToString ());
if (isSelectedButton) {
isSelectedButton = false;
} else {
return;
}
Debug.Log ("ResetButton() executed - " + isSelectedButton.ToString ());
}
/////////////////////////////////////////////////////////(end)
bool GetMouseBordersX(Tile tillf){
if (tillf.X <= 95 && tillf.X >= 5) {
return true;
} else {
return false;
}
}
bool GetMouseBordersY(Tile tillf){
if (tillf.Y <= 95 && tillf.Y >= 5) {
return true;
} else {
return false;
}
}
bool GetMouseBorders(Tile tillf){
if (GetMouseBordersY (tillf) && GetMouseBordersY (tillf)) {
return true;
} else {
return false;
}
}
}
World.cs
using UnityEngine;
using System.Collections.Generic;
using System;
public class World{
Tile[,] tiles;
int width;
int height;
Dictionary<string, InstalledObject> InstalledObjectPrototypes;
public Tile[,] Tiles {
get {
return tiles;
}
set {
tiles = value;
}
}
public int Width { get; protected set; }
public int Height { get; protected set; }
Action<InstalledObject> cbInstalledObjectCreated;
public World(int width = 100, int height = 100){
this.Width = width;
this.Height = height;
tiles = new Tile[Width, Height];
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
tiles[x,y] = new Tile(this,x,y);
}
}
Debug.Log ("World Created with " + (Width * Height) + " tiles.");
//Creating prototypes for the world
CreateInstallObjectPrototypes ("Wall",0f,1,1);
}
public Tile GetTileAt(int x, int y) {
if((x>Width || x<0) && (y>Height || y<0)){
Debug.LogError("Tile ("+x+","+y+"), is out of range.");
return null;
} else {
foreach (var til in tiles) {
if(til.X==x && til.Y==y){
return til;
}
}
}
return null;
}
/*public Tile GetTileAt(int x,int y) {
if (x > width || x < 0 || y > height || y < 0) {
Debug.LogError("Tile ("+x+","+y+") is out of range.");
return null;
}
return tiles [x, y];
}*/
public void RandomizeTiles(){
//do{
Debug.Log ("RandomizeTiles() Was successfully called.");
for (int x = 0; x < Width; x++) {
for (int y = 0; y < Height; y++) {
if (UnityEngine.Random.Range (0, 2) == 1) {
tiles [x, y].Type = Tile.TileType.Empty;
Debug.Log("Successfully created EMPTY tile");
} else {
tiles [x, y].Type = Tile.TileType.Floor;
Debug.Log("Successfully created Floor tile");
}
}
}
//}
//while(!this.CountFloor());
}
public string NumCountFloor(){
int numberEmpty = 0;
int numberFloor = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if((int)this.GetTileAt(x,y).Type == 0){
numberEmpty++;
}else if((int)this.GetTileAt(x,y).Type == 1){
numberFloor++;
}
}
}
Debug.Log ("The number of Solid Floor Tiles is: "+numberFloor+"\nThe number of Empty Floor Tiles is: "+numberEmpty);
return "The number of Solid Floor Tiles is: "+numberFloor+" and the empty ones are: "+numberEmpty;
}
public bool CountFloor(){
int numberEmpty = 0;
int numberFloor = 0;
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if((int)this.GetTileAt(x,y).Type == 0){
numberEmpty++;
}else if((int)this.GetTileAt(x,y).Type == 1){
numberFloor++;
}
}
}
if (numberEmpty > (numberFloor /4)) {
Debug.Log ("The number of Solid Floor Tiles is: "+numberFloor);
Debug.Log ("The number of Empty Floor Tiles is: "+numberEmpty);
return true;
} else {
Debug.Log ("The number of Solid Floor Tiles is: "+numberFloor);
Debug.Log ("The number of Empty Floor Tiles is: "+numberEmpty);
return false;
}
}
public void FloorFixer(){
do {
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if ((int)this.GetTileAt (x, y).Type == 0) {
if(UnityEngine.Random.Range(0,2)==1){
tiles[x,y].Type = Tile.TileType.Empty;
}
else
{
tiles[x,y].Type = Tile.TileType.Floor;
}
}
}
}
} while(this.CountFloor ());
}
/////////////////////////////////////////////////////////(start)
//Create Installed Object (Prototypes)
void CreateInstallObjectPrototypes(string objectName,float movementEffect,int width,int height) {
InstalledObjectPrototypes = new Dictionary<string, InstalledObject>();
InstalledObjectPrototypes.Add(objectName,InstalledObject.CreatePrototype (objectName,movementEffect,width,height));
Debug.Log ("Added Successfully the Prototype: "+objectName);
}
//Place an instance of the Prototype installed
public void PlaceInstalledObject(string objectType, Tile t){
Debug.Log ("PlaceInstalledObject objectType: "+objectType);
if (!InstalledObjectPrototypes.ContainsKey (objectType)) {
Debug.Log ("InstalledObjectPrototypes doesn't contain a proto for key: " + objectType);
return;
}
InstalledObject ObjNew = InstalledObject.PlaceInstance (InstalledObjectPrototypes [objectType], t);
if (cbInstalledObjectCreated != null) {
cbInstalledObjectCreated (ObjNew);
}
}
/////////////////////////////////////////////////////////(end)
public void RegisterInstalledObjectCreated(Action<InstalledObject> callbackfunc){
cbInstalledObjectCreated += callbackfunc;
}
public void UnregisterInstalledObjectCreated(Action<InstalledObject> callbackfunc){
cbInstalledObjectCreated -= callbackfunc;
}
}
Tile.cs
using UnityEngine;
using System.Collections;
using System;
public class Tile {
public enum TileType {Empty, Floor};
TileType type = TileType.Empty;
Action<Tile> cbTileTypeChanged;
GameObject myVisualTileGameObject;
LooseObject looseObject;
InstalledObject installedObject;
//To know if you can build over this block
bool isBuildiable;
World world;
int x;
int y;
int modificable;
public TileType Type {
get {
return type;
}
set {
TileType oldType = type;
type = value;
//Call a callback and let things know we've changed.
if (cbTileTypeChanged != null && oldType != type) {
cbTileTypeChanged (this);
}
}
}
public int X {
get {
return x;
}
protected set {
x = value;
}
}
public int Y {
get {
return y;
}
protected set {
y = value;
}
}
public Tile(World World_Axis,int X_Axis,int Y_Axis){
this.world = World_Axis;
this.x = X_Axis;
this.y = Y_Axis;
this.modificable = 0;
}
public void RegisterTileTypeChangedCallback(Action<Tile> callback){
cbTileTypeChanged += callback;
}
public void UnregisterTileTypeChangedCallback(Action<Tile> callback){
cbTileTypeChanged -= callback;
}
public void ChangeType (int tmpInt){
switch (tmpInt) {
case 0:
this.Type = TileType.Empty;
this.isBuildiable = false;
break;
case 1:
this.Type = TileType.Floor;
this.isBuildiable = true;
break;
case 99:
return;
}
}
public void ChangeType (String tmpString){
if (tmpString != null && tmpString.ToUpper().Trim() != "F") {
if (this.Type == TileType.Floor) {
this.Type = TileType.Empty;
} else {
this.Type = TileType.Floor;
}
} else if (tmpString.ToUpper ().Trim() == "F") {
if (this.Type == TileType.Empty) {
this.Type = TileType.Floor;
}
}
}
/////////////////////////////////////////////////////////(start)
public bool PlaceObject (InstalledObject objInstance) {
if (objInstance == null) {
// We are uninstalling whatever was here before.
installedObject = null;
return true;
}
if (objInstance != null) {
//Debug.Log ("Trying to assign an installed object to a tile that already has one!");
Debug.LogError ("Trying to assign an installed object to a tile that already has one!");
return false;
}
installedObject = objInstance;
return true;
}
/////////////////////////////////////////////////////////(end)
}
----------(SimplePool is not mine, it is a utilitary tool created and subministrated by the tutorial creator, still, you can get it on internet)--------------------
SimplePool.cs
/// Latest Version: https://gist.github.com/quill18/5a7cfffae68892621267
/// License: CC0 (http://creativecommons.org/publicdomain/zero/1.0/)
/// UPDATES:
/// 2015-04-16: Changed Pool to use a Stack generic.
///
/// Usage:
///
/// There's no need to do any special setup of any kind.
///
/// Instead of call Instantiate(), use this:
/// SimplePool.Spawn(somePrefab, somePosition, someRotation);
///
/// Instead of destroying an object, use this:
/// SimplePool.Despawn(myGameObject);
///
/// If desired, you can preload the pool with a number of instances:
/// SimplePool.Preload(somePrefab, 20);
///
/// Remember that Awake and Start will only ever be called on the first instantiation
/// and that member variables won't be reset automatically. You should reset your
/// object yourself after calling Spawn(). (i.e. You'll have to do things like set
/// the object's HPs to max, reset animation states, etc...)
///
///
///
using UnityEngine;
using System.Collections.Generic;
public static class SimplePool {
// You can avoid resizing of the Stack's internal array by
// setting this to a number equal to or greater to what you
// expect most of your pool sizes to be.
// Note, you can also use Preload() to set the initial size
// of a pool -- this can be handy if only some of your pools
// are going to be exceptionally large (for example, your bullets.)
const int DEFAULT_POOL_SIZE = 3;
/// <summary>
/// The Pool class represents the pool for a particular prefab.
/// </summary>
class Pool {
// We append an id to the name of anything we instantiate.
// This is purely cosmetic.
int nextId=1;
// The structure containing our inactive objects.
// Why a Stack and not a List? Because we'll never need to
// pluck an object from the start or middle of the array.
// We'll always just grab the last one, which eliminates
// any need to shuffle the objects around in memory.
Stack<GameObject> inactive;
// The prefab that we are pooling
GameObject prefab;
// Constructor
public Pool(GameObject prefab, int initialQty) {
this.prefab = prefab;
// If Stack uses a linked list internally, then this
// whole initialQty thing is a placebo that we could
// strip out for more minimal code.
inactive = new Stack<GameObject>(initialQty);
}
// Spawn an object from our pool
public GameObject Spawn(Vector3 pos, Quaternion rot) {
GameObject obj;
if(inactive.Count==0) {
// We don't have an object in our pool, so we
// instantiate a whole new object.
obj = (GameObject)GameObject.Instantiate(prefab, pos, rot);
obj.name = prefab.name + " ("+(nextId++)+")";
// Add a PoolMember component so we know what pool
// we belong to.
obj.AddComponent<PoolMember>().myPool = this;
}
else {
// Grab the last object in the inactive array
obj = inactive.Pop();
if(obj == null) {
// The inactive object we expected to find no longer exists.
// The most likely causes are:
// - Someone calling Destroy() on our object
// - A scene change (which will destroy all our objects).
// NOTE: This could be prevented with a DontDestroyOnLoad
// if you really don't want this.
// No worries -- we'll just try the next one in our sequence.
return Spawn(pos, rot);
}
}
obj.transform.position = pos;
obj.transform.rotation = rot;
obj.SetActive(true);
return obj;
}
// Return an object to the inactive pool.
public void Despawn(GameObject obj) {
obj.SetActive(false);
// Since Stack doesn't have a Capacity member, we can't control
// the growth factor if it does have to expand an internal array.
// On the other hand, it might simply be using a linked list
// internally. But then, why does it allow us to specificy a size
// in the constructor? Stack is weird.
inactive.Push(obj);
}
}
/// <summary>
/// Added to freshly instantiated objects, so we can link back
/// to the correct pool on despawn.
/// </summary>
class PoolMember : MonoBehaviour {
public Pool myPool;
}
// All of our pools
static Dictionary< GameObject, Pool > pools;
/// <summary>
/// Init our dictionary.
/// </summary>
static void Init (GameObject prefab=null, int qty = DEFAULT_POOL_SIZE) {
if(pools == null) {
pools = new Dictionary<GameObject, Pool>();
}
if(prefab!=null && pools.ContainsKey(prefab) == false) {
pools[prefab] = new Pool(prefab, qty);
}
}
/// <summary>
/// If you want to preload a few copies of an object at the start
/// of a scene, you can use this. Really not needed unless you're
/// going to go from zero instances to 10+ very quickly.
/// Could technically be optimized more, but in practice the
/// Spawn/Despawn sequence is going to be pretty darn quick and
/// this avoids code duplication.
/// </summary>
static public void Preload(GameObject prefab, int qty = 1) {
Init(prefab, qty);
// Make an array to grab the objects we're about to pre-spawn.
GameObject[] obs = new GameObject[qty];
for (int i = 0; i < qty; i++) {
obs[i] = Spawn (prefab, Vector3.zero, Quaternion.identity);
}
// Now despawn them all.
for (int i = 0; i < qty; i++) {
Despawn( obs[i] );
}
}
/// <summary>
/// Spawns a copy of the specified prefab (instantiating one if required).
/// NOTE: Remember that Awake() or Start() will only run on the very first
/// spawn and that member variables won't get reset. OnEnable will run
/// after spawning -- but remember that toggling IsActive will also
/// call that function.
/// </summary>
static public GameObject Spawn(GameObject prefab, Vector3 pos, Quaternion rot) {
Init(prefab);
return pools[prefab].Spawn(pos, rot);
}
/// <summary>
/// Despawn the specified gameobject back into its pool.
/// </summary>
static public void Despawn(GameObject obj) {
PoolMember pm = obj.GetComponent<PoolMember>();
if(pm == null) {
Debug.Log ("Object '"+obj.name+"' wasn't spawned from a pool. Destroying it instead.");
GameObject.Destroy(obj);
}
else {
pm.myPool.Despawn(obj);
}
}
}
Without another particular
Thanks in advance
Answer by Runalotski · Jan 10, 2016 at 09:32 PM
When you instantiate an object with
Instantiate(prefab,pos,rot);
You can store this new object into a veriable like this
Transform clone = Instaniate(prefab,pos,rot) as Transform;
You can now access and componets of the clone object to set any values you wish usimg the GetComponent()
i'll do that, but then the whole point of follow the tutorial would be lost, better bet is to try to find the problem and then re-create it, i download the original code (is in the description of the youtube video, part 9) and that works just perfectly, the $$anonymous$$e create a GameObject with no atributes and report than "an object has already been created there"
I can if you want put the link of the code with the original code, http://quill18.com/porcupine/project_files/Project%20Porcupine%20-%20Ep%20010.zip
I downloaded the project but it seems to be working fine foe me, with the exception of not being able to delete the the wall section with the bulldoze tool.
I only get an error "Trying to assign an installed object to a tile that already has one!" if I try to place a wall on top of an existing one, but this is a user made error log being used for debug to show that the system will NOT duplicate a new wall on top which seems to be intended behaviour.
I cannot see any unnamed objects being created when I place a wall.
Did you send me the version before you changed anything?
Your answer
Follow this Question
Related Questions
Distribute terrain in zones 3 Answers
Multiple Cars not working 1 Answer
How to create Prefab with property 2 Answers
How to measure width and hight in a object in unity using c# codes ? 1 Answer