How to Set arrays in other scripts - c#

Hi I am making a Multiplayer shooter in unity and im using arrays and need help
My situation is I want to make an unboxing system that chooses a random array and then set it to the list of the classes array list please help.
Please tell me if this would choose a random array: Classes[Random];
and also I need to know how to set an array from a different script
using UnityEngine;
using System.Collections;
public class SpawnNew : MonoBehaviour
{
public GameObject[] Classes;
public GameObject player;
public Transform[] spawnPoints;
public Camera spawnCam;
public AudioListener spawnListener;
public bool spawned = false;
void ClassList(){
Classes = new GameObject[10];
}
void OnGUI()
{
if (Network.isServer || Network.isClient)
{
if (!spawned)
{
if (GUI.Button(new Rect(Screen.width / 10 - 50, Screen.height / 10 - 25, 100, 50), "Spawn"))
{
SpawnPlayer();
}
}
}
}
void SpawnPlayer()
{
spawned = true;
int random = Random.Range(0, spawnPoints.Length);
Network.Instantiate(player, spawnPoints[random].position, spawnPoints[random].rotation, 0);
spawned = true;
spawnCam.enabled = false;
spawnListener.enabled = false;
spawned = true;
}
public void Die()
{
Screen.lockCursor = false;
spawned = false;
spawnCam.enabled = true;
spawnListener.enabled = true;
}
}

First of all your array is not initialized. You have to make sure the array is populated before calling SpawnPlayer method, otherwise this will through a NullReferenceException.
Yes, this int random = Random.Range(0, yourArray.Length); would give you a random index within your array.
You can access your array / method from within another script like this
GameObject yourObject = GameObject.Find("GameObjectNameThatHasYourScriptAttachedToIt");
if(yourObject !=null){
yourObject.GetComponent<SpawnNew>().Classes = someOtherArray;
// or if you want to access the method
// yourObject.GetComponent<SpawnNew>().SpawnPlayer();
}

Related

Unity. Script does not working with clones

I have created a script who will spawn objects and give tag and color for one element of prefab. But script not working with clones. This 2 scripts, GameManager( he must spawn objects) and
RandomTagAndColor( he give to element of prefab tag and name). And in scene of game, where objects is spawning, script give tag and colour only to first prefab. In game those prefabs 10. Well, I'm sorry if question is stupid, this first thing, what i doing without books,guides.
GameManager script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GameManager : MonoBehaviour
{
// Start is called before the first frame update
public GameObject firstBarrier;
public GameObject secondBarrier;
public int numOfBarriers = 0;
System.Random rnd = new System.Random();
System.Random rndY = new System.Random();
Vector3 vector = new Vector3(5, 1/3 , 1);
void Start()
{
for (numOfBarriers = 0; numOfBarriers < 10; numOfBarriers++)
{
int ewq = rnd.Next(1, 20);
int rY = rndY.Next(1, 4);
if(ewq <= 10)
{
Instantiate(firstBarrier, vector, Quaternion.identity);
}
else
{
Instantiate(secondBarrier, vector, Quaternion.identity);
}
vector.x -= 7;
vector.y = rY;
}
}
void Update()
{
}}
RandomColorAndTag script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class RandomColorAndTag : MonoBehaviour
{
GameObject Bar;
System.Random randomElement = new System.Random();
int el = 0 ;
void Start()
{
el = randomElement.Next(2, 6);
GameObject.Find($"Cube ({el})").GetComponent<Renderer>().material.color = Color.green;
if (GameObject.Find($"Cube ({el})").GetComponent<Renderer>().material.color == Color.green)
{
GameObject.Find($"Cube ({el})").transform.tag = "Green";
}
}
void Update()
{
}
}
As mentioned there are lot of unclear issues in your codes.
I will assume the RandomColorAndTag is attached to the objects you spawn. In that case don't use Find but rather simply assign the random color and tag to yourself
what is a random value between 1 and 19 good for, of all you ever do with it is check whether it is bigger or smaller than 10? => Simply use only a random 0 or 1 and check whether it is 0 ;)
I'm unsure exactly what items should be green now .. I assume among the 10 spawned items you want to pick one and make it special..
finally I wouldn't even let the objects assign their own tag and color but let the GameManager trigger it
So I would do something like
public class GameManager : MonoBehaviour
{
public TagAndColorController fortBarrier;
public TagAndColorController secondBarrier;
public int numOfBarriers = 10;
public Vector3 vector = new Vector3(5, 1f/3f , 1);
public Color specialColor = Color.Green;
public string specialTag = "Green";
private void Start()
{
var specialIndex = Random.Range(0, numberOfBarriers);
for (var i = 0; i < numOfBarriers; i++)
{
// upper bound is exclusive -> this returns 0 or 1
var rndBarrier = Random.Range(0, 2);
// not sure if intended but again: upper bound is exclusive -> this return 1, 2, or 3
var rY = Random.Range(1, 4);
var tagAndColor = Instantiate(rndBarrier == 0 ? firstBarrier : secondBarrier, vector, Quaternion.identity);
if(i == numberOfBarriers)
{
tagAndColor.SetColorAndTag(specialColor, specialTag);
}
vector.x -= 7;
vector.y = rY;
}
}
}
And the other script has no logic whatsoever but rather only is a quick access to the objects renderer and bundles the behavior
public class TagAndColorController : MonoBehaviour
{
[SerializeField] private Renderer _renderer;
public void SetColorAndTag(Color newColor, string newTag)
{
gameObject.tag = newTag;
if(!_renderer) _renderer = GetComponent<Renderer>();
_renderer.material.color = newColor;
}
}

My prefabs in unity aren't running script when spawned after one another (uses XR controller)

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)

How do i set the max. amount of existing prefabs and also despawn Prefabs floors in Unity after the player passes them?

So here is the code, right now i only spawn each frame x Prefabs (Its a simple Game im new to unity so the player is a ball and dodges stuff etc. So i have an amount of prefabs (Floors) that is spawning in front of the palyer)
public static int numSpawned = 0;
//Creates an Array to store PreFabs into it
public static GameObject[] thePath;
//Sets the x value of the spawning postion to 100
public int SpawningDistance = 100;
public int numToSpawn = 6;
//Calls the PreFabs Folder
private void Start()
{
thePath = Resources.LoadAll<GameObject>("PreFabs");
}
//Sets the Spawn Position and ++ the numSpawned
void SpawnRandomObject()
{
int withItem = Random.Range(0,6);
GameObject myObj = Instantiate(thePath[withItem]) as GameObject;
numSpawned++;
myObj.transform.position = transform.position + new Vector3(0, 0, 0);
}
//Til now it Spawns every Frame so thats what you have to fix
void Update()
{ //compares the Values
if (numToSpawn > numSpawned)
{
//where your object spawns from
transform.position = new Vector3(SpawningDistance, 0, 0);
SpawnRandomObject();
SpawningDistance = SpawningDistance + 100;
}
}
Til now its the problem that i dont know how to controlle the spawning amount and speed so i need help for that. All Prefabs are beeing stored in an array and then spawned randomly out of it.
Instead of using method SpawnRandomObject() every frame, you could create coroutine and yield WaitForSeconds(value).
[SerializeField] private float delaySpawnInSeconds = 0.5f;
...
private void Start()
{
thePath = Resources.LoadAll<GameObject>("PreFabs");
StartCoroutine(SpawnFloors());
}
Our coroutine:
private IEnumerator SpawnFloors()
{
while (numToSpawn > numSpawned)
{
//SpawnRandomObject(); //if U want to spawn object then wait
yield return new WaitForSeconds(delaySpawnInSeconds);
SpawnRandomObject(); //if U want to wait then spawn object
}
}
Doc: https://docs.unity3d.com/Manual/Coroutines.html
To get spawning amount, you could use Captain Skyhawk's idea to:
Keep an array of spawned objects and check the count.
Arrays:
Doc: https://docs.unity3d.com/2018.4/Documentation/ScriptReference/Array-length.html
You can also use lists, for example:
private List<GameObject> exampleList = new List<GameObject>();
private int sizeOfExampleList;
...\\Add items to the list in the code.\\...
private void exampleMethod ()
{
sizeOfExampleList = exampleList.Count;
}
...
I hope I helped You! :-)

Optimization issues with 2D sandbox terrain generation

My game:
Each block has a class that doesn't run anything on update, and there is a 200 x 10 span of blocks. I'm implementing random terrain generation later, and this is what I want to be done.
BLOCK CODE: (in every single block, should I optimize? or do it differently?)
using UnityEngine;
using System.Collections;
public class scr_blockMechanics : MonoBehaviour {
//#EDITABLE VARS
public string block_blockType;
private SpriteRenderer spriteRenderer;
public bool isMineable { get; set; }
public bool isRandomlyGenerated { get; set; }
public bool isWall { get; set; }
//#STATIC VARS
GameObject obj_blockItem;
//#START
void Start () {
obj_blockItem = GameObject.Find("main_blockItem");
spriteRenderer = GetComponent<SpriteRenderer>();
if(isRandomlyGenerated == false){
isMineable = false;
}
//#CREATING WALLS
/*if(isRandomlyGenerated == true && isWall == false){
//#TODO Create walls!
GameObject obj_blockWall = (GameObject)Instantiate(gameObject, transform.localPosition, Quaternion.identity);
obj_blockWall.name = obj_blockWall.name + " WALL";
obj_blockWall.transform.localPosition = new Vector3(
obj_blockWall.transform.localPosition.x,
obj_blockWall.transform.localPosition.y,
5);
Collider2D obj_blockWall_collider = obj_blockWall.GetComponent<Collider2D>();
obj_blockWall_collider.enabled = false;
Color obj_blockWall_color = Color.grey;//new Vector4(64, 64, 64, 1);
SpriteRenderer spriteRenderer_wall = obj_blockWall.GetComponent<SpriteRenderer>();
spriteRenderer_wall.color = obj_blockWall_color;
scr_blockMechanics blockMechanics_wall = obj_blockWall.GetComponent<scr_blockMechanics>();
blockMechanics_wall.isRandomlyGenerated = true;
blockMechanics_wall.isMineable = false; //#TODO: not yet mineable, because it's a wall.
blockMechanics_wall.isWall = true;
obj_blockWall.name = blockMechanics_wall.block_blockType+" WALL";
}*/
}
//#CREATE ITEM
void createItem(int uid){
GameObject obj_blockItemNew = (GameObject)Instantiate(obj_blockItem, transform.localPosition, Quaternion.identity);
obj_blockItemNew.rigidbody2D.isKinematic = false;
obj_blockItemNew.name = gameObject.name + " ITEM";
}
//#DESTROY BLOCK
void destroyBlock(){
//print ("'"+transform.name+"' has been destroyed!");
//spriteRenderer.color = Color.red;
createItem(0);
Destroy(transform.gameObject);
}
//#UPDATE
void Update () {
if(renderer.IsVisibleFrom(Camera.main) == true){
renderer.enabled = true;//gameObject.SetActive(true);
}
if(renderer.IsVisibleFrom(Camera.main) == false){
renderer.enabled = false;
}
}
}
'RANDOM' TERRAIN GENERATION
using UnityEngine;
using System.Collections;
public class scr_randomGen : MonoBehaviour {
private SpriteRenderer spriteRenderer;
private string[] block_blockTypes = new string[]{
"DIRT", //#UID 0
"STONE", //#UID 1
"STONE_BRICK", //#UID 2
};
void GENERATE(){
//#DEFAULTS
GameObject obj_block = GameObject.Find("main_block");
int pos_startingPosX = -100;
int pos_endingPosX = 100;
int pos_startingPosY = 0;
int pos_endingPosY = 10;
float X = 0;
float Y = 0;
//#TERRAIN GENERATION
for(X=pos_startingPosX;X<pos_endingPosX;X=X+1){
GameObject obj_blockNew = (GameObject)Instantiate(obj_block, new Vector3(0 + (1*X),0,0), Quaternion.identity);
scr_blockMechanics blockMechanics = obj_blockNew.GetComponent<scr_blockMechanics>();
blockMechanics.isMineable = true;
blockMechanics.isRandomlyGenerated = true;
blockMechanics.block_blockType = block_blockTypes[2];
obj_blockNew.name = blockMechanics.block_blockType+" "+X+", "+Y;
for(Y=pos_startingPosY;Y<pos_endingPosY;Y=Y+1){
obj_blockNew = (GameObject)Instantiate(obj_block, new Vector3(X,1 + (1*Y),0), Quaternion.identity);
blockMechanics = obj_blockNew.GetComponent<scr_blockMechanics>();
blockMechanics.isMineable = true;
blockMechanics.isRandomlyGenerated = true;
blockMechanics.block_blockType = block_blockTypes[2];
obj_blockNew.name = blockMechanics.block_blockType+" "+X+", "+Y;
}
}
}
void Start () {
GENERATE();
}
void Update () {
}
}
I have it so that if the camera isn't looking at blocks it disables their sprite renderer so it's not rendering as much.
Should I just disable them as a whole? I get 6fps upon running the game.
When I only have, say, 10 - 20 blocks instead of 2000 I get 130 FPS (which is still low in my opinion)
What's the best way to optimize this? make it so I get atleast 70 fps? I wanted to use Java but I don't feel comfortable with the editor and I already put 2 hours of work into this.
I have looked at people's projects in Java and it's a lot smoother and they don't have to worry about the lag. And I have looked at peoples posts saying that it is possible to create a Terarria-like game in Unity but it's always going to be laggy.
Anybody got a good idea on how to fix the lag issues?

can't get variable from an empty game object with script

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

Categories

Resources