How to interact with objects/variables from another function/method? - c#

I am trying to Destroy the impact particles after the Target (In this case an explosive barrel) explodes.
But I get the "The name 'impactParticle' does not exist in the current context" error.
I understand that I cannot interact with impactParticle from "void Die();" but is there a way to make the particle system/object public so that other methods can mention it?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Gun : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
public void Shoot()
{
muzzleFlash.Play();
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit, range))
{
Debug.Log(hit.transform.name);
Target target = hit.transform.GetComponent<Target>();
if (target != null)
{
target.TakeDamage(damage);
}
GameObject impactParticle = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
Destroy(impactParticle, 5f);
}
}
public void Die()
{
Destroy(impactParticle);
}
}
I am adding this other script just in case;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Target : MonoBehaviour
{
public float health = 50f;
public GameObject explode;
public void TakeDamage(float amount)
{
health -= amount;
if (health <= 0f)
{
Die();
}
}
public void Die()
{
GameObject PartClone = Instantiate(explode, gameObject.transform.position, gameObject.transform.rotation);
PartClone.SetActive(true);
gameObject.SetActive(false);
Destroy(PartClone, 2f);
Destroy(gameObject, 2.1f);
}
}

How about making impactParticle a class level variable:
private GameObject _impactParticle;
And instantiating it as below:
_impactParticle = Instantiate(impactEffect, hit.point, Quaternion.LookRotation(hit.normal));
then you can have access to the object in Die method:
public void Die()
{
if (_impactParticle != null)
{
Destroy(_impactParticle);
}
}

Related

Visual studio can't find definition for TakeDamage from another method

I am making health and damage script in Unity.
I have error CS0117 'PlayerHealth' does not contain a definition for 'TakeDamage'
I want player to have 20 healths and when touched an object it will damage him.
I tried searching on google but I didn't find answer.
PlayerHealth script:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
public int health = 20;
public void TakeDamage(int damage)
{
health -= damage;
if (health <= 0)
{
Destroy(gameObject, 0.3f);
}
}
}
And for EnemyDamage script I use this code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerHealth : MonoBehaviour
{
public int DMG;
float cooldown = 0f;
private void Update()
{
Debug.Log(cooldown);
cooldown -= Time.deltaTime;
}
private void OnCollisionEnter(Collision collision)
{
PlayerHealth health = collision.gameObject.GetComponent<PlayerHealth>();
if (cooldown <= 0)
{
if (health != null)
{
PlayerHealth.TakeDamage(DMG);//here is the error
}
cooldown = 1f;
}
}
}
PlayerHealth.TakeDamage(DMG); tries to call a static method TakeDamage on the class PlayerHealth but there is no such method, hence the error.
Your code is a little mess anyway, lets clean it up.
Attach this script to your game objects which can lose health (e.g. a player):
public class Health : MonoBehaviour // you called it NewBehaviourScript
{
public int health = 20;
public void TakeDamage(int damage) {
health -= damage;
if (health <= 0) {
Destroy(gameObject, 0.3f);
}
}
}
Attach this script to your game objects which can inflict damage:
public class Damage : MonoBehaviour // you called it PlayerHealth (?!)
{
public int DMG;
float cooldown = 0f;
void Update()
{
Debug.Log(cooldown);
cooldown -= Time.deltaTime;
}
void OnCollisionEnter(Collision collision)
{
if (cooldown <= 0f) {
Health health = collision.gameObject.GetComponent<Health>();
if (health != null) {
// call TakeDamage on the collided >instance<
health.TakeDamage(DMG);
}
cooldown = 1f;
}
}
}
This should give you a starting point with an appropriate colliders setup.

Not able to destroy the prefeb object in unity

using UnityEngine;
public class Gun : MonoBehaviour
{
public GameObject enemy; // Not necessary, only if you need a reference to the enemy for future actions
public float damage = 100f;
void Update()
{
if (Input.GetButtonDown("Fire1"))
{
Shoot();
}
}
void Shoot() // The are a general routine to program on all laguajes, you should name all functions with Uppercase start letter
{
RaycastHit hit;
if (Physics.Raycast(transform.position, transform.forward, out hit))
{
// Target targ = GetComponent<Target>(); //
Target targ = hit.collider.GetComponent<Target>();
// Now, you have the enemy script values referenced and you can make your actions.
// I dont understand next code, your are not referenig enemy never, I mean, enemy ever is null
if (enemy != null)
{
Destroy(enemy);
}
}
target.cs:
using UnityEngine;
public class Target : MonoBehaviour
{
// Start is called before the first frame update
public float health = 50f;
public void TakeDamage (float amount)
{
health -= amount;
if (health <= 0f)
{
Die();
}
}
void Die()
{
Destroy(gameObject);
}
}

Unity - help needed to touch and hold UI button to call update method and auto fire (here is the script)

I am a newbie with no coding experience just started using unity I was following brackeys Ray cast shooting video,https://youtu.be/THnivyG0Mvo,, and I created the gun script but I wanted to turn it into mobile so I wanted to autofire by holding a UI button.
plz, I need help me know no code.
this is my code.
I was thinking is there a way to put something in place of input.getbutton to make a button that will autofire on holding.
Thanks & sorry if this is a silly question
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Unity.VisualScripting;
public class Gun : MonoBehaviour
{
public float damage = 10f;
public float range = 100f;
public float fireRate = 15f;
public float impactForce = 30f;
public Camera fpsCam;
public ParticleSystem muzzleFlash;
public GameObject impactEffect;
private float nextTimeToFire = 0f;
// Update is called once per frame
public void Update()
{
if (Input.GetButton("Fire1") && Time.time >= nextTimeToFire)
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}
public void Shoot()
{
muzzleFlash.Play();
RaycastHit hit;
if (Physics.Raycast(fpsCam.transform.position, fpsCam.transform.forward, out hit,
range))
{
Enemy enemy = hit.transform.GetComponent<Enemy>();
if (enemy != null)
{
enemy.TakeDamage(damage);
}
if (hit.rigidbody != null)
{
hit.rigidbody.AddForce(-hit.normal * impactForce);
}
GameObject impactGO = Instantiate(impactEffect, hit.point,
Quaternion.LookRotation(hit.normal));
Destroy(impactGO, 2f);
}
}
}
Create a Button, and add a new script to it. This script will be responsible for handling the button state. Essentially what we need to do is..
When OnPointerDown happens, set a value to indicate the button is held down. When OnPointerUp happens, reset the value.
using UnityEngine;
using UnityEngine.EventSystems;
public class ClickAndHoldButton : MonoBehaviour, IPointerDownHandler, IPointerUpHandler, IPointerEnterHandler
{
public bool IsHeldDown => isHeldDown;
private bool isHeldDown;
public void OnPointerDown(PointerEventData eventData)
{
isHeldDown = true;
}
public void OnPointerUp(PointerEventData eventData)
{
isHeldDown = false;
}
public void OnPointerEnter(PointerEventData eventData)
{
}
}
Then in Update of your gun, you will check the button state to see if it is being held down.
public ClickAndHoldButton mobileFireButton;
void Update()
{
if (Time.time >= nextTimeToFire && (
Input.GetButton("Fire1") ||
mobileFireButton.IsHeldDown))
{
nextTimeToFire = Time.time + 1f / fireRate;
Shoot();
}
}

My script doesn't activate UI and doesn't play animations

Hey guys I have a made two scripts to handle door opening.
Script 1 - Raycast
Script 2 - The door opening script
I have the raycast on the player camera and I have script 2 on the door.
But there is a problem.
In script 2, I have code that makes UI active and inactive and code that does the door animation
SCRIPT 1 -
using System.Collections.Generic;
using UnityEngine;
public class PlayerCasting : MonoBehaviour
{
public Camera FPScam;
public float range = 6;
public static float ToTarget;
void Update()
{
RaycastHit Hit;
if (Physics.Raycast(FPScam.transform.position, FPScam.transform.forward, out Hit, range))
{
ToTarget = Hit.distance;
}
}
}
SCRIPT 2 -
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class DoorOpen : MonoBehaviour
{
public float Distance;
public GameObject key;
public GameObject reason;
public GameObject Hinge;
public AudioSource DoorCreak;
// Update is called once per frame
void Update()
{
Distance = PlayerCasting.ToTarget;
}
private void OnMouseOver()
{
if (Distance <= 3.5f)
{
key.SetActive(true);
reason.SetActive(true);
}
if (Input.GetButtonDown("Action"))
{
if (Distance <= 3.5f)
{
key.SetActive(false);
reason.SetActive(false);
this.GetComponent<BoxCollider>().enabled = false;
Hinge.GetComponent<Animation>().Play("DoorOpenAnim");
DoorCreak.Play();
}
}
}
private void OnMouseExit()
{
key.SetActive(false);
reason.SetActive(false);
}
}
But, the UI doesn't activate nor does the animation plays when I click 'E' and when the Raycast distance <= 3.5.
I have the raycast on the player camera
Since you're using OnMouseOver() and OnMouseExit() your methods will only work when the player's mouse is on the thing you want to raycast.
Make sure that the raycast is actually pointing the same direction the mouse cursor is. You use use Debug.Raycast() to visually see where the raycast is going.
If the raycast is going in the direction you want it to and it's still not working try a different way of communicating through the scripts and avoid using OnMouseOver().
For example you could try something like this:
public class PlayerCasting : MonoBehaviour
{
public Camera FPScam;
public float range = 6;
public static float ToTarget = 0f;
public static GameObject HoveredObject = null; // <----
void Update()
{
RaycastHit Hit;
if (Physics.Raycast(FPScam.transform.position, FPScam.transform.forward, out Hit, range))
{
ToTarget = Hit.distance;
HoveredObject = Hit.collider.gameObject; // <----
}
}
}
public class DoorOpen : MonoBehaviour
{
public float Distance;
public GameObject key;
public GameObject reason;
public GameObject Hinge;
public AudioSource DoorCreak;
// Update is called once per frame
void Update()
{
if (PlayerCasting.HoveredObject == gameObject)
{
Distance = PlayerCasting.ToTarget;
CheckDistance();
}
}
private void CheckDistance()
{
if (Distance <= 3.5f)
{
key.SetActive(true);
reason.SetActive(true);
if (Input.GetButtonDown("Action"))
{
key.SetActive(false);
reason.SetActive(false);
this.GetComponent<BoxCollider>().enabled = false;
Hinge.GetComponent<Animation>().Play("DoorOpenAnim");
DoorCreak.Play();
}
}
else
{
key.SetActive(false);
reason.SetActive(false);
}
}
private void OnMouseExit()
{
key.SetActive(false);
reason.SetActive(false);
}
}

Player won't stick to moving platform

I'm trying to create a platform that will move player with itself. Both horizontally, as well as vertically. I tried to do this by setting the player's parent to be the platform, but the player doesn't stick to it. This is the code I'm trying to use:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Platform : MonoBehaviour
{
public GameObject player;
public GameObject platformAnchor;
public float movementSpeed;
void Update()
{
transform.position = Vector3.Lerp(transform.position, platformAnchor.transform.position, (Time.deltaTime * movementSpeed));
}
private void OnTriggerEnter(Collider other)
{
if (other.gameObject == player)
{
other.transform.parent = transform;
}
}
private void OnTriggerExit(Collider other)
{
if (other.gameObject == player)
{
other.transform.parent = null;
}
}
}

Categories

Resources