Instanciate prefab as child in Unity3D - unity3d

i want a gameObject to add instanciatetd objects prom a prefab as his chiled.
so i wrote this code:
public class TgtGenerator : MonoBehaviour {
public SpriteRenderer spriteTgt;
public Sprite[] targets;public SpriteRenderer spriteTgt;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
generateRandTgt ();
}
void generateRandTgt(){
SpriteRenderer tgt = GameObject.Instantiate (spriteTgt, getRandPosition (), Quaternion.identity)as SpriteRenderer;
tgt.sprite = randSprite ();
}
Sprite randSprite(){
var length = targets.Length-1;
Debug.Log (Random.Range(0,length));
return targets[Random.Range(0,length)];
}
Vector3 getRandPosition(){
float xScale = gameObject.transform.localScale.x / 2;
float yScale = gameObject.transform.localScale.y / 2;
float x = Random.Range(-xScale,xScale);
float y = Random.Range(-yScale,yScale);
float z = 0;
return new Vector3 (x, y, z);
}
the instantiated object is getting his size from the prefab like i wanted to.
but the problem is it instanciated at the root node of the hirarchy so they are not placed inside of the gameobject coordinate like i wanted to.
when i am adding this line of code just after the instaciate line :
tgt.transform.parent = gameObject.transform;
it generated as a child like i wanted to but it gets huge and upside down.
how should i manage this?

Try Using This To Force Child To Have It's Own Scale After Being a Child:
var localScale = child.transform.localScale; // store original localScale value
child.transform.parent = parent;
child.transform.localScale = localScale; // force set

Related

Unity 3D: Instantiate GameObject to specific position on the Parent

Newbie here. I want to Instantiate a GameObject to a specific position on the Parent. I want to place it at the top of the parent. Can I position it immediately when I instantiate it or do I need to use the transform.position? In either case I don't know how to do it. I also need to figure out how to rotate the child on the parent if you are feeling generous with your time. Also, each child/copy or new instantiated object will scale with each new iteration. I'm trying to build a reverse fractal tree (the branches get bigger over time).
Just a warning - you might cringe at other parts of the code that probably could be written better.
using UnityEngine;
using System.Collections;
public class ExampleClass : MonoBehaviour
{
public Transform Cube;
public GameObject masterTree;
public int instanceCounter = 1;
public int numCubes = 30;
public float scalar = 1.4145f;
public float initialScale = 10f;
public float angle = 30f;
private Transform copy;
void Start()
{
}
private void Update()
{
if (instanceCounter <= numCubes)
{
if (instanceCounter == 1)
{
copy = Instantiate(Cube, new Vector3(0, 0, 0), Quaternion.identity);
copy.transform.localScale = new Vector3(1f, initialScale, 1f);
copy.name = "Copy" + instanceCounter;
copy.transform.parent = masterTree.transform;
instanceCounter++;
}
var copyParent = GameObject.Find("Copy" + (instanceCounter - 1));
Vector3 copyParentSize = copyParent.GetComponent<Renderer>().bounds.size;
Debug.Log("copyParentSizeY = " + copyParentSize.y);
copy = Instantiate(Cube, new Vector3(0, 0, 0), Quaternion.identity);
copy.transform.localScale = new Vector3(1f, initialScale, 1f);
initialScale = initialScale * scalar;
copy.name = "Copy" + instanceCounter;
//copy.transform.rotation *= Quaternion.Euler(angle, angle, 0);
copy.transform.parent = copyParent.transform;
instanceCounter++;
}
}
}
If I understands your needs right...
There is a Instantiate method with Parent parameter, so you can create new GO as a child of your parent
public static Object Instantiate(Object original, Transform parent);
If you want to have some kind of pivot, you can create empty GameObject in your target parent, shift it to right position and instantiate your GO as a child of that empty GO.
Also you can wrap your Cube in another empty GameObject (ex: position 0,0,0), so you can shift Cube up (0,5,0), but origin of whole GameObject remains same (0,0,0).
I understand Vector3 better now. It looks like I can add together different GameObject positions together in the same Vector3:
newPosition = new Vector3(0, copyParentSize.y + copyParentPosition.y + spacer, 0);
Now I move objects around based on the location of other objects.
Thank you for your help!

MissingComponentException: There is no 'SpriteRenderer' attached to the “Koopa Troopa” game object, but a script is trying to access it

Error as below:
MissingComponentException: There is no 'SpriteRenderer' attached to the "Gumbaa" game object, but a script is trying to access it. You probably need to add a SpriteRenderer to the game object "Gumbaa". Or your script needs to check if the component is attached before using it. UnityEngine.Renderer.get_bounds () (at /Users/builduser/buildslave/unity/build/artifacts/generated/common/runtime/GraphicsBindings.gen.cs:1007) EnemyMovement.Start () (at Assets/Scripts/EnemyMovement.cs:21)
And my game also got automatically pause whenever I clicked play button.
When I tried to Add Component 'SpriteRenderer' to Gumbaa, I then received another error message as below: Can't add component 'SpriteRenderer' to Koopa Troopa because it conflicts with the existing 'MeshFilter' derived component!
Screenshot of inspector
using System.Collections;
using UnityEngine;
public class EnemyMovement : MonoBehaviour
{
public float speed = 2.7f;
public LayerMask EnemyMask;
Transform myTrans;
float myWidth, myHeight;
Rigidbody2D rb;
SpriteRenderer mySprite;
// Use this for initialization
void Start ()
{
myTrans = this.transform;
rb = this.gameObject.GetComponent<Rigidbody2D> ();
mySprite = this.gameObject.GetComponent<SpriteRenderer> ();
myWidth = mySprite.bounds.extents.x;
myHeight = mySprite.bounds.extents.y;
}
// Update is called once per frame
void FixedUpdate ()
{
Physics2D.IgnoreLayerCollision (8, 9);
Vector2 LineCastPos = (myTrans.position.toVector2() + myTrans.right.toVector2() * myWidth + Vector2.up * myHeight * 1.2f);
Debug.DrawLine (LineCastPos, LineCastPos + myTrans.right.toVector2 () * 1.2f);
bool isBlocked = Physics2D.Linecast (LineCastPos, LineCastPos + myTrans.right.toVector2 () * 1.2f, EnemyMask);
if (isBlocked)
{
Vector2 currRot = myTrans.eulerAngles;
currRot.y += 180;
myTrans.eulerAngles = currRot;
}
Vector2 myVel = rb.velocity;
myVel.x = myTrans.right.x * speed ;
rb.velocity = myVel;
}
}
The error is pretty clear:
On your Gumba object, you added the script EnemyMovement
In the script, you do
mySprite = this.gameObject.GetComponent<SpriteRenderer> ();
This means that the GameObject that has EnemyMovement must also have SpriteRenderer
In the UnityInspector, do AddComponent and choose SpriteRenderer
Knowing if you really need to use a sprite renderer here is up to you

Can not print out gameobject's position's value correctly

When trying to print out (debug) my objects value, it gives me the position's value of where it's original position is (the startposition in world space). So my object is placed in -3.51 in y in world space before starting the game, therefore it only prints out -3,51 on every update despite the fact that in the inspector you can see the y position (in transform) changing when the object moves.
This is the code that does it:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
// Icke procedurell
public class createLevels : MonoBehaviour {
public GameObject doodle;
public Transform doodleTransform;
public GameObject greenPlatform;
public float distMultiplier = 1f;
public float valueY;
public int ammountPlatforms = 10;
public float levelWidth = 3f;
public float minY = 0.2f;
public float maxY = 1.5f;
public Vector3 spawnPosition = new Vector3();
void Start()
{
for (int i = 0;i < ammountPlatforms; i++) // Instansierar en startsumma platformar.
{
spawnPosition.y += Random.Range(minY, maxY); // Ökning i y
spawnPosition.x = Random.Range(-levelWidth, levelWidth); // Ingen ökning i x..
Instantiate(greenPlatform, spawnPosition, Quaternion.identity);
}
}
void Update()
{
Debug.Log(doodle.GetComponent<Transform>().position.y);
/*
if (doodleTransform.position.y >= 10)
{
Debug.Log("I am over a certain distance.");
distMultiplier++;
Instantiate(greenPlatform, spawnPosition, Quaternion.identity);
}
*/
}
}
Also note that this is a script on another gameobject referencing my "wanted" gameobject's position.
To summarize the question, if you look in the update function, observe the "Debug.Log". It only prints out my startvalue, and i am trying to print out the objects position in y in realtime, being dynamic.

How to set texture to automatically match with a change in window size by using same texture

I made a small 2D game by using unity3D(5.0.2f1). I dragged in some textures to use as the background in a scene. It worked well in the Unity Editor, but not when I built and ran it in a different window size. It didn't look as what I had seen in Unity Editor.
What should I do to change the texture size automatically when window size changes? Here is a screenshot of how the image looks in the editor and the build, as well as my build settings:
Maybe these will help!
//file ExtensionsHandy.cs
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public static class ExtensionsHandy
{
public static float OrthoScreenWidth(this Camera c)
{
return
c.ViewportToWorldPoint(new Vector3(1,1,10)).x
- c.ViewportToWorldPoint(new Vector3(0,1,10)).x;
}
public static float OrthoScreenHeight(this Camera c)
{
return
c.ViewportToWorldPoint(new Vector3(0,1,10)).y
- c.ViewportToWorldPoint(new Vector3(0,0,10)).y;
}
}
try like this
void Start()
{
float w = Camera.main.OrthoScreenWidth();
Debug.Log("w is " +w.ToString("f4");
}
Note. If not familiar with "extensions": quick tutorial.
Here are more very handy extensions for you.
These will actually move an object to the screen points!
For example,
transform.ScreenRight();
transform.ScreenTop();
the object, is now at the top-right of the screen!!!
And consider this ......
void Update()
{
transform.ScreenRight();
}
In that example: even if the user changes the orientation of the device, even if the user resizes the screen (Mac or Windows), the object is ALWAYS on the right of the screen!!
public static Vector3 WP( this Camera c, float x, float y, float z)
{
return c.ViewportToWorldPoint(new Vector3(x,y,z));
}
public static void ScreenLeft(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 leftTop = Camera.main.WP(0f,1f,0f);
float leftX = leftTop.x;
rr.x = leftX;
moveme.transform.position = rr;
}
public static void ScreenRight(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 rightTop = Camera.main.WP(1f,1f,0f);
float rightX = rightTop.x;
rr.x = rightX;
moveme.transform.position = rr;
}
public static void ScreenBottom(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 bottomLeft = Camera.main.WP(0f,0f,0f);
float bottomY = bottomLeft.y;
rr.y = bottomY;
moveme.transform.position = rr;
}
public static void ScreenTop(this GameObject moveme)
{
Vector3 rr = moveme.transform.position;
Vector3 topLeft = Camera.main.WP(0f,1f,0f);
float topY = topLeft.y;
rr.y = topY;
moveme.transform.position = rr;
}
Hope it helps.....

Object not destroying after reaching a certain point Unity

Okay so i'm making an infinite runner and the technique I've used is to keep the player static and move and instantiate the platform objects.
For that I've created an Array List of objects that are the platforms.
And then I'm adding them in and spawning them.
I am also translating them along the z-axis and i want to destroy the objects that go below 0 in the z axis and then add another object in replacement.
The problem is that it doesn't translate the objects unless I add another script just to do that and it doesn't destroy or add even if I add another script for translation.
My code is as follows. If you have trouble understanding my problem, please ask I would try to explain again.
I have two scripts.
1) PlatformManager: This one is applied on the empty GameObject and contains the ArrayList.
public class PlatformManager : MonoBehaviour
{
[HideInInspector]
public List<GameObject> platforms = new List<GameObject>(); // List of Platfroms.
public GameObject[] prefab; // Allow user to add as many prefabs through the inspactor.
public static float noOfPlatforms; // a variable to hold how many platoforms.
[HideInInspector]
public static float objectPosition; // Z position of the game object.
[HideInInspector]
public static float objectScale;
// Use this for initialization
void Start ()
{
noOfPlatforms = 6.0f;
objectPosition = 0.0f;
objectScale = 0.0f;
platforms.Add((GameObject)Instantiate(prefab[Random.Range(0,prefab.Length)], new Vector3(0,0,0) ,Quaternion.identity));
//platforms.Add((GameObject)Instantiate(prefab[Random.Range(0, prefab.Length)], new Vector3(0, 0, 40.40114f), Quaternion.identity));
for(int i = 0; i < noOfPlatforms; i++){
objectScale = platforms[platforms.Count-1].transform.localScale.z;
objectPosition = platforms[platforms.Count-1].transform.localPosition.z;
platforms.Add((GameObject)Instantiate(prefab[Random.Range(0,prefab.Length)], new Vector3(0,0,(objectPosition + objectScale)+277f) ,Quaternion.identity));
}
}
// Update is called once per frame
void Update ()
{
}
}
2) PlatformController: This one is supposed to instantiate and destroy and translate the objects.
public class PlatformController : MonoBehaviour {
//private bool canBeDestroy = true; // Flag to check whether the gameObject shoud be destroyed or not.
[HideInInspector]
public PlatformManager managePlateform; // Reference to plateformManager script.
[HideInInspector]
public float plateformSpeed = 10f;
[HideInInspector]
public GameObject allPlatforms;
[HideInInspector]
// Awake is called when the script instance is being loaded.
void Awake()
{
// Accessing the plateformManager script for the Plateform.
managePlateform = GameObject.FindGameObjectWithTag("Platform").GetComponent<PlatformManager>();
}
void Start()
{
}
// Update is called once per frame
void Update()
{
// Get the first platform object.
GameObject firstPlatform = managePlateform.platforms[0];
// Get the last platform object.
GameObject lastPlatform = managePlateform.platforms[managePlateform.platforms.Count - 1];
if (firstPlatform.transform.localPosition.z < 0f)
{
Destroy(firstPlatform.gameObject); // destroy the first plateform gameObject.
managePlateform.platforms.Remove(firstPlatform); // also remove the destroyed object from the list.
// When the game object is destroyed then instantiate one gameobject into list and add at the last point.
managePlateform.platforms.Add((GameObject)Instantiate(managePlateform.prefab[Random.Range(0, managePlateform.prefab.Length)], new Vector3(0, 0, (lastPlatform.transform.localPosition.z + lastPlatform.transform.localScale.z) + 277f), Quaternion.identity));
}
// Move the available platforms in the list along the z-axis
foreach (GameObject platform in managePlateform.platforms)
{
platform.transform.Translate(0, 0, -plateformSpeed * Time.deltaTime);
}
}
}