I have a issue with a script. I am trying to create a star field randomly in a sphere for my unity scene. But I am new to unity and c# so I am a bit confused.
The stars have a fixed place so they should not move and so are created in Start(); and then are drawn in Update();
The problem is I get this error:
MissingComponentException: There is no 'ParticleSystem' attached to the "StarField" game object, but a script is trying to access it.
You probably need to add a ParticleSystem to the game object "StarField". Or your script needs to check if the component is attached before using it.
Stars.Update () (at Assets/Stars.cs:31)
If i add a particle system component manually it causes a load of big flashing orange spots, which i don't want, so i want to add the component in the script some how.
This is my script attached to an empty game object:
using UnityEngine;
using System.Collections;
public class Stars : MonoBehaviour {
public int maxStars = 1000;
public int universeSize = 10;
private ParticleSystem.Particle[] points;
private void Create(){
points = new ParticleSystem.Particle[maxStars];
for (int i = 0; i < maxStars; i++) {
points[i].position = Random.insideUnitSphere * universeSize;
points[i].startSize = Random.Range (0.05f, 0.05f);
points[i].startColor = new Color (1, 1, 1, 1);
}
}
void Start() {
Create ();
}
// Update is called once per frame
void Update () {
if (points != null) {
GetComponent<ParticleSystem>().SetParticles (points, points.Length);
}
}
}
How can i set it to get a static star field, because adding a particle system component manually gives me these annoying orange particles and am wanting to do it purely via scripts.
It will be easier for you if you add the particle system manually and change the settings so that you don't see any funny shapes at runtime or in the Editor.
As a side note, you don't need to set the particles every frame in Update. Even if you did, calling GetComponent is expensive, so you should save the ParticleSystem as a field of the class in the Start() method.
Here is some modified code that worked for me:
using UnityEngine;
public class Starfield : MonoBehaviour
{
public int maxStars = 1000;
public int universeSize = 10;
private ParticleSystem.Particle[] points;
private ParticleSystem particleSystem;
private void Create()
{
points = new ParticleSystem.Particle[maxStars];
for (int i = 0; i < maxStars; i++)
{
points[i].position = Random.insideUnitSphere * universeSize;
points[i].startSize = Random.Range(0.05f, 0.05f);
points[i].startColor = new Color(1, 1, 1, 1);
}
particleSystem = gameObject.GetComponent<ParticleSystem>();
particleSystem.SetParticles(points, points.Length);
}
void Start()
{
Create();
}
void Update()
{
//You can access the particleSystem here if you wish
}
}
Here is a screenshot of the starfield with the settings used in the particle system. Note that I switched off looping and play on awake.
Related
For Unity (Lastest Version & C#)
How do I make an object fall from the sky at random places (random x but fixed y) in a 2D game
How do I delete them when they get off-screen and create a timing between objects falling
Whenever I run the program it randomly creates object but keeps naming them this: myObj, myObj(Clone), myObj(Clone)(Clone), myObj(Clone)(Clone)(Clone) every time a new object is instantiated. More importantly the instantiate part keeps running, spawning a bunch of objects and not deleting them.
Also, I just don't get how to delete the objects as soon as they get out of from the camera. Do I have to create a different script for it or smthn?
public class RandomObjectsFalling : MonoBehaviour
{
public GameObject obj;
public float timebeforedie = 1f;
void Start()
{
StartCoroutine(SpawnBlocks());
}
IEnumerator SpawnBlocks()
{
while(x <= 1)
{
float randomPosition = Random.Range(-10f, 10f);
GameObject clone = (GameObject)Instantiate(prefab, new Vector3(randomPosition, 8, 0), Quaternion.identity); //problem is this keeps getting called creating a whole bunch of objects but they don't get destroyed
yield return new WaitForSeconds(timebeforedie);
Destroy(clone);
}
}
}
Use this code to Spawn Your Obj
public GameObject prefab;
public bool startSpawning;
public float spawnDelay;
private float _currentSpawnDelay;
private void Start()
{
_currentSpawnDelay = spawnDelay;
}
private void Update()
{
if (startSpawning)
{
_currentSpawnDelay -= Time.deltaTime;
if (_currentSpawnDelay < 0)
{
_currentSpawnDelay = spawnDelay;
var randomPosition = Random.Range(-10f, 10f);
Instantiate(prefab, new Vector3(randomPosition, 8, 0), Quaternion.identity);
}
}
}
And This To Destroy Them But This Code Need To be Attach On Obj You That you want to Spawn
private void Update()
{
if (gameObject.transform.position.x < -20)
{
Destroy(gameObject);
}
}
Attach The Destroy Code to your Obj Prefab
Similar to most people on here I'm fairly new to the unity scene and I'm attempting to create a specific mechanism in my game: I want to create a bush where I can spawn fruit items from; the fruit on the bush take a specific amount of time to grow and can't be interacted with until they're fully grown. Once grown as soon as you grab the fruit, it spawns another in the position of the original to repeats the cycle.
However, how the code works is it spawns a first fruit, grows and interacts once grown but once I grab the first fruit, the plant stops growing and just shows the fully grown object(however after every time you grab that fruit it spawns another fruit as intended) ,this object doesn't react with gravity unlike the original which applies gravity after interaction.
The object is a prefab and contains the following script:
using System.Collections; using System.Collections.Generic;
using UnityEngine; using UnityEngine.XR.Interaction.Toolkit;
public class GrowthScript : MonoBehaviour { Collider ObjectCol; [SerializeField] private GameObject Item;
public int GrowTime = 6;
public float MinSize = 0.1f;
public float MaxSize = 1f;
public float Timer = 0f;
private XRGrabInteractable grabInteractable = null;
public bool IsMaxSize = false;
public bool CanRegrow = false;
// Start is called before the first frame update
void Start()
{
Debug.Log("Growing");
IsMaxSize = false;
ObjectCol = GetComponent<Collider>();
// if the plant isnt full size, it starts a routine to grow
if (IsMaxSize == false)
{
ObjectCol.enabled = !ObjectCol.enabled;
StartCoroutine(Grow());
}
}
private void Awake()
{
grabInteractable = GetComponent<XRGrabInteractable>();
grabInteractable.onSelectEntered.AddListener(Obtain);
}
private IEnumerator Grow()
{
Vector3 startScale = new Vector3(MinSize, MinSize, MinSize);
Vector3 maxScale = new Vector3(MaxSize, MaxSize, MaxSize);
do
{
transform.localScale = Vector3.Lerp(startScale, maxScale, Timer / GrowTime);
Timer += Time.deltaTime;
yield return null;
}
while (Timer < GrowTime);
IsMaxSize = true;
CanRegrow = true;
Debug.Log("Grown");
ObjectCol.enabled = !ObjectCol.enabled;
}
private void Obtain(XRBaseInteractor interactor)
{
if (CanRegrow == true)
{
GameObject instance = Instantiate(Item, transform.position, transform.rotation) as GameObject;
CanRegrow = false;
}
}
}
It would be Deeply appreciated if I could receive help on why the prefab doesn't run the code on respawn or a way to solve the problem.
Much appreciated (Good Luck)
I have some images in "assets/resource/mat" . I want to get this images and put them to array . But when I try to get this images I'm getting ArrayIndexOutOfBoundsException . I think that there is problem with Resource.LoadAll("mat") method . But I can't fix it . Please help me
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class test : MonoBehaviour
{
private string t;
public Sprite[] Icons;
void Start()
{
Object[] loadedIcons = Resources.LoadAll("mat");
Icons = new Sprite[loadedIcons.Length];
for (int x = 0; x < loadedIcons.Length; x++)
{
Icons[x] = (Sprite)loadedIcons[x];
Debug.Log("Loading....");
}
GameObject sp = new GameObject();
sp.GetComponent<SpriteRenderer>().sprite = Icons[0];
}
}
Loading all images from a particular folder, with LINQ, would look like this...
using UnityEngine;
using System.Linq;
public class Four : MonoBehaviour
{
public Sprite[] icons;
void Start()
{
icons= Resources.LoadAll("met", typeof(Sprite)).Cast<Sprite>().ToArray();
}
}
I'm not sure but I guess you instead of Sprite first have to load a Texture2D and then create a Sprite from it.
Also note you used GetComponent<SpriteRenderer>() on a newly created empty GameObject so obviously there will never be a SpriteRenderer component attached. Instead use AddComponent.
Sprite[] Icons;
Texture2D LoadedTextures;
private void Start()
{
LoadedTextures = (Texture2D[])Resources.LoadAll("mat", typeof(Texture2D));
Icons = new Sprite[loadedIcons.Length];
for (int x = 0; x < loadedIcons.Length; x++)
{
Icons[x] = Sprite.Create(
LoadedTextures[x],
new Rect(0.0f, 0.0f, LoadedTextures[x].width, LoadedTextures[x].height),
new Vector2(0.5f, 0.5f),
100.0f);
}
GameObject sp = new GameObject();
// Note that here you created a new empty GameObject
// so it obviously won't have any component of type SpriteRenderer
// so add it instead of GetComponent
sp.AddComponent<SpriteRenderer>().sprite = Icons[0];
}
I created a Quad. I assigned this script to the Quad that contains an array of Game Objects:
public class ShapeGrid : MonoBehaviour {
public GameObject[] shapes;
void Start(){
GameObject[,] shapeGrid = new GameObject[3,3];
StartCoroutine(UpdateGrid());
}
IEnumerator UpdateGrid(){
while (true) {
SetGrid ();
yield return new WaitForSeconds(2);
}
}
void SetGrid(){
int col = 3, row = 3;
for (int y = 0; y < row; y++) {
for (int x = 0; x < col; x++) {
int shapeId = (int)Random.Range (0, 4.9999f);
GameObject shape = Instantiate (shapes[shapeId]);
Vector3 pos = shapes [shapeId].transform.position;
pos.x = (float)x*3;
pos.y = (float)y*3;
shapes [shapeId].transform.position = pos;
}
}
}
}
I cloned those Game Objects so that they appear on a grid like this:
When the user clicks an object, it should disappear. What I did was place this script on every element in my array of Game Objects:
public class ShapeBehavior : MonoBehaviour {
void Update(){
if(Input.GetMouseButtonDown(0)){
Destroy(this.gameObject);
}
}
}
But what happens is when I click on an object to destroy it, every clone of that object will be destroyed. I want only the specific clone to be destroyed, not everything. How do I do that?
The problem is on your Input call, "Input.GetMouseButtonDown(0)" is true in every script when you click the button on mouse, no matter the position of mouse. Attach any kind of collider to gameObject and set it up and put the script with OnMouseDown() method, look here for more info : http://docs.unity3d.com/ScriptReference/MonoBehaviour.OnMouseDown.html
You can also use raycasting but that's more advanced way of solving this.
Also replace this.gameObject with just gameObject.
I'm trying to get variable from an empty gameObject's script, but I can't assign that gameObject on the inspector. These are the screen shots and codes from my game.
Well, I have this code to load when the game is starting. Land and Prince are objects that made from this code.
using UnityEngine;
using System.Collections;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
public class loadGame : MonoBehaviour
{
public static loadGame loadSave;
public GameObject objPrince;
public Pangeran charPrince;
public Transform prefPrince;
public Sprite[] spriteTanah;
public Dictionary<string, Tanah> myTanah = new Dictionary<string, Tanah>();
public Dictionary<string, GameObject>objTanah = new Dictionary<string, GameObject>();
public Tanah tempTanah;
public GameObject tempObjTanah;
public Transform prefTanah;
public float mapX;
public float mapY;
public int i = 0;
public int j = 0;
public int rows = 9;
public int column = 9;
void Awake(){
if(loadSave == null)
{
DontDestroyOnLoad(gameObject);
loadSave = this;
}
else if(loadSave != this)
Destroy(gameObject);
}
// Use this for initialization
void Start ()
{
Load ();
}
// Update is called once per frame
void Update ()
{
}
public void Load()
{
if(File.Exists(Application.persistentDataPath + "/playerInfo.dat"))
{
}
else
{
charPrince = new Pangeran ("Prince", "04Okt1993", 0, 0, 0, 0, 0, false, false);
objPrince = GameObject.Instantiate (prefPrince, new Vector3 (0, 0, 0), Quaternion.identity) as GameObject;
//objPrince.name = "Prince";
charPrince.locationY = 0f;
charPrince.locationX = 0f;
charPrince.hadapAtas = false;
charPrince.hadapKanan = true;
charPrince.stamina = 100f;
charPrince.exp = 0f;
charPrince.speed = 0f;
for(i = 0 ; i < rows ; i ++)
{
for(j = 0; j<column ; j++)
{
mapX = (i-j) * 0.8f;
mapY = (i+j) * 0.4f;
if(i>=1 && j>=1 && i<=5 && j<=5)
{
prefTanah.name = "land-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("land-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"land",spriteTanah[0],spriteTanah[1],spriteTanah[2]);
myTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("land-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
else
{
prefTanah.name = "snow-"+j.ToString("0#")+"-"+i.ToString("0#");
tempTanah = new Tanah("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),mapX,mapY,"snow");
myTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempTanah);
tempObjTanah = GameObject.Instantiate(prefTanah, new Vector3(mapX,mapY,0),Quaternion.identity)as GameObject;
objTanah.Add("snow-"+j.ToString("0#")+"-"+i.ToString("0#"),tempObjTanah);
}
}
}
}
}
}
I'm trying to access one of some variables from code above, but I can't assign it in the inspector.
but I can't do it.
please help me. Thank you.
The problem is that the loadLand variable is of type LoadGame which is a script. What you are trying to do is to add a GameObject to this variable. So change the public variable type to
public GameObject LoadLandObject;
private LoadGame loadLand;
and create a private LoadGame variable which is the reference to your script.
Add in the Start() method
loadLand = (LoadGame)LoadLandObject.GetComponent<LoadGame>();
With this you load the script LoadGame of the GameObject into the variable.
Do you ever set your plantingScript.loadLand to the instance of loadGame.loadSave? This must be done after Awake in your case to be sure the instance has been set.
Can I ask, what are you trying to do?
You should simply just assign you loadGame script in the inspector of plantingScript and not use statics at all. They will bite your ass sooner or later (and I'm guessing it already is).
Have a similar problem. Did n't find simple and clear solution. May be what i did help to you.
Create empty game object.
Attach loadGame.cs to it (if you whant to control when script starts - uncheck it,in this case don't foget to set loadLand.enabled to true in plantingScript when needed)
Drag this object to you loadLand field
Sample project