How to reference a class from child to parent? - c#

It may sound stupid but how can i reference a class from one script in child in another script in parent? I cant find anything on google. Note: There are couple errors in my script, that's not the point of the post.
//Public
//Private
private Rigidbody myRigidbody;
private Renderer myRenderer;
private Material tileDefaultMaterial;
private Material tileSelectedMaterial;
private Material tileSameGroupMaterial;
void Start () {
myRigidbody = GetComponent<Rigidbody> ();
myRenderer = GetComponent<Renderer> ();
tileDefaultMaterial = Resources.Load ("TileDefault", typeof(Material)) as Material;
tileSelectedMaterial = Resources.Load ("TileSelected", typeof(Material)) as Material;
tileSameGroupMaterial = Resources.Load ("TileSameGroup", typeof(Material)) as Material;
}
void Update () {
}
public class TileClass {
public int tileGroup = 0; //Indicates the Tile Group Number.
}
//Public
public GameObject[] allTiles; //Aray of all Tile GameObject.
public bool tileIsSelected = false; //If a Tile is Selected.
public int selectedTileGroup = 0; //Indicates the Selected Tile Group Number.
public int tileGroup = 0; //Indicates the Tile Group Number.
//Private
void Start () {
allTiles = new GameObject[transform.childCount];
for(int i = 0; i < transform.childCount; i++){
allTiles [i] = transform.GetChild (i).gameObject;
}
}
void Update () {
}
void OnMouseDown (){
RaycastHit hitInfo = new RaycastHit ();
bool hit = Physics.Raycast (Camera.main.ScreenPointToRay (Input.mousePosition), out hitInfo);
if (hitInfo.transform.gameObject.tag == "Tile" && tileIsSelected == false) {
Debug.Log ("A Tile is Selected!");
tileIsSelected = true;
selectedTileGroup = ;
for(int i = 0; i < allTiles.Length; i++){
if (this.tileGroup == selectedTileGroup) {
allTiles [i].GetComponent<Renderer> ().material = tileSameGroupMaterial;
}
}
myRenderer.material = tileSelectedMaterial;
} else if (hitInfo.transform.gameObject.tag == "Tile" && tileIsSelected == true) {
Debug.Log ("Second Tile is Clicked! (Should Swap them!)");
myRenderer.material = tileDefaultMaterial;
}
}

There is a famous saying :
var allTiles = transform.GetComponentsInChildren<Tile>();
And as I told you yesterday, Add OnMouseDown() in Tile.cs and write myRenderer.material = tileDefaultMaterial; there. No need to write this in TileManager.cs. And NO need to use Raycast when using OnMouseDown().

I can't read your image code, so I'll make up my own class names for the example. I'll call the parent class TileManager and the child class Tile.
Say in Tile you want access to the array of tiles in the TileManager. If allTiles is declared as public, you'd do in Tile somewhere.
TileManager tileManager = transform.parent.GetComponent<TileManager>();
var allTiles = tileManager.allTiles;
Now the Tile child has a reference to the array. Was this what you were wanting?

how about base.Method?
That should do it

Related

deactivate and activate an object in a list

I am a beginner. I want to create a game where there are six different positions and objects that spawn from them everytime player collides one of them and then they respawn. it s a loop until game finish.
I am having a problem with positions; if player stays at a position it just collides continually. I need to deactivate the position that player collides and reactivate when player collides other position. Position were made with empthy object and its collider. I dont know where to add what.
Thanks for your help
public class NewSpawnScript : MonoBehaviour{
public GameObject[] SpawnPoints;
public float spawnTime;
public GameObject[] threeD;
public List<GameObject> possibleSpawn = new List<GameObject>();
public List<GameObject> possibleThreeD = new List<GameObject>();
void Start()
{
//to avoid spawn more then one object at a position
for(int i=0;i<SpawnPoints.Length;i++)
{
possibleSpawn.Add(SpawnPoints[i]);
}
// to avoid to spawn same objects at different positions
for (int l=0;l<threeD.Length;l++)
{
possibleThreeD.Add(threeD[l]);
}
InvokeRepeating("SpawnItems", spawnTime, spawnTime);
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject.tag=="Obj")
{
//to avoid spawn more then one object at a position
for (int i = 0; i < SpawnPoints.Length; i++)
{
possibleSpawn.Add(SpawnPoints[i]);
}
// to avoid to spawn same objects at different positions
for (int l = 0; l<threeD.Length; l++)
{
possibleThreeD.Add(threeD[l]);
}
InvokeRepeating("SpawnItems", 2.5f, 2.5f);
}
}
void Update()
{
}
void SpawnItems()
{
if(possibleSpawn.Count>0 && possibleThreeD.Count>0)
{
for(int i=0;i<12;i++)
{
int spawnIndex = Random.Range(0, possibleSpawn.Count);
int spawnObject = Random.Range(0, possibleThreeD.Count);
GameObject newObj = Instantiate(possibleThreeD[spawnObject], possibleSpawn[spawnIndex].transform.position, possibleSpawn[spawnIndex].transform.rotation) as GameObject;
newObj.GetComponent<Destroyer>().mySpawnPoint = possibleSpawn[spawnIndex];
newObj.transform.parent = newObj.GetComponent<Destroyer>().mySpawnPoint.transform;
possibleSpawn.RemoveAt(spawnIndex);
possibleThreeD.RemoveAt(spawnObject);
i++;
}
}
}
}

How can i make clone object invisible Unity

1.i have an issue when i start dragging object its clonning itself, i need that in panel zone(my object respawning in there) not in dropzone im trying to find solution for this can i make clone invisible? if i can how ?here is the code :
enter code here
public class DragHandler : MonoBehaviour, IBeginDragHandler, IDragHandler, IEndDragHandler
{
public enum Slot { ileri, sağa, sola, fonksiyon };
public Slot typeofMove;
public Transform ParentreturnTo = null;
public Transform PlaceholderParent = null;
GameObject placeholder = null;
public GameObject ileriprefab;
public GameObject x;
public GameObject panel;
public void OnBeginDrag(PointerEventData eventData)
{
placeholder = new GameObject();
placeholder.transform.SetParent(this.transform.parent);
LayoutElement le = placeholder.AddComponent<LayoutElement>();
le.preferredWidth = this.GetComponent<LayoutElement>().preferredWidth;
le.preferredHeight = this.GetComponent<LayoutElement>().preferredHeight;
le.flexibleWidth = 0;
le.flexibleHeight = 0;
placeholder.transform.SetSiblingIndex(this.transform.GetSiblingIndex());
//sibling index kartı aldıgımız yeri döndürür.
Debug.Log("OnBeginDrag");
ParentreturnTo = this.transform.parent;
PlaceholderParent = ParentreturnTo;
this.transform.SetParent(this.transform.parent.parent);
if (this.transform.parent.position == GameObject.FindGameObjectWithTag("carddroparea").transform.position)
{
x = Instantiate(moveforwardprefab, moveforvardprefab.transform.position, Quaternion.identity);
x.transform.SetParent(PlaceholderParent.transform);
//im trying to saying here if the object "this" in drop zone dont instantiate it or make it invisible ??????? but its not working
}
GetComponent<CanvasGroup>().blocksRaycasts = false;
}
public void OnDrag(PointerEventData eventData)
{
Debug.Log("OnDrag");
this.transform.position = eventData.position;
if (placeholder.transform.parent != PlaceholderParent)
placeholder.transform.SetParent(PlaceholderParent);
int newSiblingIndex = PlaceholderParent.childCount;
for (int i = 0; i < PlaceholderParent.childCount; i++)
{
//**parentreturnto. getchild(i)**//
if (this.transform.position.x < PlaceholderParent.GetChild(i).position.x)
{
newSiblingIndex = i;
// placeholder.transform.SetSiblingIndex(i);
if (PlaceholderParent.transform.GetSiblingIndex() < newSiblingIndex)
newSiblingIndex--;
break;
}
}
placeholder.transform.SetSiblingIndex(newSiblingIndex);
}
public void OnEndDrag(PointerEventData eventData)
{
Debug.Log("OnEndDrag");
this.transform.SetParent(ParentreturnTo);
this.transform.SetSiblingIndex(placeholder.transform.GetSiblingIndex());
//Kartın alındıgı yere konulması için gerekli
GetComponent<CanvasGroup>().blocksRaycasts = true;
Destroy(placeholder);
if (this.transform.parent.position == GameObject.FindGameObjectWithTag("panel").transform.position)
{
Destroy(x);
Debug.Log("destroyed");
}
if (x.transform.parent.position == GameObject.FindGameObjectWithTag("carddroparea").transform.position)
{
Destroy(x);
Debug.Log("destroyed");
}
}
}
If you just want to make a GameObject invisible there are many ways to do it.
You can, for example:
yourGameObject.SetActive(false);
You can also deactivate your gameobject Renderer
yourGameObject.GetComponent<Renderer>().enabled = false;
how to adapt it to your code is up to you.

Trying to get GameObject to be created using variables from list

I'm trying to get a GameObject to be created by inputting the TileID.
For my Terrain Generation I'd eventually like to be able to do something like
Generate()
{
Tile(<TileID>);
}
Right now It will only generate a Stone tile for me since its the second of two items in the list. What can I do to allow myself to input the TileID to display the right tile.
TileObject Class:
public class TileObject : MonoBehaviour {
//Instance Variables
TileManager tileManager;
GameObject gameManager;
//Variables
public int TileID;
Sprite TileSprite;
string TileName;
SpriteRenderer spriteRenderer;
// Use this for initialization
void Start ()
{
gameManager = GameObject.Find("Manager");
tileManager = gameManager.GetComponent<TileManager>();
spriteRenderer = gameObject.GetComponent<SpriteRenderer>();
foreach (Tile tile in tileManager.Tiles)
{
TileID = tile.tileID;
TileSprite = tile.tileSprite;
TileName = tile.tileName;
}
}
public TileObject(int TileID)
{
gameObject.name = TileName;
spriteRenderer.sprite = TileSprite;
}
// Update is called once per frame
void Update ()
{
}
Tile Class:
public Tile(int newTileID, string newTileName, Sprite newTileSprite, float newBreakSpeed)
{
tileID = newTileID;
tileName = newTileName;
tileSprite = newTileSprite;
breakSpeed = newBreakSpeed;
}
Your tileManager should instantiate new tiles. For example:
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TileManager : MonoBehaviour {
public GameObject tilePrefab;
[Serializable]
public class Tile {
public int tileID;
public string tileName;
public Sprite tileSprite;
public float breakSpeed;
}
// List should be populated in inspector
public List<Tile> Tiles;
public GameObject Generate(int id) {
GameObject newObj = null;
try {
var data = Tiles.FirstOrDefault(tileData => id == tileData.tileID);
newObj = Instantiate(tilePrefab);
newObj.GetComponent<SpriteRenderer>().sprite = data.tileSprite;
newObj.name = data.tileName; // same name to multiple tiles?
} catch {
Debug.LogWarning("TileManager not initialised properly!");
}
return newObj;
}
}
The tilePrefab is a game object that is used as "prototype" for instantiation. In this example it is just a 2d sprite.
the tileManager tile data is populated in the inspector:
then you can generate tiles with:
var manager = GetComponent<TileManager>();
// generate 10 tiles with id [0..maxid]
int tilecount = 10;
int maxid = 1;
for (int id = 0; id <= maxid; ++id) {
for (int i = 0; i < tilecount; ++i) {
var obj = manager.Generate(id);
obj.transform.position = UnityEngine.Random.insideUnitCircle;
}
}
Based on what I see here it appears as though you are trying to use a single TileObject when you should be using one for each tile you want to render.
Where are you calling the constructor for TileObject? If it is from within the TileManager class, including that would make answering this question a lot easier.
All I can say without a clear view of the TileManager class is that when the Start() method is called, while proceeding through your foreach you write over each previously set value for
TileID = tile.tileID;
TileSprite = tile.tileSprite;
TileName = tile.tileName;
So as it reads though the list of tiles in TileManager, the previously read tile information is overwritten. For Example...
Iteration 1
TileID = 0;
TileSprite = sprite1;
TileName = firstTile;
Iteration 2
TileID = 1;
TileSprite = sprite2;
TileName = secondTile;
Iteration 3
TileID = 2;
TileSprite = sprite3;
TileName = thirdTile;
After it reaches the end of the list (of size n) you will end up with
Iteration N
TileID = **N-1**;
TileSprite = sprite**N**;
TileName = **Nth**Tile;
Essentially the TileObject class will contain the values from the last tile in tileManager.Tiles. Then when you call TileObject() it is creating a tile using the values from the last tile in the list.
I can help lead you more in the correct direction once I have a copy of the TileManager class. Hopefully this helps, if you have any questions don't hesitate to ask.

How to manage variables in child script from another script in parent? [duplicate]

This question already has answers here:
How to reference a class from child to parent?
(3 answers)
Closed 6 years ago.
I am trying to manage some variables in TileScript like TileGroupID, TileIsSelected from the TilesManager script in parent but i cant find a way to do it. For example i want to search all the Tiles if one of them have TileIsSelected True and then do something in all Tiles that have TileGroupID 1. I created tilesArray to keep track all the game objects but i don't know how i can use that to do what i said earlier.
TileScript:
//Public
public int tileGroupID = 0; //Indicates the Tile Group ID.
public bool tileIsSelected = false; //If this Tile is Selected.
public GameObject[] tilesArray; //Reference to Tiles Array.
//Private
private Rigidbody myRigidbody;
private Renderer myRenderer;
private Material tileDefaultMaterial;
private Material tileSelectedMaterial;
private Material tileSameGroupMaterial;
void Start () {
tilesArray = GetComponentInParent<TilesManager> ().tilesArray;
myRigidbody = GetComponent<Rigidbody> ();
myRenderer = GetComponent<Renderer> ();
tileDefaultMaterial = Resources.Load ("TileDefault", typeof(Material)) as Material;
tileSelectedMaterial = Resources.Load ("TileSelected", typeof(Material)) as Material;
tileSameGroupMaterial = Resources.Load ("TileSameGroup", typeof(Material)) as Material;
}
TilesManager:
//Public
public GameObject[] tilesArray; //Aray of all Tiles GameObject.
//Private
void Start () {
tilesArray = new GameObject[transform.childCount];
for(int i = 0; i < transform.childCount; i++){
tilesArray [i] = transform.GetChild (i).gameObject;
}
}
void OnMouseDown (){
//Do stuff with each tile.
}
The OnMouseDown function should be moved from the TilesManager script to the TileScript script. It will be called when each Tile is clicked on. When this happens, you can call a function on the TilesManager function and pass it the current GameObject that was clicked on.
In your TileScript script:
void OnMouseDown()
{
//Let Tiles Manager know that there was a press on (this) Tile
tileManagerInstance.OnObjectSelection(this.gameObject);
}
In your TilesManager script:
public void OnObjectSelection(GameObject selectedObj)
{
//Change Material of the Selected GameObject
selectedObj.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
when i click on a tile TileIsSelected change to true, change his
material and change all the other tile material that have same
TileGroupID as the one i clicked.
All you need now is a basic for loop. Loop through the tilesArray array and check which one has the-same tileGroupID as the GameObject that was clicked.
void findTheSameTileGroupIDAndChangeColor(GameObject selectedObj)
{
//Get the TileScript attached to the selectedObj
TileScript selectedTileScript = selectedObj.GetComponent<TileScript>();
//Loop through all GameObject in the array
for (int i = 0; i < tilesArray.Length; i++)
{
/*
Make sure this is NOT selectedObj since we've arleady
changed its Material in OnObjectSelection function
*/
if (selectedObj != tilesArray[i])
{
//Get TileScript attached to the current Tile loop
TileScript tileLoop = tilesArray[i].GetComponent<TileScript>();
//Check if selectedObj and the current loop tileGroupID matches
if (selectedTileScript.tileGroupID == tileLoop.tileGroupID)
{
//It matches! Now, change it's color
tileLoop.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
}
}
}
Finally the Whole thing I said put together:
TileScript:
public class TileScript : MonoBehaviour
{
public int tileGroupID = 0; //Indicates the Tile Group ID.
public bool tileIsSelected = false; //If this Tile is Selected.
public GameObject[] tilesArray; //Reference to Tiles Array.
//Private
private Rigidbody myRigidbody;
private Renderer myRenderer;
private Material tileDefaultMaterial;
private Material tileSelectedMaterial;
private Material tileSameGroupMaterial;
private TilesManager tileManager;
void Start()
{
tilesArray = GetComponentInParent<TilesManager>().tilesArray;
myRigidbody = GetComponent<Rigidbody>();
myRenderer = GetComponent<Renderer>();
tileDefaultMaterial = Resources.Load("TileDefault", typeof(Material)) as Material;
tileSelectedMaterial = Resources.Load("TileSelected", typeof(Material)) as Material;
tileSameGroupMaterial = Resources.Load("TileSameGroup", typeof(Material)) as Material;
//Get Tiles Manager
GameObject tileManagerObj = GameObject.Find("Tiles");
tileManager = tileManagerObj.GetComponent<TilesManager>();
}
void OnMouseDown()
{
//Let Tiles Manager know that there was a press on (this) Tile
tileManager.OnObjectSelection(this.gameObject);
}
}
TilesManager:
public class TilesManager : MonoBehaviour
{
public GameObject[] tilesArray; //Aray of all Tiles GameObject.
public Material tileSelectedMaterial;
void Start()
{
tilesArray = new GameObject[transform.childCount];
for (int i = 0; i < transform.childCount; i++)
{
tilesArray[i] = transform.GetChild(i).gameObject;
}
}
//Will be called from the TileScript(Receives any tile that is selected)
public void OnObjectSelection(GameObject selectedObj)
{
//Change Material of the Selected GameObject
selectedObj.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
//Change Mateial of other GameObjects that matches the tileGroupID of the selectedObj
findTheSameTileGroupIDAndChangeColor(selectedObj);
}
void findTheSameTileGroupIDAndChangeColor(GameObject selectedObj)
{
//Get the TileScript attached to the selectedObj
TileScript selectedTileScript = selectedObj.GetComponent<TileScript>();
//Loop through all GameObject in the array
for (int i = 0; i < tilesArray.Length; i++)
{
/*
Make sure this is NOT selectedObj since we've arleady
changed its Material in OnObjectSelection function
*/
if (selectedObj != tilesArray[i])
{
//Get TileScript attached to the current Tile loop
TileScript tileLoop = tilesArray[i].GetComponent<TileScript>();
//Check if selectedObj and the current loop tileGroupID matches
if (selectedTileScript.tileGroupID == tileLoop.tileGroupID)
{
//It matches! Now, change it's color
tileLoop.GetComponent<MeshRenderer>().material = tileSelectedMaterial;
}
}
}
}
}

UNET Change Texture of child object for clients

I have tried multiple techniques, but still no result. The host is able to change the color, but not for the client players. The code looks like this.
public List<GameObject> bases = new List<GameObject>();
[SyncVar]
public Texture redTexture;
[SyncVar]
public Texture blueTexture;
[SyncVar]
GameObject objID;
NetworkIdentity objNetID;
public void CheckTexture()
{
if (isLocalPlayer)
{
for (int i = 0; i < bases.Count; ++i)
{
var tempScript = bases[i].GetComponent<BaseScoreScript>();
if (tempScript.owner == "blue")
{
objID = bases[i];
CmdCheckText(objID, blueTexture);
}
}
}
}
[ClientRpc]
void RpcChangeTexture(GameObject obj, Texture text)
{
obj.GetComponentInChildren<MeshRenderer>().material.mainTexture = text;
}
[Command]
void CmdCheckText(GameObject obj, Texture texture)
{
objNetID = obj.GetComponent<NetworkIdentity>();
objNetID.AssignClientAuthority(connectionToClient);
RpcChangeTexture(obj, texture);
objNetID.RemoveClientAuthority(connectionToClient);
}
Thanks for any who look at this. I solved the issue. Probably not the most efficient, I can work on that later. But I added a [Command] to the non player object (which does have a NetworkIdentidy and set to local player), in this command I reference a list of players in the scene and set a public variable in the playersscript (which is a SyncVar <- that what did it). And in the playerscript I reference that non Player object and set its texture to the one I wanted. Not worried if it isLocalPlayer or not, because I want all players to see the change.
[Command]
void CmdSyncOwner(string own)
{
//List<GameObject> players = new List<GameObject>();
foreach (GameObject obj in GameObject.FindObjectsOfType<GameObject>())
{
players.Remove(obj);
players.Add(obj);
}
for (int i = 0; i < players.Count; ++i)
{
if (players[i].tag.Contains("Ply"))
{
players[i].GetComponent<FPSPlayerFunction>().baseOwner = own;
}
}
}
that's the code in the non-player script and:
[SyncVar]
public string baseOwner;
void BaseStatus()
{
var blue = Color.blue;
var red = Color.red;
foreach(GameObject obj in bases)
{
if (baseOwner == "blue")
{
centBaseStatus.image.color = blue;
centBaseStatus.GetComponentInChildren<Text>().text = "Center Base : "+ baseOwner;
GameObject.Find("CenterBase").GetComponentInChildren<Renderer>().material.mainTexture = BlueBase;
}
}
}
for the playerscrip.
I know its not pretty. But yea, if you have any suggestions on better ways to do this, please let me know. And if this is helpful to someone... Awesome Sauce!

Categories