How to cast an Object to GameObject? - unity3d

I tried to get Terrains from Resources.FindObjectsOfTypeAll(typeof(Terrain)), and then activate it depend on the situations.
But it return Objects.
I had tried to cast it to GameObject by (GameObect)obj and obj as GameObject.
The first one raised an Invalid cast error, and the second returned a null.
The examples I was able to find online talked about Resources.Load mostly, which requires Instantiation.
But I don't think FindObjectsOfTypeAll requires instantiation, because the GameObjects are "already there"! Right!?
So could somebody please be so kind and teach me how can I cast Objects into GameObject so I could activated it!?
Much appreciated!

Terrain is a component, so its associated GameObject is accessed via the gameObject property.
Something like:
var go = ((Terrain)obj).gameObject;

Hi think you could use something like finding the terrain with the name of the object or the name of the tag, maybe this could help:
public class ExampleClass : MonoBehaviour
{
public GameObject terrain;
public GameObject[] terrains;
void Example()
{
// This returns the GameObject named Hand.
terrain = GameObject.Find("Hand");
// returns a list of the game objects with tags = 'terrain'
terrains = GameObject.FindGameObjectsWithTag("terrain");
//returns a single object with the tag terrain
terrain = GameObject.FindWithTag("terrain");
}
}

Related

Destroy specific child object of prefab object in c# / Unity

I search a lot but couldn't find any answer. My problem: I instantiate several Gameobjects of a Prefab, each consists of two child objects: an obstacle and a scorezone. I want to destroy the scorezone (only of that specific instance), when the player touches the obstacle. So in Runtime my hierarchy looks like this:
-ObjectPrefab(clone)
---Scorezone
---Obstacle
-ObjectPrefab(Clone)
---Scorezone
---Obstacle
...
So I need to find ONE child gameobject (not the Transform) to then destroy it. I tried several codes but none worked. Here is the code with the three alternatives I tried, but none of them worked.:
private void OnCollisionEnter2D(Collision2D collision) {
if (collision.gameObject.tag == "obstacle") {
Alternative 1:
Destroy(GameObject.FindWithTag("scorezone"));
Alternative 1 comes really close, but it destroys all scorezones of all instantiated objects.
Alternative 2:
Destroy(collision.gameObject.transform.parent.gameObject.FindWithTag("scorezone"));
Alternative 2 would sound logic to me but I get the error message "Transform does not contain a definition for "FindWithTag".
Alternative 3:
foreach (Transform child in collision.gameObject.transform)
{
if (child.tag == "scorezone")
{
Destroy(child.gameObject);
}
}
}
Alternative 3 does not give an error but actually does nothing at all when the player hits the obstacle.
I really appreciate some help, thanks in advance!
Store the reference!
If it is really a "prefab" so meaning you have it as an asset and instantiate it on runtime the best way (in my eyes and performance wise) would actually be to use a serialized field:
// Put this component on your obstacle
public class ObjectController : MonoBehaviour
{
// Drag the according object here via the Inspector in the prefab
// => when the prefab is Instantiated this field is already referenced
[SerializeField] private GameObject _scoreZone;
// Read-only access to the reference
public GameObject ScoreZone => _scoreZone;
}
This field reference is stored together with your prefab asset. So every instance of the prefab already has its own child references set up.
and then do
private void OnCollisionEnter2D(Collision2D collision)
{
// Rather use CompareTag which is slightly more efficient
// and adds some security (== silently fails if typo, CompareTag throws an exception instead)
if (collision.gameObject.CompareTag("obstacle"))
{
var controller = collision.gameObject.GetComponent<ObjectController>();
if(controller)
{
Destroy(controller.ScoreZone);
}
}
}
By Index
Alternatively but error prone you could simply use the index. You already know that there are only 2 childs, the first one being the Scorezone with index 0 so you can also do
if (collision.gameObject.CompareTag("obstacle"))
{
var scoreZone = collision.transform.parent.GetChild(0);
Destroy(scoreZone);
}
By Name
Using the name you could also use Find - I would not recommend this! It is error prone and slow
if (collision.gameObject.CompareTag("obstacle"))
{
var scoreZone = collision.transform.parent.Find("ScoreZone");
Destroy(scoreZone);
}

unity get child data

I am trying to create a procedural created dungeon in Unity.
I have it creating the dungeon, and have a script attached to each prefab that goes to make up the walls, floor etc. Each one of these is attached to a single parent, to make it easy to delete and rebuild the entire dungeon. The script contains details:
public class WallPrefab
{
public bool use;
private int roomId;
public WallTypes type; //enum = torch, switch, item etc
public WallDirections direction; //direction wall is facing
public GameObject myPrefab; //nested
}
The prefab also contains an empty game object used as a mount point for torches, switches etc.
myPrefab
prefab //prefab for the actual 3d object
wallmount //empty game object to store location and rotation details
....
My questions:
1. How do I get the wall type?
int childs = transform.childCount;
for (var i = childs - 1; i >= 0; i--)
{
c = transform.GetChild(i).gameObject;
Debug.Log("child:" + c.name);
//WallTypes g = c.GetComponentInChildren<WallPrefab>().type;
WallTypes g = c.transform.GetComponentInChildren<WallSettings>().type;
(Edited to insert working solution to this part of my problem!)
This code does not work, because Unity complains that:
ArgumentException: GetComponent requires that the requested component
'WallPrefab' derives from MonoBehaviour or Component or is an
interface.
How do I get the transform of the mount point?
I know how to get the location and rotation, once I get the mount point, but how do I actually get the mount point?
Question 1 seems pretty self explainatory.
Question 2 looks a bit more interessting.
If i understood you correctly, you have a script, that "creates" torches on specified mount points. Assuming those mount points are empty game objects and you dont want to add torches directly into the prefab (would be nice if we got a little bit more detail here on how exactly your dungeon+mount point is generated), i would add a script to the prefab, add a GameObject instance variable and use the inspector to drag the mount point onto the script. then i would use "gameobjectVariable.transform.position" to get the position.
something like:
public class prefabClassWithMountPoints{
GameObject mountpoint; //drag mount point from inspector
GameObject torchGameObject; //drag torch prefab here
public void createTorch(){
GameObject torchObject = Instantiate(torchGameObject, mountpoint.transform.position, Quaternion.identity);
//...
}
//rest of code
}
this is assuming the mount points are not randomly generated WITHIN the prefab.

Scriptable Object as a custom version of sprite

I have made a scriptable object which has a one property a public sprite. I want to have one version of sprite added everywhere I want.
With the possibility that if I ever want to change it I will just pin another sprite to scriptable object and in every place where it is pinned the sprite will change.
Is there any way to walk thought this problem or any other idea to make one object where I will store one Sprite and pin it to multiple objects.
Finally is this concept possible in Unity?
I have already thought about:
Deriving prom Sprite Renderer but the class is sealed, so i cannot make my own version of it this way
Creating my own custom version of Sprite Render cause if an any update come I would have to make yet again another version.
I think you can use prefabs to achieve the same thing as you need:
You can create prefab by dragging and object to your assets.(Your prefab will be just an object with transform and e.g. Sprite Renderer)
After creating prefab you can copy it as many times as you want.
Than when you decide to change the sprite just simply go to your prefab and edit sprite there. Now every instance of your prefab will have sprite changed.
It is possible with C# events. First, make your ScriptableObject call event whenever sprite is set. Allow Sprite to be set only using property (or method), so that you could track the change, like this:
public sealed class SpriteObject : ScriptableObject
{
public event Action SpriteChanged;
[SerializeField]
private Sprite _sprite;
public Sprite Sprite
{
get { return _sprite; }
set
{
if(_sprite == value)
return;
_sprite = value;
SpriteChanged?.Invoke();
}
}
}
Then, you need script, that will react to changed and assign the changed sprite to SpriteRenderer. So, something like this:
NOTE: name is purely for example. Do NOT name your classes like this!
[RequireComponent(typeof(SpriteRenderer))]
public class ScriptThatUsedSpriteObject : MonoBehaviour
{
public SpriteObject spriteObject;
private SpriteRenderer spriteRenderer;
/// Called once the script is created.
private void Awake()
{
spriteRenderer = GetComponent<SpriteRenderer>();
if(spriteObject != null)
{
spriteRenderer.sprite = spriteObject.Sprite;
spriteObject.SpriteChanged += HandleSpriteChanged;
}
}
/// Called whenever sprite is changed inside SpriteObject.
private void HandleSpriteChanged()
{
spriteRenderer.sprite = spriteObject.Sprite;
}
}
Now, if some script changes sprite in SpriteObject, every ScriptThatUsedSpriteObject will automatically update their sprites.
public class PublicSprite : MonoBehaviour {
public Sprite publicSprite;
#region Singelton
public static PublicSprite instance;
private void Awake()
{
if (instance != null)
{
Debug.LogWarning("More than one instance found");
return;
}
instance = this;
}
}
get the sprite like this:
PublicSprite.instance.publicSprite;
as Mentioned here, you probably want to use a Singelton. It is best to avoid the use of them only if its necessary as its a very bad programming practice. (you can learn more on why to avoid them here: What is so bad about singletons?
However, I can't think of another way of doing what you seek for.

Unity 2D: Simple Cutscene animation system/manager

I am struggeling to come up with a smart way to deal with cutscenes in my 2D game. I think I have decided to Create/Control the cutscenes using the Animator, and moving the actual GameObjects around.
What I am struggeling with is:
This approach means each GameObject needs it's own Animator. So how do I then trigger the correct Cutscene? I am going to use game stages to control the game and its progress, so for example:
if(gameStage == 34 && entering scene castle)
{
playCorrectCutscene();
}
How and where do I keep references to all my cutscenes? Say I have 22 NPCs in a scene, and 15 of those have their own Animator since they have a cutscene, how do I play the Animation from NPC_11?
I guess what I am looking for is some sort of "Cutscene Manager". The best possible solution would be to have a List of every cutscene (animation) with an ID. Then I could just use the ID to play the correct animation. But since each Animation is stored in the actual GameObject I have no idea if that is possible.
Hope Im making sense.
Once you create complete prefab with 1 Animator per prefab, then you can use bellow method to create instances on the fly:
Let say you have CutsceneManager script like this:
class CutsceneManager : MonoBehaviour {
public GameObject InstantiateResource(string folder, string name)
{
GameObject resource = Instantiate<GameObject>(Resources.Load<GameObject>(folder + "/" + name));
if (resource == null)
{
Debug.LogErrorFormat("Cannot find resource {0} in {1}", name, folder);
return null;
}
resource.name = name;
return resource;
}
}
The easiest way to use it is to attach it to Empty object. Then you can create public variable for manager in other scripts, where you would need to show cutscene, like this:
class SomeOtherScript : MonoBehaviour {
public CutsceneManager CutsceneManager;
}
This will let you drag&drop CutsceneManager empty into each script where you need it. This way you have 1 instance of cutscenemanager for all classes.
Now, in place where you would need to play custscene, you instantiate:
class SomeOtherScript : MonoBehaviour {
public CutsceneManager CutsceneManager;
public void PlayMyCutscene() {
GameObject cutscene = CutsceneManager.InstantiateResource("Cutscenes", "SomeOtherCutscene");
cutscene.setActive(true); // Or whetever other method to fire it off
}
}
On folder structure you would need to have: Assets\Resources\Cutscenes
Cutscenes would be called: SomeOtherCutscene.prefab
Notice there is no need to include .prefab when you are instantiating one - Unity framework will "know" and add it for you.

How to find all Cube game Object in the scene?

I'm looking for a way to find all CubeGameObject in the scene. I'm trying to do this :
Cube[] ballsUp = FindObjectsOfType (typeof(Cube)) as Cube[];
But cube isn't a game object type apparently.
I think i need to use something related to PrimitiveType but can figure out what and how to use it...
Thanks
Your Cube is of primitive type. And Primitive type objects are not possible to find using FindObjectsOfType.
There are many ways to solve the above problem. The easiest is by using tags.
When you instantiate your cube object you can use tag "Cube".
GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
cube.tag = "Cube";
Then you can get all the cube objects in scene with cube tags using
GameObject[] arrayofcubes = GameObject.FindGameObjectsWithTag("Cube");
This will give all the array of GameObject cubes in the scene.
FindObjectsOfType can be used to find gameobjects with attached classed and not primitive types.
Another way to proceed is finding all objects with MeshFilters and Searching for the Desired primitive name in the mesh filter arrays
string[] meshNames = new string[5] {"Cube", "Sphere", "Capsule", "Cylinder", "Plane"};
MeshFilter[] allMeshFilters = FindObjectsOfType(typeof(MeshFilter)) as MeshFilter[];
foreach(MeshFilter thisMeshFilter in allMeshFilters)
{
foreach(string primName in meshNames)
{
if (primName == thisMeshFilter.sharedMesh.name)
{
Debug.Log("Found a primitive of type: " + primName);
}
}
}
Geeting all the Object by their primitive type (C#)
You could try using a script. Let's say your GameObjects have a script MyScript, then you could FindObjectsofType GameObject and GetComponent Myscript.
Hope this helps. Although, I know it's not the answer you want, it's definitely an idea worth trying as a last resort :)
You could try this. If you are using the cube primitive of unity the mesh should be called "Cube" and while running "Cube Instance".
var gameOjects = GameObject.FindObjectsOfType<GameObject>();
foreach (var gameOject in gameOjects)
{
var meshFilter = gameOject.GetComponent<MeshFilter>();
if (meshFilter != null && meshFilter.mesh.name == "Cube Instance")
Debug.Log(gameOject.name);
}
tough this isn't very elegant or robust.
A more appropriate way would be to tag all cubes and get them by "FindGameObjectsWithTag"
Then recommended way from Unity of doing this is to create a tag and then use GameObject.FindGameObjectsWithTag to find all of them. GameObject.FindGameObjectsWithTag returns array of objects in this tag.
For example, create a tag called "cubeTags" then go to each cube and change the tag to cubeTags. When you want to find all the cubes, you can just do:
GameObject[] cubes = GameObject.FindGameObjectsWithTag ("cubeTags");
Cube[] ballsUp = new Cube[cubes.Length];
for(int i=0; i<cubes.Length; i++){
ballsUp = cubes[i].GetComponent<Cube>();
}