I was using this tutorial to code a VR game in Unity. When I got to the scripting, I ran into an issue. I could not see variables in the Inspector sidebar. Here is my code:
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Hello : MonoBehaviour {
[SerializeField]
public AudioClip clip;
public AudioSource audioSource;
public Transform gunBarrelTransform;
void Start ()
{
audioSource = GetComponent<AudioSource> ();
audioSource.clip = clip;
}
void Update (){
if (OVRInput.Get (OVRInput.Button.SecondaryHandTrigger)) {
audioSource.Play ();
RaycastGun ();
}
}
private void RaycastGun()
{
RaycastHit hit;
if (Physics.Raycast (gunBarrelTransform.position,
gunBarrelTransform.forward, out hit)) {
if (hit.collider.gameObject.CompareTag ("Cube")) {
Destroy (hit.collider.gameObject);
}
}
}
}
Even when I remove the [SerializeField] it does not work. Does anybody know why the variables aren't showing up? Thank you so much for the help!
Related
I'm new to coding and i'm trying to spawn a clone of a ball in unity, but it won't appear.
It does spawn at the spawn point but it doesn't appear.
Here is my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameController : MonoBehaviour
{
public GameObject ball;
public Transform spawnPoint;
// Start is called before the first frame update
void Start()
{
SpawnBall();
}
// Update is called once per frame
void Update()
{
}
void SpawnBall()
{
Instantiate(ball, spawnPoint.position, Quaternion.identity);
}
}
Edit: it's a 3d game and the mesh renderer is enabled.
Okay nevermind: i just redid the ball and it worked.
¯_(ツ)_/¯
I made a script that shoots a bullet and destroys it after 3 seconds, however it destroys the original bullet after it is shot which makes unity unable to make copies of it to shoot another bullet, An okay solution might be to make a copy of the bullet and shoot the copy however I do not know how to do that.
This is the script for the gun
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunShootingScript : MonoBehaviour
{
public ParticleSystem MuzzleFlash;
public float damage = 10f;
public float range = 100f;
public GameObject bulletPrefab;
public float bulletLife = 3f;
public Camera playerCamera;
private void Update()
{
if(Input.GetKeyDown(KeyCode.Mouse0))
{
Destroy(bulletPrefab, bulletLife);
Shoot();
}
}
void Shoot()
{
MuzzleFlash.Play();
Instantiate(bulletPrefab, playerCamera.transform.position, playerCamera.transform.rotation);
RaycastHit hit;
if(Physics.Raycast(playerCamera.transform.position, playerCamera.transform.forward, out hit, range))
{
TakeDamage target = hit.transform.GetComponent<TakeDamage>();
if(target != null)
{
target.GiveDamage(damage);
}
}
}
}
This is the script for the bullet.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Shot : MonoBehaviour
{
// Start is called before the first frame update
public float speed = 3000f;
void Update()
{
transform.position += transform.forward * speed * Time.deltaTime;
}
}
From what I see, you destroy the bulletPrefab but you never actually assign an object for it. You can have a separate GameObject and do that when instantiating inside the Shoot method. Try this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunShootingScript : MonoBehaviour
{
public ParticleSystem MuzzleFlash;
public float damage = 10f;
public float range = 100f;
public GameObject bulletPrefab;
public float bulletLife = 3f;
private GameObject bulletShot // This is what I added
public Camera playerCamera;
private void Update()
{
if(Input.GetKeyDown(KeyCode.Mouse0))
{
Destroy(bulletShot); // Removed the timer from here
Shoot();
}
}
void Shoot()
{
MuzzleFlash.Play();
bulletShot = Instantiate(bulletPrefab, playerCamera.transform.position, playerCamera.transform.rotation); // Assigned the bullet to the separate GameObject
RaycastHit hit;
if(Physics.Raycast(playerCamera.transform.position, playerCamera.transform.forward, out hit, range))
{
TakeDamage target = hit.transform.GetComponent<TakeDamage>();
if(target != null)
{
target.GiveDamage(damage);
}
}
}
}
That way, when you try to destroy it, there will actually be something to destroy. However, this will create a new issue. The previously instantiated object will be destroyed instantly when you shoot again. You can fix that by creating a list and adding the bullets there. However, that is NOT efficient. And since you are going to start all over, I suggest you go for an Object Pool. What is that? Glad you asked!
There is a very good video by Jason Weimann on YouTube about object pooling. You might want to give it a go, it is old but definitely not outdated.
https://www.youtube.com/watch?v=uxm4a0QnQ9E
You might need to keep a reference to the shot bullet, to be able to destroy with a coroutine after 3 seconds, it later on like this:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GunShootingScript : MonoBehaviour
{
public ParticleSystem MuzzleFlash;
public float damage = 10f;
public float range = 100f;
public GameObject bulletPrefab;
public float bulletLife = 3f;
private Queue<GameObject> myQ = new Queue<GameObject>(); //queue to keep track of the shot bullet and handle the delayed destroy
private IEnumerator coroutine;
void Start() {
coroutine = DelayedDestroy(3f);
}
public Camera playerCamera;
private void Update()
{
if(Input.GetKeyDown(KeyCode.Mouse0))
{
//Destroy(bulletPrefab, bulletLife); Commented to avoid immediate destruction
Shoot();
}
}
void Shoot()
{
MuzzleFlash.Play();
myQ.Enqueue(Instantiate(bulletPrefab, playerCamera.transform.position, playerCamera.transform.rotation));
RaycastHit hit;
if(Physics.Raycast(playerCamera.transform.position, playerCamera.transform.forward, out hit, range))
{
TakeDamage target = hit.transform.GetComponent<TakeDamage>();
if(target != null)
{
target.GiveDamage(damage);
}
}
StartCoroutine(coroutine);
}
private IEnumerator DelayedDestroy(float waitTime) {
yield return new WaitForSeconds(waitTime);
GameObject nullcheck = myQ.Dequeue();
if (nullcheck != null) { //in case the queue is empty
Destroy(nullcheck );
}
}
}
Did not debug that, it is to give you the idea. You can check the Queue data structure and coroutines.
Check pooling to achieve what you are making even better :)
I am trying to add some sound to my unity practice project and I have applied the sound and prepared the script necessary for it... but now whenever I am testing it through Unity player audio is not working.. each time I am getting this error log.
"Can not play a disabled audio source UnityEngine.AudioSource:Play()
coinhandler:OnCollisionEnter2D(Collision2D) (at
Assets/Script/coin/coinhandler.cs:24)"
My Coinhandler.cs script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Audio;
public class coinhandler : MonoBehaviour {
public Transform particles;
public AudioSource coinCollectS;
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
}
void OnCollisionEnter2D (Collision2D collider)
{
if (collider.gameObject.tag == "Player")
coinCollectS.Play ();
{
Instantiate (particles, new Vector3 (transform.position.x, transform.position.y, -0.2f), Quaternion.identity);
shooterMain.IncreaseSpeed ();
shooterMain.increasePoint ();
GameObject.FindWithTag ("points").GetComponent<Text>().text = shooterMain.getPoints ().ToString ();
Destroy (gameObject);
}
}
}
I'm making a target in Unity that looks like a dartboard with three different levels of scoring depending on where you shoot. The issue is that the Score Text wont change when I shoot on the target. I'm a novice and I "translated" below code from Javascript and wondering if you experts could see
if there is any issues with the code?
GlobalScore (attached this to an empty gameObject. I draged the text 'ScoreNumber' to ScoreText slot in Unity)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class GlobalScore : MonoBehaviour {
public static int CurrentScore;
public int InternalScore;
public GameObject ScoreText;
void Update () {
InternalScore = CurrentScore;
ScoreText.GetComponent<Text>().text = "" + InternalScore;
}
}
ZScore25 (created 3 scripts (ZScore25, ZScore50, ZScore100) which I attached to the three cylinder gameObject I created)
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class ZScore25 : MonoBehaviour
{
void DeductPoints(int DamageAmount)
{
GlobalScore.CurrentScore += 25;
}
}
HandgunDamage Script
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class HandGunDamage : MonoBehaviour {
public int DamageAmount = 5;
public float TargetDistance;
public float AllowedRange = 15.0f;
void Update () {
if (GlobalAmmo.LoadedAmmo >= 1) {
if (Input.GetButtonDown("Fire1"))
{
RaycastHit Shot;
if (Physics.Raycast(transform.position, transform.TransformDirection(Vector3.forward), out Shot))
{
TargetDistance = Shot.distance;
if (TargetDistance < AllowedRange)
{
Shot.transform.SendMessage("DeductPoints", DamageAmount, SendMessageOptions.DontRequireReceiver);
}
}
}
}
}
}
Debug.Log (or breakpoints) help you to see where the problem lies. I tested your case with minor changes and the score text value was changing.
I replaced ZScore25,50,100 scripts with a single ZScore script that has score as public field which you can set in the editor.
public class ZScore : MonoBehaviour {
public int Score;
public void DeductPoints() {
Debug.Log("CurrentScore += " + Score);
GlobalScore.CurrentScore += Score;
}
}
..and then I used raycast (the example script below was attached to camera):
void Update () {
if (Input.GetMouseButtonDown(0)) {
var lookAtPos = Camera.main.ScreenToWorldPoint (new Vector3 (Input.mousePosition.x, Input.mousePosition.y, Camera.main.nearClipPlane));
transform.LookAt (lookAtPos);
RaycastHit Shot;
if (Physics.Raycast(transform.position, transform.forward, out Shot))
{
Debug.Log ("Raycast hit");
var score = Shot.transform.GetComponent<ZScore> ();
if (score != null) {
Debug.Log ("Hit ZScore component");
score.DeductPoints ();
}
}
}
}
When ever the enemy dies, he plays the sound but the sound ends up being super distorted. I think it's because its playing in the Update method, but I'm not sure how to overcome that.
From other forums I've read they say to use a boolean but how would I go about implementing a boolean in this situation?
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.AI;
public class aiscript : MonoBehaviour
{
NavMeshAgent agent;
public GameObject bloodExplosion;
private AudioSource audioSource;
public GameObject render;
public float Health;
public GameObject bloodSpawn;
private Transform bloodSpawned;
public GameObject player;
void Start()
{
agent = GetComponent<NavMeshAgent>();
}
void Update()
{
agent.SetDestination(player.transform.position);
if(Health <= 0)
{
render.SetActive(true);
audioSource = gameObject.GetComponent<AudioSource>();
audioSource.PlayOneShot(audioSource.clip);
Instantiate(bloodExplosion, bloodSpawn.transform.position,
bloodSpawn.transform.rotation);
Die();
}
}
public void Die()
{
Destroy(this.gameObject, audioSource.clip.length);
}
}
Found out how, if anyone was wondering I added an if statement:
if(Health <= 0)
{
render.SetActive(true);
audioSource = gameObject.GetComponent<AudioSource>();
if(!audioSource.isPlaying)
{
audioSource.PlayOneShot(audioSource.clip);
}
Instantiate(bloodExplosion, bloodSpawn.transform.position,
bloodSpawn.transform.rotation);
Die();
}