I'm quite new to unity and programming in general and I'm using "DontDestroyOnLoad (gameObject);" in a script that manages the all sounds played in the game, I run in to a problem that things like pause and unpause stop working when I load into another scene even though DondtDestroyOnLoad is on, it gives me a NullReferenceException error so i think that when loading a new scene it empty's the variables. does anyone now a way to prevent that from happening?
using UnityEngine.Audio;
using System;
using UnityEngine;
using Random=UnityEngine.Random;
public class AudioManager : MonoBehaviour
{
public Sound[] sounds;
public static AudioManager instance;
void Awake() {
if (instance == null) {
instance = this;
}
else {
Destroy(gameObject);
return;
}
DontDestroyOnLoad (gameObject);
foreach (Sound s in sounds) {
s.source = gameObject.AddComponent<AudioSource>();
s.source.clip = s.clip;
s.source.volume = s.volume;
if (s.randompitch == false) {
s.source.pitch = s.pitch;
}
s.source.loop = s.loop;
if (s.playonstart == true) {
Play(s.name);
}
}
}
public void Play (string name) {
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("there is no" + name);
return;
}
if (s.randompitch == true ) {
s.source.pitch = Random.Range(s.randompitchmin, s.randompitchmax);
}
s.source.Play();
}
public void SoundPause (string name) {
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("there is no" + name);
return;
}
s.source.Pause();
}
public void SoundUnPause (string name) {
Sound s = Array.Find(sounds, sound => sound.name == name);
if (s == null){
Debug.LogWarning("there is no" + name);
return;
}
s.source.UnPause();
}
}
You can add DontDestroyOnLoad to its array
like this
for(int i = 0; i < sounds.Length;)
{
DontDestroyOnLoad(sounds[i]);
i++;
}
Or you can search for sounds in Scane
by using :
GameObject.Find
GameObject.FindGameObjectsWithTag
Object.FindObjectOfType
EDIT
for(int i = 0; i < sounds.Length;)
{
DontDestroyOnLoad(sounds[i].GetComponent<GameObject>());
i++;
}
Related
I'm new to Unity New Input System, I have recently migrated my project from the old input system to the new input system but I'm facing some difficulties using it.
I have a class called InputManager that manages all the input actions for my game, and another class called PlayerInteractions that holds all the player's interactions, such as picking up objects, opening and closing drawers/doors and so on.
playerInteraction class was working perfectly using the old input system, but when I changed it to the new input system I couldn't handle the function calls properly so it didn't work completely. I managed to make picking up objects work but the opening/closing part didn't work because for that I'm calling another function from a class called InteractiveObjects that is attached to all objects that can be opened/closed such as door/drawers...
and it was hard for me to handle these function calls since I'm not good enough at the New Input System.
Here is a snippet of the PlayerInteractions Class
private InteractiveObjects interactiveObjects;
bool PickingUp, Open;
void Update()
{
raycastPos = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width / 2, Screen.height / 2, 0));
RaycastHit hit;
if (Physics.SphereCast(raycastPos, sphereCastRadius, mainCamera.transform.forward, out hit, maxDistance, 1 << interactableLayerIndex))
{
lookObject = hit.collider.transform.gameObject;
}
else
{
lookObject=null;
}
if (PickingUp)
{
if (currentlyPickedUpObject == null)
{
if (lookObject != null)
{
PickupObject();
}
}
else
{
BreakConnection();
}
}
PickingUp = false;
if (hit.transform)
{
interactiveObjects = hit.transform.GetComponent<InteractiveObjects>();
}
else
{
lookObject = null;
interactiveObjects = null;
}
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
Open = false;
}
public void OnPickingUp()
{
PickingUp = true;
}
public void OnOpen()
{
Open = true;
}
This part from above:
if (Open)
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
was like this:
if (Input.GetKeyDown(KeyCode.E))
{
if (interactiveObjects)
{
interactiveObjects.PerformAction();
}
}
and the InteractiveObject class was something like this:
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Input.GetKeyDown(KeyCode.E))
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
if(Input.GetKeyDown(KeyCode.E)) was changed to if (Open).
Here is the full IneractiveObject class after the change:
public class InteractiveObjects : MonoBehaviour
{
[SerializeField] private Vector3 openPosition, closedPosition;
[SerializeField] private float animationTime;
[SerializeField] private bool isOpen = false;
[SerializeField] private MovementType movementType;
bool Open;
private enum MovementType { Slide, Rotate };
private Hashtable iTweenArgs;
private AudioSource aSource;
void Start()
{
iTweenArgs = iTween.Hash();
iTweenArgs.Add("position", openPosition);
iTweenArgs.Add("time", animationTime);
iTweenArgs.Add("islocal", true);
aSource = GetComponent<AudioSource>();
}
public void PerformAction()
{
if (aSource)
{
aSource.Play();
}
if (Open)
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch (movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
Open = false;
}
public void OnOpen()
{
Open = true;
}
}
Here is my Input Action:
InputManager class:
public class InputManager : MonoBehaviour
{
[SerializeField] Movement movement;
[SerializeField] PlayerInteractions playerInteractions;
[SerializeField] MouseLook mouseLook;
PlayerControls controls;
PlayerControls.GroundMovementActions groundMovement;
Vector2 horizontalInput;
Vector2 mouseInput;
private void Awake()
{
controls = new PlayerControls();
groundMovement = controls.GroundMovement;
// groundMovement.[action].performed += context => do something
groundMovement.HorizontalMovement.performed += ctx => horizontalInput = ctx.ReadValue<Vector2>();
groundMovement.Jump.performed += _ => movement.OnJumpPressed();
groundMovement.Running.performed += _ => movement.OnRunning();
groundMovement.PickingUp.performed += _ => playerInteractions.OnPickingUp();
groundMovement.MouseX.performed += ctx => mouseInput.x = ctx.ReadValue<float>();
groundMovement.MouseY.performed += ctx => mouseInput.y = ctx.ReadValue<float>();
groundMovement.Open.performed += _ => playerInteractions.OnOpen();
}
private void Update()
{
movement.ReceiveInput(horizontalInput);
mouseLook.ReceiveInput(mouseInput);
}
private void OnEnable()
{
controls.Enable();
}
private void OnDestroy()
{
controls.Disable();
}
}
So the InputManager class is calling a function from playerInteractions which is also calling a function from InteractiveObjects for opening/closing feature. that didn't work for me but I don't know how to fix this. please help.
The solution is here, you no longer need Open Boolean and you can call the function directly through the new input system. for this job; Enter only the contents of if on OnOpen.
public void OnOpen()
{
if (isOpen)
{
iTweenArgs["position"] = closedPosition;
iTweenArgs["rotation"] = closedPosition;
}
else
{
iTweenArgs["position"] = openPosition;
iTweenArgs["rotation"] = openPosition;
}
isOpen = !isOpen;
switch(movementType)
{
case MovementType.Slide:
iTween.MoveTo(gameObject, iTweenArgs);
break;
case MovementType.Rotate:
iTween.RotateTo(gameObject, iTweenArgs);
break;
}
}
This not only simplifies the structure of the code. Rather, it prevents the if condition from being repeated in the update. Now run OnOpen as you set it by pressing the B key:
controls.GroundMovement.Open.performed += _ => playerInteraction.OnOpen();
How do conditions work continuously?
There are several ways to build functions that work continuously. This is an example that works by defining Func<bool> in the target object script:
public class PlayerInteraction : MonoBehaviour
{
public Func<bool> IsPressingOpen;
public void Update()
{
if (IsPressingOpen())
{
// do something...
}
}
}
And it is enough to set the function according to the result of key pressing:
playerInteraction.IsPressingOpen = () => controls.GroundMovement.Open.IsPressed();
Hope this answer is comprehensive and practical.
There is a problem on my project that when it plays the video play automatically. How I want to make the video play and pause in Unity. I'm using Unity 2019.3.5f1 and Vuforia. Is there any tutorial about how to make video playback AR can play and pause?
I try this code but it doesn't work. I don't know why?
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Vuforia;
using UnityEngine.Video;
public class PlayControl : MonoBehaviour, ITrackableEventHandler
{
public GameObject videoplayer, Playvideo_button, Pausevideo_button, Stopvideo_button;
protected TrackableBehaviour mTrackableBehaviour;
public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus, TrackableBehaviour.Status newStatus)
{
if (newStatus == TrackableBehaviour.Status.DETECTED ||
newStatus == TrackableBehaviour.Status.TRACKED ||
newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " found");
if (mTrackableBehaviour.TrackableName == "Video_marker")
{
videoplayer.GetComponent<VideoPlayer>().Play();
}
OnTrackingFound();
}
else if (previousStatus == TrackableBehaviour.Status.TRACKED &&
newStatus == TrackableBehaviour.Status.NO_POSE)
{
Debug.Log("Trackable " + mTrackableBehaviour.TrackableName + " lost");
videoplayer.GetComponent<VideoPlayer>().Stop();
OnTrackingLost();
}
else
{
// For combo of previousStatus=UNKNOWN + newStatus=UNKNOWN|NOT_FOUND
// Vuforia is starting, but tracking has not been lost or found yet
// Call OnTrackingLost() to hide the augmentations
OnTrackingLost();
}
}
// Start is called before the first frame update
void Start()
{
mTrackableBehaviour = GetComponent<TrackableBehaviour>();
if(mTrackableBehaviour)
{
mTrackableBehaviour.RegisterTrackableEventHandler(this);
}
}
protected virtual void OnTrackingFound()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Enable rendering:
foreach (var component in rendererComponents)
component.enabled = true;
// Enable colliders:
foreach (var component in colliderComponents)
component.enabled = true;
// Enable canvas':
foreach (var component in canvasComponents)
component.enabled = true;
}
protected virtual void OnTrackingLost()
{
var rendererComponents = GetComponentsInChildren<Renderer>(true);
var colliderComponents = GetComponentsInChildren<Collider>(true);
var canvasComponents = GetComponentsInChildren<Canvas>(true);
// Disable rendering:
foreach (var component in rendererComponents)
component.enabled = false;
// Disable colliders:
foreach (var component in colliderComponents)
component.enabled = false;
// Disable canvas':
foreach (var component in canvasComponents)
component.enabled = false;
}
// Update is called once per frame
void Update()
{
if (Input.GetMouseButtonDown(0))
{
Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
RaycastHit hit;
if (Physics.Raycast(ray, out hit))
{
//case 1
if (hit.collider.tag == "Playvideo")
{
videoplayer.GetComponent<VideoPlayer>().Play();
Playvideo_button.SetActive(false);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(true);
}
//case 2
if (hit.collider.tag == "Stopvideo")
{
videoplayer.GetComponent<VideoPlayer>().Stop();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(false);
}
//case 3
if (hit.collider.tag == "Pausevideo")
{
videoplayer.GetComponent<VideoPlayer>().Pause();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(false);
Stopvideo_button.SetActive(true);
}
}
}
}
}
It's not really clear where does this script runs in your project. The best way to make sure your hits are in the right place is to add the script to the buttons, which I see that you didn't. Did you make sure your Raycast reaches the right button? you can define a maxDistance to your Physics.Raycast that may be a great help here. Also in your "if" statements, I would check if there is a collision first and then check for the tag, something like this:
if (Physics.Raycast(ray, out hit, 900.0f))
{
if (hit.transform != null)
{
if (GameObject.ReferenceEquals(hit.transform.gameObject, playButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Play();
Playvideo_button.SetActive(false);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(true);
}
else if (GameObject.ReferenceEquals(hit.transform.gameObject, stopButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Stop();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(true);
Stopvideo_button.SetActive(false);
}
else if (GameObject.ReferenceEquals(hit.transform.gameObject, pauseButtonGameObject))
{
videoplayer.GetComponent<VideoPlayer>().Pause();
Playvideo_button.SetActive(true);
Pausevideo_button.SetActive(false);
Stopvideo_button.SetActive(true);
}
}
}
i have a piano app in unity and i am using an ArrayList to add notes and then playing it back and it workes mostly but the playback method since it activates when playMode is true, it continues on a loop, i need to know how i can use an if statement to check if all the recorded notes have been played and if they have then the loop should break. i really need help.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class NotePlay: MonoBehaviour
{
public Button record, play;
public bool recordMode = false;
public bool playMode = false;
Animator anim;
public AudioClip noteA;
public AudioClip noteB;
public AudioClip noteC;
public AudioClip noteD;
public AudioClip noteE;
public AudioClip noteF;
public AudioClip noteG;
public AudioSource audio;
public int count = 0;
// Use this for initialization
public ArrayList notes;
void Start()
{
anim = gameObject.GetComponent<Animator>();
audio = GetComponent<AudioSource>();
notes = new ArrayList();
Button rec = record.GetComponent<Button>();
Button pl = play.GetComponent<Button>();
record.onClick.AddListener(()=>{ recordMode = !recordMode; });
play.onClick.AddListener(() => { playMode = !playMode; recordMode =
false; });
}
void Playback()
{
bool flag = true;
for (int i = 0; i < notes.Count && flag; i++)
{
char c = (char)notes[i];
System.Threading.Thread.Sleep(1000);
PlayNote(c);
print(c);
// i want the recorded notes to only play once
if ()
{
}
}
}
void PlayNote(char note)
{
if (note == 'a')
{
//anim.SetTrigger("A");
GameObject.Find("Sphere_A").GetComponent<AudioSource>
().PlayOneShot(noteA);
GameObject.Find("Sphere_A").GetComponent<Animator>
().SetTrigger("A");
print("a");
}
if (note == 'b')
{
//anim.SetTrigger("B");
GameObject.Find("Sphere_B").GetComponent<AudioSource>
().PlayOneShot(noteB);
GameObject.Find("Sphere_B").GetComponent<Animator>
().SetTrigger("B");
print("b");
}
if (note == 'c')
{
///anim.SetTrigger("C");
GameObject.Find("Sphere_C").GetComponent<AudioSource>
().PlayOneShot(noteC);
GameObject.Find("Sphere_C").GetComponent<Animator>
().SetTrigger("C");
}
if (note == 'd')
{
//anim.SetTrigger("D");
GameObject.Find("Sphere_D").GetComponent<AudioSource>
().PlayOneShot(noteD);
GameObject.Find("Sphere_D").GetComponent<Animator>
().SetTrigger("D");
}
if (note == 'e')
{
//anim.SetTrigger("E");
GameObject.Find("Sphere_E").GetComponent<AudioSource>
().PlayOneShot(noteE);
GameObject.Find("Sphere_E").GetComponent<Animator>
().SetTrigger("E");
}
else if (note == 'f')
{
// anim.SetTrigger("F");
GameObject.Find("Sphere_F").GetComponent<AudioSource>
().PlayOneShot(noteF);
GameObject.Find("Sphere_F").GetComponent<Animator>
().SetTrigger("F");
}
else if (note == 'g')
{
//anim.SetTrigger("G");
GameObject.Find("Sphere_G").GetComponent<AudioSource>
().PlayOneShot(noteG);
GameObject.Find("Sphere_G").GetComponent<Animator>
().SetTrigger("G");
}
}
// Update is called once per frame
void Update()
{
if (recordMode == true)
{
if (Input.GetKeyDown(KeyCode.A)) {notes.Add('a'); PlayNote('a'); }
if (Input.GetKeyDown(KeyCode.B)) {notes.Add('b'); PlayNote('b'); }
if (Input.GetKeyDown(KeyCode.C)) {notes.Add('c'); PlayNote('c'); }
if (Input.GetKeyDown(KeyCode.D)) {notes.Add('d'); PlayNote('d'); }
if (Input.GetKeyDown(KeyCode.E)) {notes.Add('e'); PlayNote('e'); }
if (Input.GetKeyDown(KeyCode.F)) {notes.Add('f'); PlayNote('f'); }
if (Input.GetKeyDown(KeyCode.G)) {notes.Add('g'); PlayNote('g'); }
}
else
{
if (Input.GetKeyDown(KeyCode.A)) { PlayNote('a'); }
if (Input.GetKeyDown(KeyCode.B)) { PlayNote('b'); }
if (Input.GetKeyDown(KeyCode.C)) { PlayNote('c'); }
if (Input.GetKeyDown(KeyCode.D)) { PlayNote('d'); }
if (Input.GetKeyDown(KeyCode.E)) { PlayNote('e'); }
if (Input.GetKeyDown(KeyCode.F)) { PlayNote('f'); }
if (Input.GetKeyDown(KeyCode.G)) { PlayNote('g'); }
}
if (playMode == true )
{
Playback();
}
}
}
You may want to specify that the AudioSource don't have to loop the sound. Add this line to your Start method :
void Start()
{
anim = gameObject.GetComponent<Animator>();
audio = GetComponent<AudioSource>();
audio.loop = false; // <--------------- HERE
notes = new ArrayList();
Button rec = record.GetComponent<Button>();
Button pl = play.GetComponent<Button>();
record.onClick.AddListener(()=>{ recordMode = !recordMode; });
play.onClick.AddListener(() => { playMode = !playMode; recordMode = false; });
}
You can either do this in code as above or directly in the inspector of your AudioSource. I think the default value of the loop property is set to true, that's why it's looping when you play a note.
I am making a simple drag and drop unity game. When I drag the object for the first time it does not give score but when I drag it once again it gives score even if I am dropping at the wrong place. I am using tag to match desired objects
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using System;
public class sh_score : MonoBehaviour {
static int score = 0;
public Text scoreText;
public GameObject ans_circle;
public GameObject tag_circle;
public GameObject tag_rectangle;
public GameObject ans_rectangle;
public GameObject ans_triangle;
public GameObject tag_triangle;
public GameObject ans_square;
public GameObject tag_square;
public GameObject ans_star;
public GameObject tag_star;
void Start()
{
score = score;
if( (ans_circle == null || tag_circle == null) || (ans_rectangle == null || tag_rectangle == null)|| (ans_square == null || tag_square == null) || (ans_triangle == null || tag_triangle == null)|| (ans_star == null || tag_star == null))
{
ans_circle = GameObject.FindGameObjectWithTag("ans_circle");
if (ans_circle != null)
{ Debug.Log("ans Find"); }
tag_circle = GameObject.FindGameObjectWithTag("circle");
if (tag_circle != null)
{
Debug.Log("circle");
}
checkTagPlace();
ans_rectangle = GameObject.FindGameObjectWithTag("ans_rectangle");
if (ans_rectangle != null)
{ Debug.Log("ans Find"); }
tag_rectangle = GameObject.FindGameObjectWithTag("rectangle");
if (tag_circle != null)
{
Debug.Log("rectangle");
}
ans_triangle = GameObject.FindGameObjectWithTag("ans_triangle");
if (ans_triangle != null)
{ Debug.Log("ans Find"); }
tag_triangle = GameObject.FindGameObjectWithTag("triangle");
if (tag_triangle != null)
{
Debug.Log("triangle");
}
ans_star = GameObject.FindGameObjectWithTag("ans_star");
if (ans_star != null)
{ Debug.Log("ans Find"); }
tag_star = GameObject.FindGameObjectWithTag("star");
if (tag_star != null)
{
Debug.Log("star");
}
ans_square = GameObject.FindGameObjectWithTag("ans_square");
if (ans_square != null)
{ Debug.Log("ans Find"); }
tag_square = GameObject.FindGameObjectWithTag("square");
if (tag_square != null)
{
Debug.Log("square");
}
}
}
void update()
{
scoreText.text = score.ToString();
}
public void IncrementScore()
{
score = score + 9;
score++;
scoreText.text = "Score: " + score;
}
public void checkTagPlace()
{
Debug.Log("check function run");
float circle_postion = tag_circle.transform.position.x;
float circle_Tag_positon = ans_circle.transform.position.x;
float triangle_position = tag_triangle.transform.position.x;
float triangle_Tag_positon = ans_triangle.transform.position.x;
float square_postion = tag_square.transform.position.x;
float square_Tag_positon = ans_square.transform.position.x;
float star_postion = tag_star.transform.position.x;
float star_Tag_positon = ans_star.transform.position.x;
float rectangle_position = tag_rectangle.transform.position.x;
float rectangle_Tag_positon = ans_rectangle.transform.position.x;
if ((ans_circle.transform.position.x == tag_circle.transform.position.x))
{
Debug.Log("found position");
IncrementScore();
}
else if ((ans_rectangle.transform.position.x == tag_rectangle.transform.position.x))
{
IncrementScore();
}
else if ((ans_square.transform.position.x == tag_square.transform.position.x))
{
IncrementScore();
}
else if (ans_triangle.transform.position.x == tag_triangle.transform.position.x)
{
IncrementScore();
}
else if (ans_star.transform.position.x == tag_star.transform.position.x)
{
IncrementScore();
}
}
}
I cannot post comments yet but
You are calling checkTagPlace before having set all of your attributes it may be the cause of the bug.
Searching gameObjects with tags this way may be a problem in the future if you have several objects with the same tag
Usually to do what you want to do you want to use Colliders on your GameObject and the OnCollisionEnter/OnCollisionStay/OnTriggerEnter/OnTriggerStay functions (do not forget the upper case). Then you will be able to check if the "collisioned" GameObject have the correct tag.
I believe your problem might be here:
if(ans_rectangle.transform.position.x == tag_rectangle.transform.position.x)
When you check to see if these positions (and the other if statements like this one) are equal, you are checking if they're exactly equal. Unless you have some controller which is discretizing the movements of your shapes, thats almost never going to happen.
I believe what you want is really something like this:
float epsilon=.001;
if(Math.abs(ans_rectangle.transform.position.x - tag_rectangle.transform.position.x)<epsilon)
Alternatively, you can give colliders to all of your shapes and actually check for collisions between the two shape types, perhaps using layer masks to keep from comparing shapes of dissimilar types.
I understand that this doesn't explain all the behavior you're seeing, but it might explain why it doesn't increment your score the first time.
Since you don't include the code which is enabling the dragging, we can't know if that is the problem or not.
I want to gain 10 points when the player kill an enemy but I don't get it. I've created a method to add score on my PuntosPistas script in the Player, and just call the method inside of the CheckHealth of the Enemy but it don't sum 10 points in score. Can anybody help me? This is my code:
In the Enemy:
public class v_AIMotor : vCharacter
{
GameObject Player;
void Start ()
{
Player = GameObject.FindGameObjectWithTag("Player");
}
public void CheckHealth()
{
if (currentHealth <= 0 && !isDead)
{
isDead = true;
Player.GetComponent<PuntosPistas>().KillEnemy ();
print("10 points”);
DisableActions();
}
}
}
In the Player:
public class PuntosPistas : MonoBehaviour
{
public int Score;
public Text TextoContador;
void Start ()
{
Score = PlayerPrefs.GetInt("Score");
TextoContador.text = "" + Score;
}
public void KillEnemy()
{
Score = Score + 10;
TextoContador.text = "" + Score;
PlayerPrefs.SetInt("Score",Score);
}
}
Sorry! This is the full code where I call CheckHealth():
#region AI Health
GameObject Player;
void Start ()
{
Player = GameObject.FindGameObjectWithTag("Player");
}
public void CheckHealth()
{
if (currentHealth <= 0 && !isDead)
{
isDead = true;
Player.GetComponent<PuntosPistas> ().KillEnemy ();
DisableActions();
}
}
public void HealthRecovery()
{
if (currentHealth <= 0) return;
if (currentHealthRecoveryDelay > 0)
{
currentHealthRecoveryDelay -= Time.deltaTime;
}
else
{
if (currentHealth > maxHealth)
currentHealth = maxHealth;
if (currentHealth < maxHealth)
currentHealth = Mathf.Lerp(currentHealth, maxHealth, healthRecovery * Time.deltaTime);
}
}
protected void RemoveComponents()
{
if (_capsuleCollider != null) Destroy(_capsuleCollider);
if (_rigidbody != null) Destroy(_rigidbody);
if (animator != null) Destroy(animator);
if (agent != null) Destroy(agent);
var comps = GetComponents<MonoBehaviour>();
foreach (Component comp in comps) Destroy(comp);
}
public override void TakeDamage(Damage damage)
{
if (rolling || currentHealth <= 0) return;
if (canSeeTarget() && !damage.ignoreDefense && !actions && CheckChanceToRoll()) return;
// change to block an attack
StartCoroutine(CheckChanceToBlock(chanceToBlockAttack, 0));
// defend attack behaviour
if (canSeeTarget() && BlockAttack(damage)) return;
// instantiate hit particle
var hitRotation = Quaternion.LookRotation(new Vector3(transform.position.x, damage.hitPosition.y, transform.position.z) - damage.hitPosition);
SendMessage("TriggerHitParticle", new HittEffectInfo(new Vector3(transform.position.x, damage.hitPosition.y, transform.position.z), hitRotation, damage.attackName), SendMessageOptions.DontRequireReceiver);
// apply damage to the health
currentHealth -= damage.value;
currentHealthRecoveryDelay = healthRecoveryDelay;
// apply tag from the character that hit you and start chase
if (!sphereSensor.passiveToDamage && damage.sender != null)
{
target = damage.sender;
currentState = AIStates.Chase;
sphereSensor.SetTagToDetect(damage.sender);
if (meleeManager != null)
meleeManager.SetTagToDetect(damage.sender);
}
// trigger hit sound
if (damage.sender != null)
damage.sender.SendMessage("PlayHitSound", SendMessageOptions.DontRequireReceiver);
// update the HUD display
if (healthSlider != null)
healthSlider.Damage(damage.value);
// trigger the HitReaction when the AI take the damage
var hitReactionConditions = stepUp || climbUp || jumpOver || quickTurn || rolling;
if (animator != null && animator.enabled && !damage.activeRagdoll && !hitReactionConditions)
{
animator.SetInteger("Recoil_ID", damage.recoil_id);
animator.SetTrigger("HitReaction");
}
// turn the ragdoll on if the weapon is checked with 'activeRagdoll'
if (damage.activeRagdoll)
transform.SendMessage("ActivateRagdoll", SendMessageOptions.DontRequireReceiver);
CheckHealth();
}
#endregion
And this is the error in console:
NullReferenceException: Object reference not set to an instance of an object
Invector.v_AIMotor.CheckHealth () (at Assets/Invector-3rdPersonController/Scripts/CharacterAI/v_AIMotor.cs:504)
Invector.v_AIMotor.TakeDamage (.Damage damage) (at Assets/Invector-3rdPersonController/Scripts/CharacterAI/v_AIMotor.cs:582)
UnityEngine.Component:SendMessage(String, Object, SendMessageOptions)
vMeleeManager:OnDamageHit(HitInfo) (at Assets/Invector-3rdPersonController/Scripts/MeleeCombat/vMeleeManager.cs:295)
UnityEngine.Component:SendMessageUpwards(String, Object, SendMessageOptions)
Invector.vHitBox:CheckHitProperties(Collider) (at Assets/Invector-3rdPersonController/Scripts/MeleeCombat/vHitBox.cs:68)
Invector.vHitBox:OnTriggerEnter(Collider) (at Assets/Invector-3rdPersonController/Scripts/MeleeCombat/vHitBox.cs:48)
please investigate on the way you call CheckHealth(), it's not clear from your code.
That code should be work if you call the method properly, try in this way:
public class v_AIMotor : vCharacter{
GameObject Player;
void Start ()
{
Player = GameObject.FindGameObjectWithTag("Player");
}
public void CheckHealth()
{
if (currentHealth <= 0 && !isDead)
{
isDead = true;
Player.GetComponent<PuntosPistas>().KillEnemy ();
print("10 points”);
DisableActions();
}
}
void Update()
{
CheckHealth();
}
}
void update is not the best way for sure, but should be do the job.