Why Camera not exist in the script? - c#

using UnityEngine;
using System.Collections;
[RequireComponent(typeof(Camera))]
public class CameraFrustumGizmo : MonoBehaviour
{
Camera _camera;
void Start()
{
_camera = GetComponent<Camera>();
}
The Camera is black and when i start to type Ca...there is no Camera.
I'm not getting errors when compiling the script but when running the game i'm getting null exception.
The script is attached to Main Camera.
I tried now this:
using UnityEngine;
using System.Collections;
public class CameraTest : MonoBehaviour {
Camera _camera;
void Start()
{
_camera = GetComponent<Camera>();
}
public virtual void OnDrawGizmos()
{
Matrix4x4 temp = Gizmos.matrix;
Gizmos.matrix = Matrix4x4.TRS(transform.position, transform.rotation, Vector3.one);
if (_camera.orthographic)
Now the Camera exist but once i attached the script to the Main Camera i'm getting null exception before even running the game the null is on the line:
if (_camera.orthographic)
NullReferenceException: Object reference not set to an instance of an object
CameraTest.OnDrawGizmos () (at Assets/MyScripts/CameraTest.cs:17)
UnityEditor.DockArea:OnGUI()

OnDrawGizmos will be called in the scene view, which means that it may be called while the game isn't running.
Your Start function isn't called until the game runs, so there's a chance that _camera won't be initialized by the time OnDrawGizmos is called.
Basically, when you're messing around with editor scripting, you need to be very careful about which object references exist. It's usually best if your references can be rebuilt on the fly -- given that Unity reloads assemblies each time it re-compiles code, that is going to happen pretty often anyway.
Usually I'll do this with a property that caches a reference the first time it's needed:
Camera cachedCamera;
Camera _camera {
get {
if (cachedCamera == null) {
cachedCamera = GetComponent<Camera>();
}
return cachedCamera;
}
}
That will still fail in some circumstances, but it gives you the basic idea.

Related

Unity Transform not updating position realtime

I am trying to create a simple scriptable object for my shoot ability. I have that aspect working, but as I try to set my Transform to my player, it does not update the shoot position. I am very new to C#, and this script isnt complete. I still need to add the functionality to destroy the created objects. Any help would be greatly appreciated. I suspect I need to add an update function but im am not certain how to do this.
using UnityEngine.InputSystem;
using UnityEngine.AI;
using UnityEngine;
namespace EO.ARPGInput
{
[CreateAssetMenu]
public class Shoot : Ability
{
public Transform projectileSpawnPoint;
public GameObject projectilePrefab;
public float bulletSpeed = 10;
public float bulletLife = 3;
public override void Activate(GameObject parent)
{
var projectile = Instantiate(projectilePrefab, projectileSpawnPoint.position, projectileSpawnPoint.rotation);
projectile.GetComponent<Rigidbody>().velocity = projectileSpawnPoint.forward * bulletSpeed;
Destroy(projectile, bulletLife);
void OnCollisionEnter(Collision collision)
{
Destroy(projectile);
}
}
}
}
I'm still new to Unity and coding also, so take my advice with a load of salt :P.
It may be best to have a transform on your character (say just past the barrel of the player's gun) that you can put as the projectileSpawnPoint. In your code the projectileSpawnPoint is never set. Your first line of code in the "Activate" method should be something like:
public override void Activate(GameObject parent)
{
projectileSpawnPoint = playerGunBarrelTransform.transform.position;
var projectile = Instantiate(projectilePrefab, projectileSpawnPoint.position, projectileSpawnPoint.rotation);
projectile.GetComponent<Rigidbody>().velocity = projectileSpawnPoint.forward * bulletSpeed;
Destroy(projectile, bulletLife);
For destroying the projectile afterward you can keep it as you have it in OnCollision. howeer, with bullets in particular, since they tend to be instantiated A LOT and then destroyed afterward it would be best to use an object pooler for them to instantiate several of them on start and then disable and enable them as needed so you can resuse them instead of making new ones every time.
you have to create a new script that derives from Monobehaviour for your projectiles. attach that script to the projectile prefab and place the OnCollisionEnter method in that script. now your projectiles should get destroyed when touching another collider. make sure that there is a rigidbody component attached to the projectile.

Unity Scene does not exist although its defined?

I'm working on a death script for my game in Unity. I made a 3d Box without textures underneath my level and made its Collider isTrigger = true. I now added a script to the box that reloads the current scene when the player enters the trigger. Its 2 lines of code and I don't know why but I get the error:
Assets\scripts\death.cs(20,32): error CS0103: The name 'currentScene' does not exist in the current context
The Code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class death : MonoBehaviour
{
void Start()
{
Scene currentScene = SceneManager.GetActiveScene();
}
private void OnTriggerEnter(Collider other)
{
SceneManager.LoadScene(currentScene.buildIndex);
}
}
I know that the comments above already noticed your problem was the local variable and thanks to them, but this is just about to optimize your code and memory. you can just keep OnTriggerEnter only and delete Start.
private void OnTriggerEnter(Collider other)
{
SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
}
there's no need to store the scene in a variable if we will not use in a further needs. it will be just a waste of memory (bad habit)

Enabling/Disabling Script in C# failing to work

So I've been developing a 2D platformer game in C# and Unity and as a part of the game I have been developing powerups. One of these in invincibility, so when the player collides with the game object they cannot be killed for a period of time. I am relatively new to Unity and C# and read that I can use '.enabled' to enable/disable an external script that is attached to the same object. However, when I activate the powerup the object is destroyed but if I collide with an enemy or object I still die. Can anyone see why this is happening.
Below is the script that I have developed.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class InvincibilityPowerup : MonoBehaviour
{
public int Duration = 15;
void OnTriggerEnter2D(Collider2D coll)
{
if (coll.gameObject.tag == "Shield")
{
Destroy(GameObject.Find("Invincibility"));
StartCoroutine("Invincible");
}
}
IEnumerator Invincible()
{
Collision pIn = gameObject.GetComponent<Collision>();
pIn.enabled = false;
yield return new WaitForSeconds(Duration);
pIn.enabled = true;
}
}
1) GameObject.Find is completely unnecessary here. You already know which object is the invincibility powerup: its the one this script is attached to
2) Collision pIn = gameObject.GetComponent<Collision>(); both a) doesn't do what you want it to (you want to get the OTHER game object!) b) doesn't work anyway (Collision is not a component, Collider is)
3) you're destroying this before starting the coroutine, meaning your coroutine is being destroyed too.

How to fix "Can't Play a Disabled Audio Source"?

I am trying to add a sound into my game that whenever the player moves over a certain space it plays a crunch sound. I have created the AudioSource file and a .OGG file for the sound.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SpaceBlue : MonoBehaviour
{
public Transform spaceNext;
public AudioSource stepOnObject;
public AudioClip stepOnSound;
private void Start()
{
stepOnObject.clip = stepOnSound;
stepOnObject.enabled = true;
}
private void OnTriggerEnter(Collider other)
{
if (other.tag == "Player")
{
stepOnObject.Play();
if (BoardScript.diceValue > 0)
{
BoardScript.diceValue -= 1;
Debug.Log("The dice are now " +BoardScript.diceValue);
other.transform.LookAt(spaceNext);
}
}
}
}
I have included the source and clip to my game object and i have tried it both with and without "Play on wake" selected.
Whenever the play walks over the player walks over the object i get a warning in the unity engine saying that the source is disabled.
Any help is appreciated :)
I had a similar problem and I fixed it by changing the location of the Play() call to after calling Destroy(GameObject). I would recommend trying moving the call to Play() to the end of the function, or trying Invoke("stepOnObject.Play", 0.5f); to ensure it gets called.
Otherwise, make sure its checkbox is ticked, and that the AudioSource actually has a AudioClip attached.
If you have any piece of code in some other script that Destroys this game object or makes SetActive false, then the best way to solve this problem will be to delay that piece of code by some time using a Coroutine.

Unity3d not liking collision

using UnityEngine;
using System.Collections;
public class chicken_for : MonoBehaviour {
// Use this for initialization
void Start () {
}
// Update is called once per frame
void FixedUpdate () {
if (collision.gameObject.Quad == collisionObject){
Application.LoadLevel("SciFi Level");
}
}
}
I am attempting to when A person touches a quad, he goes to this sci-fi fortress. It however says the name 'collision' does not exist in the current context.
You're referencing a variable (collision) that doesn't exist. You've got a variable collisionObject that doesn't exist, too.
collision is typically the name of the argument to the OnCollisionEnter method. Your code should probably be inside this method instead of FixedUpdate. I'm guessing that you've copied code from a tutorial somewhere but put it in the wrong method.
collisionObject on the other hand is harder to guess, but I expect that if your script is intended to be a component on the player object, then collisionObject should be your quad; if the script is on the quad then collisionObject should be the player.
Either way, you need to declare that variable - probably as a public field so that you can populate it from the inspector.
Add a new function and make sure the player is tagged as player in the inspector. You also need to make sure that there is a collider on the quad that the player touches and a rigidbody component on the player.
using UnityEngine;
using System.Collections;
public class chicken_for : MonoBehaviour {
//This function will handle the collision on your object
void OnCollisionEnter (Collider col){
if(col.gameobject.tag == "Player"){ //if colliding object if tagged player
Application.LoadLevel("SciFi Level"); //load the sci-fi level
}
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
}
This should get you roughly where you want to be!

Categories