C# - Unity - audio when two objects collide, not working :( - c#

I've got a problem. I am creating a small game project where where a ball escapes from ghosts.
I am trying to write a script that plays "evil laughter" when the ball collides with a ghost.
When i added the audio upon collision code into the script, the other function which gets the player to the "Game over"-scene stops working
Does anyone know what the problem might be?
Thanks a lot in advance! (code below) <3
public class GhostScript : MonoBehaviour
public AudioSource ghostCollision; //this is the collision sound reference
public GameObject target; //this is the player or a reference for him
UnityEngine.AI.NavMeshAgent agent;
// Start is called before the first frame update
void Start()
{
ghostCollision = GetComponent<AudioSource>();
agent = GetComponent<UnityEngine.AI.NavMeshAgent>();
if (target == null) {
target = GameObject.FindGameObjectWithTag("Player");
}
}
// Update is called once per frame
void Update()
{
agent.destination = target.transform.position;
}
public void OnCollisionEnter(Collision collision){
if (collision.gameObject.tag == "Player"){
ghostCollision.Play();
SceneManager.LoadScene("menu");
}
}

That's because as soon as you call SceneManager.LoadScene the current scene (which contains your Player, AI and AudioSource) gets lost and replaced with the new Scene. Adding a delay to the scene load should do the trick, you can use Invoke for that (or Coroutines if you're more advanced).
private void OnCollisionEnter(Collision other)
{
if (other.gameObject.tag == "Player")
{
ghostCollision.Play();
// Invokes the function after the AudioClip is over
Invoke("LoadScene", ghostCollision.clip.length);
}
}
private void LoadScene()
{
SceneManager.LoadScene("your-scene-name");
}

Related

OnCollisionEnter does not work upon initial collision - Unity 3D

I am a beginner in Unity and I am currently making a simple game. I have a problem where upon initial collision, the event that I wanted to happen does not trigger or in other words the OnCollisionEnter is not working upon initial collision.
The process of my script is when colliding which is the OnCollisionEnter the button will appear or it will be set active to true. But in the first collision it does not trigger or it is not working, I need to walk away a bit and go back in that way it only works. Sometimes I need to do it 2 or more times for the collider to trigger. I don't know if the script has problem or the collider itself but I made sure it is colliding properly when I look at the editor.
I set the object to static so it will not be pushed when walking and colliding towards it. I wonder if that has to do with this problem because even disabled it is the same. But can anyone give suggestions on how not to make the objects move or be pushed away upon collision?
Here is the script for my collision:
using UnityEngine;
using UnityEngine.UI;
public class InteractNPC : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse, nameBtn;
private Transform head;
private Vector3 offset = new Vector3(0, 1.0f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
uiUse.gameObject.SetActive(true);
head = transform.GetChild(0);
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
nameBtn.transform.position = Camera.main.WorldToScreenPoint(head.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
//Debug.Log("wews2");
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
nameBtn.gameObject.SetActive(false);
}
}
}
Here is another script with collision and has the same problem:
using UnityEngine;
using UnityEngine.UI;
public class InteractButtonPosition : MonoBehaviour
{
//public Button UI;
[SerializeField] GameObject uiUse;
private Vector3 offset = new Vector3(0, 0.5f, 0);
// Start is called before the first frame update
void Start()
{
//uiUse = Instantiate(UI, FindObjectOfType<Canvas>().transform).GetComponent<Button>();
//uiUse = GameObject.FindGameObjectWithTag("ViewButton");
}
// Update is called once per frame
void Update()
{
uiUse.transform.position = Camera.main.WorldToScreenPoint(this.transform.position + offset);
}
private void OnCollisionEnter(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
Debug.Log("wews");
uiUse.gameObject.SetActive(true);
}
}
private void OnCollisionExit(Collision collisionInfo)
{
if(collisionInfo.collider.name == "Player")
{
//Destroy(uiUse.gameObject);
uiUse.gameObject.SetActive(false);
}
}
}
Try changing Colision detection from Descrete to Continuous
collission detection
I solved this issue by using OntriggerEnter instead of OnCollisionEnter. In the editor, for the NPC I put a Collider on each part of the body and check the IsTrigger in the parent Object so it will still collide with my character even if the IsTrigger is enabled that will make the character go through the object. I just enlarged the scale of the collider with IsTrigger enabled so the collision will be detected immediately.

Unity gameObject without a script is reaching a collision method

So I am taking a class in basic game development and am currently working on a game with Unity. My game worked perfectly up until now when I updated my unity version. In order for the player to actually take damage I have a method that can only be reached if explicitly called by a script. Somehow the ground, that has no script attached, damages my player.
I have posted the code below.
This one is part of the player script
3 references
public void Hurt(int dmg, string yep)
{
HP -= dmg;
Debug.Log($"took {dmg} damage from{yep}. You now have {HP} HP left");
if (HP <= 0)
{
SceneManagement.Death();
}
}
This one is part of the script attatched to my flame object
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag != "FlameTurret" && collision.gameObject.tag != "flame")
{
player.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
Destroy(this.gameObject);
}
}
This one is attatched to a projectile fired by the enemy
if (collision.gameObject.CompareTag("Player"))
{
if (!called)
{
collision.gameObject.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
called = true;
}
}
This one is attatched to an enemy
if (collision.gameObject.CompareTag("Player"))
{
if (!called)
{
collision.gameObject.GetComponent<PlayerController>().Hurt(damage, collision.gameObject.tag);
called = true;
}
Destroy(this.gameObject);
}
Console output
Nothing with the tag "Ground" has a script and nothing else than the methods i've posted are supposed to reference my Hurt() method but the ground still damages my player. Any help would be greatly appreciated!
Your problem seems to be that this function here
private void OnCollisionEnter2D(Collision2D collision)
Will be run whenever any collider (game object with a collider component attached - the game object does not need to have any scripts attached to it) intersects with your player
This code here
if (collision.gameObject.tag != "FlameTurret" && collision.gameObject.tag != "flame")
Will pass so long as the object that collides does not have the tag of "FlameTurret" or "flame", which I assume your ground does not.
It seems to me a little odd that everything in your game will damage your player except for flames... is this an error?
Either way a simple fix would be to tag your ground with something like environment and then add under your OnCollisionEnter2D() have a check along the lines of
if (collision.gameObject.tag == "environment"){
return; // do nothing
}

Animator Trigger Not firing on having error "parameter does not exist"

I am new to unity so i am unable to figure out this , I have dolphin in my game when it collides it dies so it has two animations one is its moving changes to dead body and second animation is bubbles which are dolphin's child object , the second trigger it fires is to stop bubbles , the first trigger is working that is its moving body changes to dead body , but the second trigger doesn't work that is its bubbles are still coming out, i dot know whats wrong.
public class Dolphin : MonoBehaviour
{
private bool IsDead=false;
private Rigidbody2D rb2d;
public float upforce = 200f;
private Animator anim;
// Use this for initialization
void Start ()
{
rb2d = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
}
// Update is called once per frame
void Update ()
{
if (IsDead == false)
{
if (Input.GetMouseButtonDown(0))
{
rb2d.velocity = Vector2.zero;
rb2d.AddForce(new Vector2(0, upforce));
}
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
IsDead = true;
anim.SetTrigger("Die");
anim.SetTrigger("StopBubble");
Debug.Log("rigger");
}
}
You should set the second trigger to your bubble game object Animator (Not to Dolphin Animator)
Only change your script to this:
private void OnCollisionEnter2D(Collision2D collision)
{
IsDead = true;
anim.SetTrigger("Die");
transform.GetChild(0).GetComponent<Animator>().SetTrigger("StopBubble");
Debug.Log("rigger");
}
(Note: Your bubble game object is the first child of dolphin game object. By using transform.GetChild(0) you can access to it)
I hope it helps you

Despite Force Applied, No Movement

This code is for an elevator-type platform, where once the player stands on it, it 'takes' the player up by adding force onto it.
The thing is, while the force is created, the rigidbody (the player) does not move when the elevator moves. The code was written in C#, using Unity 5. In the code, the player is assigned the public 'rb', and contains a rigidbody.
The animation is a simple animation clip that moves the elevator up. Any ideas? Thank you for your time and answers in advance.
The elevator is Kinematic, the Player is not.
using UnityEngine;
using System.Collections;
/*This script activates when the player steps on the elevator, as it takes them up a floor.*/
public class ElevatorMovementScript : MonoBehaviour
{
private bool elevatorUp = false;
public Animation anim;
public int elevatorDelay = 5;
public int force = 800;
public Rigidbody rb;
// Use this for initialization
void Start ()
{
anim = GetComponent<Animation>();
}
// Update is called once per frame
void Update ()
{
}
/*Checks if the player has stepped onto the elevator. If the player has, it waits five seconds, and then pushes the player up.*/
void OnTriggerStay(Collider other)
{
if (other.gameObject.tag == "Player" && !elevatorUp)
{
Invoke("AnimationPlay",elevatorDelay);
elevatorUp = true;
}
}
/*Plays the animation of the player going up. Used for the 'Invoke' method.*/
void AnimationPlay()
{
rb.AddForce(transform.up * force);
Debug.Log (transform.up * force);
anim.Play ("Up");
}
}
It looks like this script is on your elevator's game object, in which case this line:
rb.AddForce(transform.up * force);
Will try to apply a force to the elevator, not the player. You've got to keep track of the player's rigidbody or somehow get it on demand in AnimationPlay.
You said that
the player is assigned the public 'rb'
But rb = GetComponent<Rigidbody>(); will ignore this and use the rigidbody attached to the gameobject that ElevatorMovementScript is attached to.

unity OnTriggerStay2D() for two triggers

I am using unity 5 c# and I have a gameobject with 2 trigger colliders one of them is in a different location.
I need to be able to use OnTriggerStay2D and OnTriggerEnter2D for them but I need to find what trigger is being entered. Right now if I enter the 1st(polygon) trigger the OnTriggerEnter activates for the 2nd(box).
How can I Tell the two colliders apart???
public void OnTriggerEnter2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = true; //if the player is in shooting range
Idle = false;
}
}
public void OnTriggerStay2D(Collider2D other) //1st collider trigger
{
if (Found != true) {
if (other.tag == "Player") {
Shield = true;
Idle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other) //2nd collider trigger
{
if (other.tag == "Player") {
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
}
I have tried making the 1st trigger public void OnTriggerStay2D(PolygonCollider2D other) but it says "This message parameter has to be of type: Collider2D
The message will be ignored."
What I am trying to do is have a polygon trigger in front of the gameobject and a different box trigger closer to the gameobject so when you go near the gameobject you enter the 1st trigger and it puts its shield up but when you get close to it (within shooting range of it) it will put its shield down and start shooting you.
Well collider2d detects all types of 2d colliders. It doesn't matter if it's polygon or just a box. As the documentation suggestions it doesn't need to be public or private. It only takes a collider2d as it's argument however.
For debugging purposes why not use print?
Print("you've entered the trigger function");
Also I wouldn't use 2 different trigger colliders on the same GameObject. Why not just make 2 separate gameobjects so you can have more thorough detection. Each GameObject with its own trigger collider can have different tags.
If you have to use 2 trigger colliders on one object. Which isn't the best idea. You could use shapeCount to determine which one it's hitting. Although like I said I would warrant against doing 2 trigger colliders on the same object when whatever you're trying to do can be easier on two separate objects.
However links aren't usually prohibited I think. I would watch and study these videos. They're very useful for explaining the engine and they really aren't even that long.
https://unity3d.com/learn/tutorials/modules/beginner/2d
They even have a video explaining 2d colliders.
This is my fix. In one of my games I have a boulder, I have a trigger which will delete a block below it so it falls, I then have another trigger which tells the boulder to start moving left or right I then also have another trigger which will delete the boulder once the boulder comes in contact.
So what you can do is create 2 new game objects, create a new CS file and name them appropriately, then with those two new classes allow them to take in the gameobject you are referring to in your question.
Then when they are triggered you can use code from their class.
So your first class would become something like this
public void OnTriggerEnter2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Found = true; //if the player is in shooting range
Enemy.Idle = false;
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then the other class would be something like this
public void OnTriggerStay2D(Collider2D other)
{
if (Enemy.Found != true) {
if (other.tag == "Player") {
Enemy.Shield = true;
IEnemy.dle = false;
}
}
}
public void OnTriggerExit2D(Collider2D other)
{
if (other.tag == "Player") {
Enemy.Exit2DTrigger();
}
}
Then in your Enemy class you would have
public void Exit2DTrigger()
{
Found = false;
Shield = false;
Shooting = false;
Idle = true;
}
P.S. also don't you need to use other.gameObject.tag == "Player" ?

Categories

Resources