Unity3D RawImage(UI) Instantiate - user-interface

When I am instantiating prefab as GameObject there is no problem. But when instantiating prefab as RawImage there is NullReferenceException problem. (Prefab is RawImage if you need to know)
This is my code:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class Insstantia : MonoBehaviour
{
public GameObject img;
public void Instan()
{
RawImage[] myObject = new RawImage[8];
RectTransform[] rt = new RectTransform[8];
for (int i = 0; i < 8; i++)
{
myObject[i] = Instantiate(img, new Vector3(800 * i, 0, 0), Quaternion.identity) as RawImage;
rt[i] = myObject[i].GetComponent<RectTransform>();
myObject[i].transform.SetParent(gameObject.transform, false);
rt[i].anchorMin = new Vector2(0.05875f, 0);
rt[i].anchorMax = new Vector2(0.94375f, 1);
}
}
}

This is because you are casting your GameObject prefab to a component type (RawImage) which is possible because the Component type inherits from the Object type.
So when you try to get a Component for example on this line:
rt[i] = myObject[i].GetComponent<RectTransform>();
A NullReferenceExceptiion is thrown because "img" gameObject has been cast to a Component type object and therefore the RectTransform Component does not exist.
Try changing your public GameObject img field to:
public RawImage img;

Your issue is that you are trying to convert a GameObject into a Component. The instantiate command will create a GameObject for you, which in this case is your prefab with a component attached to it.
To fix this issue, you would just have to store the GameObject instead of the component, and if you were to need the RawImage component, obtain it in the same way as your RectTransform.
public GameObject[] myObject = new GameObject[8];
instead of
public RawImage[] myObject = new RawImage[8];
(and don't forget to change your conversion call from as RawImage To as GameObject)
If you are referring to a Actual Image, and not the component. You might want to take a look at Resources.Load Instead of using Instantiate.

Related

Moving a Prefab in Unity

The purpose of the code is to
make a prefab of "Normal" and "Virus"
make them move in random directions
when they collide, change "Normal" into "Virus" Prefabs
However, I've got stucked on step 2.
I successfuly made "Normal" and "Virus" Prefabs get spawned at random places.
Btw, I have no idea what I should do to supply transform function to Prefabs.
Also, what codes should I use to replace "Normal" Prefabs into "Virus" Prefabs if they collide each other?
These are the codes and pics I used
using UnityEngine;
public class VirusSpawner : MonoBehaviour
{
[SerializeField]
private int objectSpawnCount = 5;
[SerializeField]
private GameObject[] prefabArray;
private void Awake()
{
for (int i = 0; i < objectSpawnCount; ++i)
{
int index = Random.Range(0, prefabArray.Length);
float x = Random.Range(-3, 3);
float y = Random.Range(-4, 4);
Vector3 position = new Vector3(x, y, 0);
Instantiate(prefabArray[index], position, Quaternion.identity);
}
}
}
As I understood what you need is a script for your objects, responsible for moving them and controlling all this "Normal" and "Virus" states.
2.1. Create a C# Script (i.e. "Virus") that moves the object as soon as it exists.
2.2. Right after instantiating your prefabs add this script to it:
GameObject newGO = Instantiate(prefabArray[index], position, Quaternion.identity);
newGO.AddComponent<Virus>();
On the new "Virus" script, add the collision detection and variable that holds the state of Normal or Virus
As #Caio Rocha said you can instantiate new Virus Object and add component to it but there can be one more way which can be faster :
Create a Empty Game Object.
Add both (Virus and Normal) prefabs as children of that prefab and drag and drop to project window to create new Prefab.
Attach this script to Parent:
public class ParentObject : MonoBehaviour
{
public GameObject VirusObject;
public GameObject NormalObject;
private bool isVirus;
private void Awake()
{
isVirus = (Random.Range(0, 2) == 1); //Randomly Make an object
//virus or normal on instantiation
if (isVirus)
{
TurnToVirus();
}
else
{
TurntoNormal();
}
}
private void OnCollisionEnter(Collision other)
{
ParentObject coll =
other.collider.gameObject.GetComponent<ParentObject>();
if (coll && coll.isVirus) //if other object is virus
{
TurnToVirus();
}
}
private void TurnToVirus()
{
VirusObject.SetActive(true);
NormalObject.SetActive(false);
}
private void TurntoNormal()
{
VirusObject.SetActive(false);
NormalObject.SetActive(true);
}
}
Now Inside prefab array move this Parent prefab instead of your own prefabs and it will randomly create normal and virus objects and when they interact normal turn to viruses. Make sure this script and collider is now on parent. This is much optimized over adding component individually just for single check.

Getting errors when i try to get game to restart when i hit an obstacle or fall of ground

Please excuse me I'm a complete novice at all this but I'm trying to make a game following "Brackeys How To Make A Video Game" I'm on video 8 if that helps. I can't seem to find what i have done wrong i have added my scripts for "player movement", "player collision" and "game manager". Please if there is anything else you need to help me please ask i really don't want to give up just yet was really enjoying doing this.
Thank you all
using UnityEngine;
public class PlayerMovement : MonoBehaviour {
// This is a reference to the Rigidbody component called "rb"
public Rigidbody rb;
public float forwardForce = 2000f; // Variable that determines the forward force
public float sidewaysForce = 500f; // Variable that determines the sideways force
// We marked this as "Fixed"Update because we
// are using it to mess with physics.
void FixedUpdate ()
{
// Add a forward force
rb.AddForce(0, 0, forwardForce * Time.deltaTime);
if (Input.GetKey("d")) // If the player is pressing the "d" key
{
// Add a force to the right
rb.AddForce(sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (Input.GetKey("a")) // If the player is pressing the "a" key
{
// Add a force to the left
rb.AddForce(-sidewaysForce * Time.deltaTime, 0, 0, ForceMode.VelocityChange);
}
if (rb.position.y < -1f)
{
FindObjectOfType<GameManager>().EndGame();
}
}
}
using UnityEngine;
public class PlayerCollision : MonoBehaviour {
public PlayerMovement movement; // A reference to our PlayerMovement script
// This function runs when we hit another object.
// We get information about the collision and call it "collisionInfo".
void OnCollisionEnter (Collision collisionInfo)
{
// We check if the object we collided with has a tag called "Obstacle".
if (collisionInfo.collider.tag == "Obstacle")
{
movement.enabled = false; // Disable the players movement.
FindObjectOfType<GameManager>().EndGame();
}
}
}
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
bool gameHasEnded = false;
public float restartDelay = 1f;
public GameObject completeLevelUI;
public void CompleteLevel ()
{
completeLevelUI.SetActive(true);
}
public void EndGame ()
{
if (gameHasEnded == false)
{
gameHasEnded = true;
Debug.Log("GAME OVER");
Invoke("Restart", restartDelay);
}
}
void Restart ()
{
SceneManager.LoadScene(SceneManager.GetActiveScene().name);
}
}
when i fall off ground:
NullReferenceException: Object reference not set to an instance of an object
PlayerMovement.FixedUpdate () (at Assets/Scripts/PlayerMovement.cs:32)
when i hit an obstacle:
NullReferenceException: Object reference not set to an instance of an object
PlayerCollision.OnCollisionEnter (UnityEngine.Collision collisionInfo) (at Assets/Scripts/PlayerCollision.cs:15)
It seems to me that FindObjectOfType<GameManager>() is returning null, which is causing a null reference exception when you attempt to call the EndGame function. This most likely means that there is no object in your scene with the GameManager component on it. The solution to this problem is simple:
Create an empty object in your scene and add the GameManager component to it. This will fix the error in this instance, but it could happen in the future if you're not careful. It is also a good idea to check if you found an object or not before calling functions on it:
GameManager gm = FindObjectOfType<GameManager>();
if (gm != null)
{
gm.EndGame();
}

Destroying a prefab from mouse click raycast

I want to destroy or remove a spawning prefab from my scene when the mouse clicks on the gameobject. I'm trying to use the code below from the Unity docs, however I'm presented with the following error:
object reference not set to the instance of an object.
This script is attached to my main camera. onclick crashes the game. Can anyone see where this is going wrong?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class onClickDestroy : MonoBehaviour
{
public GameObject destroyCube;
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit(); //*
if (Physics.Raycast(ray, out hit)) //**
{
print("true" + hit.point);
}
}
}
}
Solution 1
Make sure your Camera is really tagged as MainCamera
if not click there and select MainCamera from the list
Solution 2
Get and check the main camera at game start
priavte Camera _camera;
privtae void Awake()
{
_camera = Camera.main;
if(!_camera)
{
Debug.LogError("No Camera tagged MainCamera in Scene!");
enabled = false;
}
}
Solution 3
Or instead of using Camera.main at all instead get the Camera component directly
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class onClickDestroy : MonoBehaviour
{
public GameObject destroyCube;
privtae Camera _camera;
private void Awake()
{
_camera = GetComponent<Camera>();
}
// Update is called once per frame
private void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = _camera.ScreenPointToRay(Input.mousePosition);
RaycastHit hit = new RaycastHit();
if (Physics.Raycast(ray, out hit))
{
print("true" + hit.point);
}
}
}
}

Can I know in Unity 5 who Instantiated the object?

Is it possible to get information from an Instantiated object from the one who Instantiated it?
For example let's say we have objectA:
Instantiate(objectB, gameObject.transform.position, Quaternion.identity);
Is there a way to do something like this in objectB:
Awake() { var vector = Parent.transform.position };
Where "parent" is the initiator.
You can do the following to accomplish that:
// in objectA class's function
GameObject objB = Instantiate(objectB, gameObject.transform.position, Quaternion.identity);
objB.parentPos = transform.position;
// and if you just want to know who Instantiated it, use this line:
objB.parentGameObj = gameObject;
// in objectB class
public Vector3 parentPos;
public GameObject parentGameObj;

Use parameters for variable animation

I'd like to animate my Score-GUI text counting up to a variable value but there are two things in my way:
1: How can I animate to a variable instead of a fixed value?
2: Why can't I add own properties (like int) to my script and animate them?
For #2 I created a property in my script. Yet the editor won't show it in the AddProperty-dialog (as shown below):
public int currentScore = 0;
public int score {
get { return currentScore; }
set { this.currentScore += value; }
}
EDIT: The animator is set up in the most basic way:
Since you only have 1 Animation. An Animator is irrelevant to the solution. This is tested and working. Now you need to make the Animation a Legacy type to get this working because we are not going to use the Animator.
Click the Animation on the Project -> look at the upper right section of the Inspector view, there is a little button there which will drop down a selection. "Debug" then Check the Legacy.
Set your Animation to whatever you want. I force the WrapMode in the script to be wrap mode once. So it will only play once.
Now in the Animation Component make sure you select the Animation that you want by default or it wont work. Cause we only use anim.Play(); Without parameters meaning, run the default animation that is set.
I created a Text UI and added an Animation that alpha is 0 from the start and at the end point making it 1. You have to do that on your own.
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class MyScore : MonoBehaviour {
// Use this for initialization
public int currentScore = 0;
public GameObject Myscore; // Drag the GameObject that has the Animation for your score.
public Text myScoreText; //Drag in the Inspector the Text object to reference
public Animation anim;
public int score
{
get { return currentScore; }
set { this.currentScore += value; }
}
void Start()
{
anim = Myscore.GetComponent<Animation>(); // Reference the Animation Component.
anim.wrapMode = WrapMode.Once; // Legacy animation Set to play once
AddScore();
}
public void AddScore()
{
score += 10;
myScoreText.text = score.ToString();
anim.Play();
Debug.Log("Current Score is "+ score);
Invoke("AddScore", 2);
}
}
Good luck.

Resources